{"action":"created","comment":{"url":"https://api.github.com/repos/coveo/spillway/pulls/comments/87028820","pull_request_review_id":7657638,"id":87028820,"diff_hunk":"@@ -0,0 +1,96 @@\n+/**\n+ * The MIT License\n+ * Copyright (c) 2016 Coveo\n+ *\n+ * Permission is hereby granted, free of charge, to any person obtaining a copy\n+ * of this software and associated documentation files (the \"Software\"), to deal\n+ * in the Software without restriction, including without limitation the rights\n+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n+ * copies of the Software, and to permit persons to whom the Software is\n+ * furnished to do so, subject to the following conditions:\n+ *\n+ * The above copyright notice and this permission notice shall be included in\n+ * all copies or substantial portions of the Software.\n+ *\n+ * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n+ * THE SOFTWARE.\n+ */\n+package com.coveo.spillway.storage.utils;\n+\n+import java.time.Duration;\n+import java.time.Instant;\n+import java.util.TimerTask;\n+\n+import org.apache.commons.lang3.tuple.Pair;\n+import org.slf4j.Logger;\n+import org.slf4j.LoggerFactory;\n+\n+import com.coveo.spillway.limit.LimitKey;\n+import com.coveo.spillway.storage.AsyncBatchLimitUsageStorage;\n+import com.coveo.spillway.storage.InMemoryStorage;\n+import com.coveo.spillway.storage.LimitUsageStorage;\n+\n+/**\n+ * Synchronization {@link TimerTask} that is launched periodically\n+ * by the {@link AsyncBatchLimitUsageStorage}.\n+ *\n+ * @author Emile Fugulin\n+ * @since 1.0.0\n+ */\n+public class CacheSynchronisation extends TimerTask {\n+  private static final Logger logger = LoggerFactory.getLogger(CacheSynchronisation.class);\n+\n+  private InMemoryStorage cache;\n+  private LimitUsageStorage storage;\n+\n+  public CacheSynchronisation(InMemoryStorage cache, LimitUsageStorage storage) {\n+    this.cache = cache;\n+    this.storage = storage;\n+  }\n+\n+  @Override\n+  public void run() {\n+    cache.applyOnEach(\n+        (instantEntry) -> {\n+          try {\n+            Instant expiration = instantEntry.getKey();\n+\n+            instantEntry\n+                .getValue()\n+                .entrySet()\n+                .forEach(\n+                    valueEntry -> {\n+                      int cost = valueEntry.getValue().getDelta();\n+\n+                      LimitKey limitKey = valueEntry.getKey();\n+\n+                      Duration duration =\n+                          Duration.ofMillis(\n+                              expiration.toEpochMilli() - limitKey.getBucket().toEpochMilli());\n+\n+                      AddAndGetRequest request =\n+                          new AddAndGetRequest.Builder()\n+                              .withResource(limitKey.getResource())\n+                              .withLimitName(limitKey.getLimitName())\n+                              .withProperty(limitKey.getProperty())\n+                              .withExpiration(duration)\n+                              .withEventTimestamp(limitKey.getBucket())\n+                              .withCost(cost)\n+                              .build();\n+\n+                      Pair<LimitKey, Integer> reponse = storage.addAndGet(request);","path":"src/main/java/com/coveo/spillway/storage/utils/CacheSynchronisation.java","position":null,"original_position":86,"commit_id":"0395008a1fa9b592752e787445ba88e526a54451","original_commit_id":"e665587ef70e6726c5a8dae025ace716779d1def","user":{"login":"francistb","id":757840,"avatar_url":"https://avatars.githubusercontent.com/u/757840?v=3","gravatar_id":"","url":"https://api.github.com/users/francistb","html_url":"https://github.com/francistb","followers_url":"https://api.github.com/users/francistb/followers","following_url":"https://api.github.com/users/francistb/following{/other_user}","gists_url":"https://api.github.com/users/francistb/gists{/gist_id}","starred_url":"https://api.github.com/users/francistb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/francistb/subscriptions","organizations_url":"https://api.github.com/users/francistb/orgs","repos_url":"https://api.github.com/users/francistb/repos","events_url":"https://api.github.com/users/francistb/events{/privacy}","received_events_url":"https://api.github.com/users/francistb/received_events","type":"User","site_admin":false},"body":"I suggest to go with that first version for now. It's already a good improvement over the previous version. Further optimizations can be done in a separate issue.","created_at":"2016-11-08T16:36:19Z","updated_at":"2016-11-08T16:36:19Z","html_url":"https://github.com/coveo/spillway/pull/19#discussion_r87028820","pull_request_url":"https://api.github.com/repos/coveo/spillway/pulls/19","_links":{"self":{"href":"https://api.github.com/repos/coveo/spillway/pulls/comments/87028820"},"html":{"href":"https://github.com/coveo/spillway/pull/19#discussion_r87028820"},"pull_request":{"href":"https://api.github.com/repos/coveo/spillway/pulls/19"}}},"pull_request":{"url":"https://api.github.com/repos/coveo/spillway/pulls/19","id":92234936,"html_url":"https://github.com/coveo/spillway/pull/19","diff_url":"https://github.com/coveo/spillway/pull/19.diff","patch_url":"https://github.com/coveo/spillway/pull/19.patch","issue_url":"https://api.github.com/repos/coveo/spillway/issues/19","number":19,"state":"open","locked":false,"title":"Add batch synchronisation","user":{"login":"Sytten","id":2366731,"avatar_url":"https://avatars.githubusercontent.com/u/2366731?v=3","gravatar_id":"","url":"https://api.github.com/users/Sytten","html_url":"https://github.com/Sytten","followers_url":"https://api.github.com/users/Sytten/followers","following_url":"https://api.github.com/users/Sytten/following{/other_user}","gists_url":"https://api.github.com/users/Sytten/gists{/gist_id}","starred_url":"https://api.github.com/users/Sytten/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Sytten/subscriptions","organizations_url":"https://api.github.com/users/Sytten/orgs","repos_url":"https://api.github.com/users/Sytten/repos","events_url":"https://api.github.com/users/Sytten/events{/privacy}","received_events_url":"https://api.github.com/users/Sytten/received_events","type":"User","site_admin":false},"body":"This is a first implementation of a new async storage that sync in batch. Suggestions and critiques are welcome. \r\nThis storage was necessary since we just can't make a query to our database (even async) for each query that arrives, that does not scale.","created_at":"2016-11-03T20:35:28Z","updated_at":"2016-11-08T16:36:19Z","closed_at":null,"merged_at":null,"merge_commit_sha":"7fab7ce92644f6f15c7558907d2a4601577b6788","assignee":{"login":"francistb","id":757840,"avatar_url":"https://avatars.githubusercontent.com/u/757840?v=3","gravatar_id":"","url":"https://api.github.com/users/francistb","html_url":"https://github.com/francistb","followers_url":"https://api.github.com/users/francistb/followers","following_url":"https://api.github.com/users/francistb/following{/other_user}","gists_url":"https://api.github.com/users/francistb/gists{/gist_id}","starred_url":"https://api.github.com/users/francistb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/francistb/subscriptions","organizations_url":"https://api.github.com/users/francistb/orgs","repos_url":"https://api.github.com/users/francistb/repos","events_url":"https://api.github.com/users/francistb/events{/privacy}","received_events_url":"https://api.github.com/users/francistb/received_events","type":"User","site_admin":false},"assignees":[{"login":"francistb","id":757840,"avatar_url":"https://avatars.githubusercontent.com/u/757840?v=3","gravatar_id":"","url":"https://api.github.com/users/francistb","html_url":"https://github.com/francistb","followers_url":"https://api.github.com/users/francistb/followers","following_url":"https://api.github.com/users/francistb/following{/other_user}","gists_url":"https://api.github.com/users/francistb/gists{/gist_id}","starred_url":"https://api.github.com/users/francistb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/francistb/subscriptions","organizations_url":"https://api.github.com/users/francistb/orgs","repos_url":"https://api.github.com/users/francistb/repos","events_url":"https://api.github.com/users/francistb/events{/privacy}","received_events_url":"https://api.github.com/users/francistb/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/coveo/spillway/pulls/19/commits","review_comments_url":"https://api.github.com/repos/coveo/spillway/pulls/19/comments","review_comment_url":"https://api.github.com/repos/coveo/spillway/pulls/comments{/number}","comments_url":"https://api.github.com/repos/coveo/spillway/issues/19/comments","statuses_url":"https://api.github.com/repos/coveo/spillway/statuses/0395008a1fa9b592752e787445ba88e526a54451","head":{"label":"coveo:add-batch-async","ref":"add-batch-async","sha":"0395008a1fa9b592752e787445ba88e526a54451","user":{"login":"coveo","id":8632328,"avatar_url":"https://avatars.githubusercontent.com/u/8632328?v=3","gravatar_id":"","url":"https://api.github.com/users/coveo","html_url":"https://github.com/coveo","followers_url":"https://api.github.com/users/coveo/followers","following_url":"https://api.github.com/users/coveo/following{/other_user}","gists_url":"https://api.github.com/users/coveo/gists{/gist_id}","starred_url":"https://api.github.com/users/coveo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coveo/subscriptions","organizations_url":"https://api.github.com/users/coveo/orgs","repos_url":"https://api.github.com/users/coveo/repos","events_url":"https://api.github.com/users/coveo/events{/privacy}","received_events_url":"https://api.github.com/users/coveo/received_events","type":"Organization","site_admin":false},"repo":{"id":56723673,"name":"spillway","full_name":"coveo/spillway","owner":{"login":"coveo","id":8632328,"avatar_url":"https://avatars.githubusercontent.com/u/8632328?v=3","gravatar_id":"","url":"https://api.github.com/users/coveo","html_url":"https://github.com/coveo","followers_url":"https://api.github.com/users/coveo/followers","following_url":"https://api.github.com/users/coveo/following{/other_user}","gists_url":"https://api.github.com/users/coveo/gists{/gist_id}","starred_url":"https://api.github.com/users/coveo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coveo/subscriptions","organizations_url":"https://api.github.com/users/coveo/orgs","repos_url":"https://api.github.com/users/coveo/repos","events_url":"https://api.github.com/users/coveo/events{/privacy}","received_events_url":"https://api.github.com/users/coveo/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/coveo/spillway","description":"A simple, distributed and flexible rate limiter","fork":false,"url":"https://api.github.com/repos/coveo/spillway","forks_url":"https://api.github.com/repos/coveo/spillway/forks","keys_url":"https://api.github.com/repos/coveo/spillway/keys{/key_id}","collaborators_url":"https://api.github.com/repos/coveo/spillway/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/coveo/spillway/teams","hooks_url":"https://api.github.com/repos/coveo/spillway/hooks","issue_events_url":"https://api.github.com/repos/coveo/spillway/issues/events{/number}","events_url":"https://api.github.com/repos/coveo/spillway/events","assignees_url":"https://api.github.com/repos/coveo/spillway/assignees{/user}","branches_url":"https://api.github.com/repos/coveo/spillway/branches{/branch}","tags_url":"https://api.github.com/repos/coveo/spillway/tags","blobs_url":"https://api.github.com/repos/coveo/spillway/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/coveo/spillway/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/coveo/spillway/git/refs{/sha}","trees_url":"https://api.github.com/repos/coveo/spillway/git/trees{/sha}","statuses_url":"https://api.github.com/repos/coveo/spillway/statuses/{sha}","languages_url":"https://api.github.com/repos/coveo/spillway/languages","stargazers_url":"https://api.github.com/repos/coveo/spillway/stargazers","contributors_url":"https://api.github.com/repos/coveo/spillway/contributors","subscribers_url":"https://api.github.com/repos/coveo/spillway/subscribers","subscription_url":"https://api.github.com/repos/coveo/spillway/subscription","commits_url":"https://api.github.com/repos/coveo/spillway/commits{/sha}","git_commits_url":"https://api.github.com/repos/coveo/spillway/git/commits{/sha}","comments_url":"https://api.github.com/repos/coveo/spillway/comments{/number}","issue_comment_url":"https://api.github.com/repos/coveo/spillway/issues/comments{/number}","contents_url":"https://api.github.com/repos/coveo/spillway/contents/{+path}","compare_url":"https://api.github.com/repos/coveo/spillway/compare/{base}...{head}","merges_url":"https://api.github.com/repos/coveo/spillway/merges","archive_url":"https://api.github.com/repos/coveo/spillway/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/coveo/spillway/downloads","issues_url":"https://api.github.com/repos/coveo/spillway/issues{/number}","pulls_url":"https://api.github.com/repos/coveo/spillway/pulls{/number}","milestones_url":"https://api.github.com/repos/coveo/spillway/milestones{/number}","notifications_url":"https://api.github.com/repos/coveo/spillway/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/coveo/spillway/labels{/name}","releases_url":"https://api.github.com/repos/coveo/spillway/releases{/id}","deployments_url":"https://api.github.com/repos/coveo/spillway/deployments","created_at":"2016-04-20T21:56:55Z","updated_at":"2016-11-03T14:55:40Z","pushed_at":"2016-11-08T16:34:55Z","git_url":"git://github.com/coveo/spillway.git","ssh_url":"git@github.com:coveo/spillway.git","clone_url":"https://github.com/coveo/spillway.git","svn_url":"https://github.com/coveo/spillway","homepage":"","size":265,"stargazers_count":4,"watchers_count":4,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":2,"mirror_url":null,"open_issues_count":8,"forks":2,"open_issues":8,"watchers":4,"default_branch":"master"}},"base":{"label":"coveo:master","ref":"master","sha":"ef5801bc56d1aecec97be333d6e6d4499d020a17","user":{"login":"coveo","id":8632328,"avatar_url":"https://avatars.githubusercontent.com/u/8632328?v=3","gravatar_id":"","url":"https://api.github.com/users/coveo","html_url":"https://github.com/coveo","followers_url":"https://api.github.com/users/coveo/followers","following_url":"https://api.github.com/users/coveo/following{/other_user}","gists_url":"https://api.github.com/users/coveo/gists{/gist_id}","starred_url":"https://api.github.com/users/coveo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coveo/subscriptions","organizations_url":"https://api.github.com/users/coveo/orgs","repos_url":"https://api.github.com/users/coveo/repos","events_url":"https://api.github.com/users/coveo/events{/privacy}","received_events_url":"https://api.github.com/users/coveo/received_events","type":"Organization","site_admin":false},"repo":{"id":56723673,"name":"spillway","full_name":"coveo/spillway","owner":{"login":"coveo","id":8632328,"avatar_url":"https://avatars.githubusercontent.com/u/8632328?v=3","gravatar_id":"","url":"https://api.github.com/users/coveo","html_url":"https://github.com/coveo","followers_url":"https://api.github.com/users/coveo/followers","following_url":"https://api.github.com/users/coveo/following{/other_user}","gists_url":"https://api.github.com/users/coveo/gists{/gist_id}","starred_url":"https://api.github.com/users/coveo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coveo/subscriptions","organizations_url":"https://api.github.com/users/coveo/orgs","repos_url":"https://api.github.com/users/coveo/repos","events_url":"https://api.github.com/users/coveo/events{/privacy}","received_events_url":"https://api.github.com/users/coveo/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/coveo/spillway","description":"A simple, distributed and flexible rate limiter","fork":false,"url":"https://api.github.com/repos/coveo/spillway","forks_url":"https://api.github.com/repos/coveo/spillway/forks","keys_url":"https://api.github.com/repos/coveo/spillway/keys{/key_id}","collaborators_url":"https://api.github.com/repos/coveo/spillway/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/coveo/spillway/teams","hooks_url":"https://api.github.com/repos/coveo/spillway/hooks","issue_events_url":"https://api.github.com/repos/coveo/spillway/issues/events{/number}","events_url":"https://api.github.com/repos/coveo/spillway/events","assignees_url":"https://api.github.com/repos/coveo/spillway/assignees{/user}","branches_url":"https://api.github.com/repos/coveo/spillway/branches{/branch}","tags_url":"https://api.github.com/repos/coveo/spillway/tags","blobs_url":"https://api.github.com/repos/coveo/spillway/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/coveo/spillway/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/coveo/spillway/git/refs{/sha}","trees_url":"https://api.github.com/repos/coveo/spillway/git/trees{/sha}","statuses_url":"https://api.github.com/repos/coveo/spillway/statuses/{sha}","languages_url":"https://api.github.com/repos/coveo/spillway/languages","stargazers_url":"https://api.github.com/repos/coveo/spillway/stargazers","contributors_url":"https://api.github.com/repos/coveo/spillway/contributors","subscribers_url":"https://api.github.com/repos/coveo/spillway/subscribers","subscription_url":"https://api.github.com/repos/coveo/spillway/subscription","commits_url":"https://api.github.com/repos/coveo/spillway/commits{/sha}","git_commits_url":"https://api.github.com/repos/coveo/spillway/git/commits{/sha}","comments_url":"https://api.github.com/repos/coveo/spillway/comments{/number}","issue_comment_url":"https://api.github.com/repos/coveo/spillway/issues/comments{/number}","contents_url":"https://api.github.com/repos/coveo/spillway/contents/{+path}","compare_url":"https://api.github.com/repos/coveo/spillway/compare/{base}...{head}","merges_url":"https://api.github.com/repos/coveo/spillway/merges","archive_url":"https://api.github.com/repos/coveo/spillway/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/coveo/spillway/downloads","issues_url":"https://api.github.com/repos/coveo/spillway/issues{/number}","pulls_url":"https://api.github.com/repos/coveo/spillway/pulls{/number}","milestones_url":"https://api.github.com/repos/coveo/spillway/milestones{/number}","notifications_url":"https://api.github.com/repos/coveo/spillway/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/coveo/spillway/labels{/name}","releases_url":"https://api.github.com/repos/coveo/spillway/releases{/id}","deployments_url":"https://api.github.com/repos/coveo/spillway/deployments","created_at":"2016-04-20T21:56:55Z","updated_at":"2016-11-03T14:55:40Z","pushed_at":"2016-11-08T16:34:55Z","git_url":"git://github.com/coveo/spillway.git","ssh_url":"git@github.com:coveo/spillway.git","clone_url":"https://github.com/coveo/spillway.git","svn_url":"https://github.com/coveo/spillway","homepage":"","size":265,"stargazers_count":4,"watchers_count":4,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":2,"mirror_url":null,"open_issues_count":8,"forks":2,"open_issues":8,"watchers":4,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/coveo/spillway/pulls/19"},"html":{"href":"https://github.com/coveo/spillway/pull/19"},"issue":{"href":"https://api.github.com/repos/coveo/spillway/issues/19"},"comments":{"href":"https://api.github.com/repos/coveo/spillway/issues/19/comments"},"review_comments":{"href":"https://api.github.com/repos/coveo/spillway/pulls/19/comments"},"review_comment":{"href":"https://api.github.com/repos/coveo/spillway/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/coveo/spillway/pulls/19/commits"},"statuses":{"href":"https://api.github.com/repos/coveo/spillway/statuses/0395008a1fa9b592752e787445ba88e526a54451"}}}}
{"actor":{"display_login":"francistb"}}