{"action":"created","comment":{"url":"https://api.github.com/repos/Shopify/semian/pulls/comments/219774890","pull_request_review_id":158026082,"id":219774890,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxOTc3NDg5MA==","diff_hunk":"@@ -0,0 +1,51 @@\n+class LRUCache\n+  extend Forwardable\n+  def_delegators :@table, :size, :count\n+  def_delegators :@table, :empty?\n+  def_delegators :@table, :keys\n+  def_delegators :@table, :clear\n+\n+  attr_accessor :max_items, :table\n+  def initialize(max_items)\n+    @max_items = max_items\n+    @table = {}\n+  end\n+\n+  def set(key, value)\n+    @table.delete(key)\n+    @table[key] = value\n+    clear_unused_resources\n+    # @table.shift if @table.length > @max_items\n+    value\n+  end\n+\n+  def get(key)\n+    if found = @table.delete(key)\n+      @table[key] = found\n+    else\n+      nil\n+    end\n+  end\n+\n+  def []=(key, value)\n+    set(key, value)\n+  end\n+\n+  def [](key)\n+    get(key)\n+  end\n+\n+  def delete(key)\n+    @table.delete(key)\n+  end\n+\n+  private\n+\n+  def clear_unused_resources\n+    @table.each do |key, value|\n+      next unless value.instance_of?(Semian::ProtectedResource)\n+      @table.delete(key) unless value&.circuit_breaker.in_use? && !!value&.bulkhead","path":"lib/semian/lru_cache.rb","position":47,"original_position":47,"commit_id":"5bdcfb355442a2db083130b003a40449c86db73f","original_commit_id":"5bdcfb355442a2db083130b003a40449c86db73f","user":{"login":"sirupsen","id":97400,"node_id":"MDQ6VXNlcjk3NDAw","avatar_url":"https://avatars3.githubusercontent.com/u/97400?v=4","gravatar_id":"","url":"https://api.github.com/users/sirupsen","html_url":"https://github.com/sirupsen","followers_url":"https://api.github.com/users/sirupsen/followers","following_url":"https://api.github.com/users/sirupsen/following{/other_user}","gists_url":"https://api.github.com/users/sirupsen/gists{/gist_id}","starred_url":"https://api.github.com/users/sirupsen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sirupsen/subscriptions","organizations_url":"https://api.github.com/users/sirupsen/orgs","repos_url":"https://api.github.com/users/sirupsen/repos","events_url":"https://api.github.com/users/sirupsen/events{/privacy}","received_events_url":"https://api.github.com/users/sirupsen/received_events","type":"User","site_admin":false},"body":"I think it would be good custom here to call `destroy` on all the resource (the circuit + bulkhead, even if the latter doesn't exist) before deleting it from the hash. I don't expect that to make any difference now, but maybe it would in the future if the Circuit starts doing things like modifying timeouts permanently and needs to be cleaned up 🤷‍♂️ ","created_at":"2018-09-24T09:27:10Z","updated_at":"2018-09-24T09:30:03Z","html_url":"https://github.com/Shopify/semian/pull/193#discussion_r219774890","pull_request_url":"https://api.github.com/repos/Shopify/semian/pulls/193","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/Shopify/semian/pulls/comments/219774890"},"html":{"href":"https://github.com/Shopify/semian/pull/193#discussion_r219774890"},"pull_request":{"href":"https://api.github.com/repos/Shopify/semian/pulls/193"}},"in_reply_to_id":219774621},"pull_request":{"url":"https://api.github.com/repos/Shopify/semian/pulls/193","id":216033294,"node_id":"MDExOlB1bGxSZXF1ZXN0MjE2MDMzMjk0","html_url":"https://github.com/Shopify/semian/pull/193","diff_url":"https://github.com/Shopify/semian/pull/193.diff","patch_url":"https://github.com/Shopify/semian/pull/193.patch","issue_url":"https://api.github.com/repos/Shopify/semian/issues/193","number":193,"state":"open","locked":false,"title":"[WIP] Use LRU Cache for Semian resources","user":{"login":"max611","id":5659685,"node_id":"MDQ6VXNlcjU2NTk2ODU=","avatar_url":"https://avatars1.githubusercontent.com/u/5659685?v=4","gravatar_id":"","url":"https://api.github.com/users/max611","html_url":"https://github.com/max611","followers_url":"https://api.github.com/users/max611/followers","following_url":"https://api.github.com/users/max611/following{/other_user}","gists_url":"https://api.github.com/users/max611/gists{/gist_id}","starred_url":"https://api.github.com/users/max611/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/max611/subscriptions","organizations_url":"https://api.github.com/users/max611/orgs","repos_url":"https://api.github.com/users/max611/repos","events_url":"https://api.github.com/users/max611/events{/privacy}","received_events_url":"https://api.github.com/users/max611/received_events","type":"User","site_admin":false},"body":"This PR aims to refactor the Semian resources to a type of LRU cache. This will allow us to remove unused objects from the resources array and hopefully gain some performance out of it. (Will benchmark to make sure we see an improvement)\r\n\r\nAs of now, we never clean up the resources and it can end up with thousands of resources and therefore leak some memory because of it. Instead of using a simple array, this PR aims to add a new object called `LRUCache` to dynamically remove empty resources. This will allow us to use less resources and less memory.\r\n\r\nAn example would be using many webhooks and creating a resource for everyone of them, you could easily grow the amount of resources to a large number and keep them in the resources object and never clearing them which would cause memory usage for no reason. \r\n\r\nOne of the goals is to make sure this is backward compatible and also make sure this is an improvement. I will post benchmarks once I run them.","created_at":"2018-09-17T16:00:16Z","updated_at":"2018-09-24T09:30:03Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a9a7c59d79e1e2ae2d26f364cbe44c0cfd51c769","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/Shopify/semian/pulls/193/commits","review_comments_url":"https://api.github.com/repos/Shopify/semian/pulls/193/comments","review_comment_url":"https://api.github.com/repos/Shopify/semian/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Shopify/semian/issues/193/comments","statuses_url":"https://api.github.com/repos/Shopify/semian/statuses/5bdcfb355442a2db083130b003a40449c86db73f","head":{"label":"Shopify:implement_lru_cache","ref":"implement_lru_cache","sha":"5bdcfb355442a2db083130b003a40449c86db73f","user":{"login":"Shopify","id":8085,"node_id":"MDEyOk9yZ2FuaXphdGlvbjgwODU=","avatar_url":"https://avatars1.githubusercontent.com/u/8085?v=4","gravatar_id":"","url":"https://api.github.com/users/Shopify","html_url":"https://github.com/Shopify","followers_url":"https://api.github.com/users/Shopify/followers","following_url":"https://api.github.com/users/Shopify/following{/other_user}","gists_url":"https://api.github.com/users/Shopify/gists{/gist_id}","starred_url":"https://api.github.com/users/Shopify/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Shopify/subscriptions","organizations_url":"https://api.github.com/users/Shopify/orgs","repos_url":"https://api.github.com/users/Shopify/repos","events_url":"https://api.github.com/users/Shopify/events{/privacy}","received_events_url":"https://api.github.com/users/Shopify/received_events","type":"Organization","site_admin":false},"repo":{"id":24375548,"node_id":"MDEwOlJlcG9zaXRvcnkyNDM3NTU0OA==","name":"semian","full_name":"Shopify/semian","private":false,"owner":{"login":"Shopify","id":8085,"node_id":"MDEyOk9yZ2FuaXphdGlvbjgwODU=","avatar_url":"https://avatars1.githubusercontent.com/u/8085?v=4","gravatar_id":"","url":"https://api.github.com/users/Shopify","html_url":"https://github.com/Shopify","followers_url":"https://api.github.com/users/Shopify/followers","following_url":"https://api.github.com/users/Shopify/following{/other_user}","gists_url":"https://api.github.com/users/Shopify/gists{/gist_id}","starred_url":"https://api.github.com/users/Shopify/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Shopify/subscriptions","organizations_url":"https://api.github.com/users/Shopify/orgs","repos_url":"https://api.github.com/users/Shopify/repos","events_url":"https://api.github.com/users/Shopify/events{/privacy}","received_events_url":"https://api.github.com/users/Shopify/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/Shopify/semian","description":":monkey: Resiliency toolkit for Ruby for failing fast","fork":false,"url":"https://api.github.com/repos/Shopify/semian","forks_url":"https://api.github.com/repos/Shopify/semian/forks","keys_url":"https://api.github.com/repos/Shopify/semian/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Shopify/semian/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Shopify/semian/teams","hooks_url":"https://api.github.com/repos/Shopify/semian/hooks","issue_events_url":"https://api.github.com/repos/Shopify/semian/issues/events{/number}","events_url":"https://api.github.com/repos/Shopify/semian/events","assignees_url":"https://api.github.com/repos/Shopify/semian/assignees{/user}","branches_url":"https://api.github.com/repos/Shopify/semian/branches{/branch}","tags_url":"https://api.github.com/repos/Shopify/semian/tags","blobs_url":"https://api.github.com/repos/Shopify/semian/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Shopify/semian/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Shopify/semian/git/refs{/sha}","trees_url":"https://api.github.com/repos/Shopify/semian/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Shopify/semian/statuses/{sha}","languages_url":"https://api.github.com/repos/Shopify/semian/languages","stargazers_url":"https://api.github.com/repos/Shopify/semian/stargazers","contributors_url":"https://api.github.com/repos/Shopify/semian/contributors","subscribers_url":"https://api.github.com/repos/Shopify/semian/subscribers","subscription_url":"https://api.github.com/repos/Shopify/semian/subscription","commits_url":"https://api.github.com/repos/Shopify/semian/commits{/sha}","git_commits_url":"https://api.github.com/repos/Shopify/semian/git/commits{/sha}","comments_url":"https://api.github.com/repos/Shopify/semian/comments{/number}","issue_comment_url":"https://api.github.com/repos/Shopify/semian/issues/comments{/number}","contents_url":"https://api.github.com/repos/Shopify/semian/contents/{+path}","compare_url":"https://api.github.com/repos/Shopify/semian/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Shopify/semian/merges","archive_url":"https://api.github.com/repos/Shopify/semian/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Shopify/semian/downloads","issues_url":"https://api.github.com/repos/Shopify/semian/issues{/number}","pulls_url":"https://api.github.com/repos/Shopify/semian/pulls{/number}","milestones_url":"https://api.github.com/repos/Shopify/semian/milestones{/number}","notifications_url":"https://api.github.com/repos/Shopify/semian/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Shopify/semian/labels{/name}","releases_url":"https://api.github.com/repos/Shopify/semian/releases{/id}","deployments_url":"https://api.github.com/repos/Shopify/semian/deployments","created_at":"2014-09-23T14:47:19Z","updated_at":"2018-09-24T08:38:00Z","pushed_at":"2018-09-21T14:23:32Z","git_url":"git://github.com/Shopify/semian.git","ssh_url":"git@github.com:Shopify/semian.git","clone_url":"https://github.com/Shopify/semian.git","svn_url":"https://github.com/Shopify/semian","homepage":"","size":577,"stargazers_count":602,"watchers_count":602,"language":"Ruby","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":34,"mirror_url":null,"archived":false,"open_issues_count":26,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":34,"open_issues":26,"watchers":602,"default_branch":"master"}},"base":{"label":"Shopify:master","ref":"master","sha":"c56d83797a744963b7723443510283c1ef6ddf84","user":{"login":"Shopify","id":8085,"node_id":"MDEyOk9yZ2FuaXphdGlvbjgwODU=","avatar_url":"https://avatars1.githubusercontent.com/u/8085?v=4","gravatar_id":"","url":"https://api.github.com/users/Shopify","html_url":"https://github.com/Shopify","followers_url":"https://api.github.com/users/Shopify/followers","following_url":"https://api.github.com/users/Shopify/following{/other_user}","gists_url":"https://api.github.com/users/Shopify/gists{/gist_id}","starred_url":"https://api.github.com/users/Shopify/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Shopify/subscriptions","organizations_url":"https://api.github.com/users/Shopify/orgs","repos_url":"https://api.github.com/users/Shopify/repos","events_url":"https://api.github.com/users/Shopify/events{/privacy}","received_events_url":"https://api.github.com/users/Shopify/received_events","type":"Organization","site_admin":false},"repo":{"id":24375548,"node_id":"MDEwOlJlcG9zaXRvcnkyNDM3NTU0OA==","name":"semian","full_name":"Shopify/semian","private":false,"owner":{"login":"Shopify","id":8085,"node_id":"MDEyOk9yZ2FuaXphdGlvbjgwODU=","avatar_url":"https://avatars1.githubusercontent.com/u/8085?v=4","gravatar_id":"","url":"https://api.github.com/users/Shopify","html_url":"https://github.com/Shopify","followers_url":"https://api.github.com/users/Shopify/followers","following_url":"https://api.github.com/users/Shopify/following{/other_user}","gists_url":"https://api.github.com/users/Shopify/gists{/gist_id}","starred_url":"https://api.github.com/users/Shopify/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Shopify/subscriptions","organizations_url":"https://api.github.com/users/Shopify/orgs","repos_url":"https://api.github.com/users/Shopify/repos","events_url":"https://api.github.com/users/Shopify/events{/privacy}","received_events_url":"https://api.github.com/users/Shopify/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/Shopify/semian","description":":monkey: Resiliency toolkit for Ruby for failing fast","fork":false,"url":"https://api.github.com/repos/Shopify/semian","forks_url":"https://api.github.com/repos/Shopify/semian/forks","keys_url":"https://api.github.com/repos/Shopify/semian/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Shopify/semian/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Shopify/semian/teams","hooks_url":"https://api.github.com/repos/Shopify/semian/hooks","issue_events_url":"https://api.github.com/repos/Shopify/semian/issues/events{/number}","events_url":"https://api.github.com/repos/Shopify/semian/events","assignees_url":"https://api.github.com/repos/Shopify/semian/assignees{/user}","branches_url":"https://api.github.com/repos/Shopify/semian/branches{/branch}","tags_url":"https://api.github.com/repos/Shopify/semian/tags","blobs_url":"https://api.github.com/repos/Shopify/semian/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Shopify/semian/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Shopify/semian/git/refs{/sha}","trees_url":"https://api.github.com/repos/Shopify/semian/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Shopify/semian/statuses/{sha}","languages_url":"https://api.github.com/repos/Shopify/semian/languages","stargazers_url":"https://api.github.com/repos/Shopify/semian/stargazers","contributors_url":"https://api.github.com/repos/Shopify/semian/contributors","subscribers_url":"https://api.github.com/repos/Shopify/semian/subscribers","subscription_url":"https://api.github.com/repos/Shopify/semian/subscription","commits_url":"https://api.github.com/repos/Shopify/semian/commits{/sha}","git_commits_url":"https://api.github.com/repos/Shopify/semian/git/commits{/sha}","comments_url":"https://api.github.com/repos/Shopify/semian/comments{/number}","issue_comment_url":"https://api.github.com/repos/Shopify/semian/issues/comments{/number}","contents_url":"https://api.github.com/repos/Shopify/semian/contents/{+path}","compare_url":"https://api.github.com/repos/Shopify/semian/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Shopify/semian/merges","archive_url":"https://api.github.com/repos/Shopify/semian/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Shopify/semian/downloads","issues_url":"https://api.github.com/repos/Shopify/semian/issues{/number}","pulls_url":"https://api.github.com/repos/Shopify/semian/pulls{/number}","milestones_url":"https://api.github.com/repos/Shopify/semian/milestones{/number}","notifications_url":"https://api.github.com/repos/Shopify/semian/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Shopify/semian/labels{/name}","releases_url":"https://api.github.com/repos/Shopify/semian/releases{/id}","deployments_url":"https://api.github.com/repos/Shopify/semian/deployments","created_at":"2014-09-23T14:47:19Z","updated_at":"2018-09-24T08:38:00Z","pushed_at":"2018-09-21T14:23:32Z","git_url":"git://github.com/Shopify/semian.git","ssh_url":"git@github.com:Shopify/semian.git","clone_url":"https://github.com/Shopify/semian.git","svn_url":"https://github.com/Shopify/semian","homepage":"","size":577,"stargazers_count":602,"watchers_count":602,"language":"Ruby","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":34,"mirror_url":null,"archived":false,"open_issues_count":26,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":34,"open_issues":26,"watchers":602,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Shopify/semian/pulls/193"},"html":{"href":"https://github.com/Shopify/semian/pull/193"},"issue":{"href":"https://api.github.com/repos/Shopify/semian/issues/193"},"comments":{"href":"https://api.github.com/repos/Shopify/semian/issues/193/comments"},"review_comments":{"href":"https://api.github.com/repos/Shopify/semian/pulls/193/comments"},"review_comment":{"href":"https://api.github.com/repos/Shopify/semian/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Shopify/semian/pulls/193/commits"},"statuses":{"href":"https://api.github.com/repos/Shopify/semian/statuses/5bdcfb355442a2db083130b003a40449c86db73f"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"sirupsen"}}