{"action":"created","comment":{"url":"https://api.github.com/repos/rackerlabs/otter/pulls/comments/31366307","id":31366307,"diff_hunk":"@@ -111,8 +115,50 @@ def group_id(s):\n                             filter(server_predicate),\n                             filter(has_group_id))\n \n-    eff = get_all_server_details(changes_since)\n-    return eff.on(servers_apply)\n+    return get_all_server_details(changes_since).on(servers_apply)\n+\n+\n+def merge_servers(first, second):\n+    \"\"\"\n+    Return servers got by merging the two sets of servers where second\n+    takes precedence over first\n+\n+    :param list first: List of server dicts\n+    :param list second: List of server dicts\n+    :return: List of merged server dicts\n+    \"\"\"\n+    def sdict(servers):\n+        return {s['id']: s for s in servers}\n+\n+    return merge(sdict(first), sdict(second)).itervalues()\n+\n+\n+@do\n+def get_scaling_group_servers(tenant_id, group_id, now,\n+                              cache_class=CassScalingGroupServersCache,\n+                              all_as_servers=get_all_scaling_group_servers):\n+    \"\"\"\n+    Get a group's servers taken from cache if it exists. Updates cache\n+    if it is empty from newly fetched servers\n+    # NOTE: This function takes tenant_id even though the whole effect is\n+    # scoped on the tenant because cache calls require tenant_id. Should\n+    # they also not take tenant_id and work on the scope?\n+\n+    :return: Servers as iterator of dicts\n+    :rtype: Effect\n+    \"\"\"\n+    cache = cache_class(tenant_id, group_id)\n+    cached_servers, last_update = yield cache.get_servers()\n+    if last_update is None or now - last_update >= timedelta(days=30):\n+        last_update = now - timedelta(days=30)\n+        changes = (yield all_as_servers(last_update))[group_id]","path":"otter/convergence/gathering.py","position":79,"original_position":79,"commit_id":"702b6b491e2311cce7e6b39e8159fd7812a105ed","original_commit_id":"702b6b491e2311cce7e6b39e8159fd7812a105ed","user":{"login":"cyli","id":223200,"avatar_url":"https://avatars.githubusercontent.com/u/223200?v=3","gravatar_id":"","url":"https://api.github.com/users/cyli","html_url":"https://github.com/cyli","followers_url":"https://api.github.com/users/cyli/followers","following_url":"https://api.github.com/users/cyli/following{/other_user}","gists_url":"https://api.github.com/users/cyli/gists{/gist_id}","starred_url":"https://api.github.com/users/cyli/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cyli/subscriptions","organizations_url":"https://api.github.com/users/cyli/orgs","repos_url":"https://api.github.com/users/cyli/repos","events_url":"https://api.github.com/users/cyli/events{/privacy}","received_events_url":"https://api.github.com/users/cyli/received_events","type":"User","site_admin":false},"body":"This probably  needs to be `.get(group_id, {})`, for when there are no servers yet.","created_at":"2015-05-29T21:25:52Z","updated_at":"2015-05-29T21:25:52Z","html_url":"https://github.com/rackerlabs/otter/pull/1458#discussion_r31366307","pull_request_url":"https://api.github.com/repos/rackerlabs/otter/pulls/1458","_links":{"self":{"href":"https://api.github.com/repos/rackerlabs/otter/pulls/comments/31366307"},"html":{"href":"https://github.com/rackerlabs/otter/pull/1458#discussion_r31366307"},"pull_request":{"href":"https://api.github.com/repos/rackerlabs/otter/pulls/1458"}}},"pull_request":{"url":"https://api.github.com/repos/rackerlabs/otter/pulls/1458","id":36083248,"html_url":"https://github.com/rackerlabs/otter/pull/1458","diff_url":"https://github.com/rackerlabs/otter/pull/1458.diff","patch_url":"https://github.com/rackerlabs/otter/pull/1458.patch","issue_url":"https://api.github.com/repos/rackerlabs/otter/issues/1458","number":1458,"state":"open","locked":false,"title":"Servers cache using changes-since filter","user":{"login":"manishtomar","id":758529,"avatar_url":"https://avatars.githubusercontent.com/u/758529?v=3","gravatar_id":"","url":"https://api.github.com/users/manishtomar","html_url":"https://github.com/manishtomar","followers_url":"https://api.github.com/users/manishtomar/followers","following_url":"https://api.github.com/users/manishtomar/following{/other_user}","gists_url":"https://api.github.com/users/manishtomar/gists{/gist_id}","starred_url":"https://api.github.com/users/manishtomar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/manishtomar/subscriptions","organizations_url":"https://api.github.com/users/manishtomar/orgs","repos_url":"https://api.github.com/users/manishtomar/repos","events_url":"https://api.github.com/users/manishtomar/events{/privacy}","received_events_url":"https://api.github.com/users/manishtomar/received_events","type":"User","site_admin":false},"body":"Implements first 3 tasks of #881. Reviewer question:\r\n\r\nThe cache model interface assumes multiple caches of a scaling group separated by `update_time`. `get_servers` is implemented with that assumption whereas in reality only one cache is always used. Should the model and/or the impl change with only one cache in mind? If so, I'll remove `take_while` and its usage. This is why I don't have its tests yet. ","created_at":"2015-05-23T06:31:26Z","updated_at":"2015-05-29T21:25:52Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f9cfd1392d68c2415222ae226849e207f095c1ad","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/rackerlabs/otter/pulls/1458/commits","review_comments_url":"https://api.github.com/repos/rackerlabs/otter/pulls/1458/comments","review_comment_url":"https://api.github.com/repos/rackerlabs/otter/pulls/comments{/number}","comments_url":"https://api.github.com/repos/rackerlabs/otter/issues/1458/comments","statuses_url":"https://api.github.com/repos/rackerlabs/otter/statuses/702b6b491e2311cce7e6b39e8159fd7812a105ed","head":{"label":"rackerlabs:change-since","ref":"change-since","sha":"702b6b491e2311cce7e6b39e8159fd7812a105ed","user":{"login":"rackerlabs","id":84293,"avatar_url":"https://avatars.githubusercontent.com/u/84293?v=3","gravatar_id":"","url":"https://api.github.com/users/rackerlabs","html_url":"https://github.com/rackerlabs","followers_url":"https://api.github.com/users/rackerlabs/followers","following_url":"https://api.github.com/users/rackerlabs/following{/other_user}","gists_url":"https://api.github.com/users/rackerlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/rackerlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rackerlabs/subscriptions","organizations_url":"https://api.github.com/users/rackerlabs/orgs","repos_url":"https://api.github.com/users/rackerlabs/repos","events_url":"https://api.github.com/users/rackerlabs/events{/privacy}","received_events_url":"https://api.github.com/users/rackerlabs/received_events","type":"Organization","site_admin":false},"repo":{"id":6097139,"name":"otter","full_name":"rackerlabs/otter","owner":{"login":"rackerlabs","id":84293,"avatar_url":"https://avatars.githubusercontent.com/u/84293?v=3","gravatar_id":"","url":"https://api.github.com/users/rackerlabs","html_url":"https://github.com/rackerlabs","followers_url":"https://api.github.com/users/rackerlabs/followers","following_url":"https://api.github.com/users/rackerlabs/following{/other_user}","gists_url":"https://api.github.com/users/rackerlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/rackerlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rackerlabs/subscriptions","organizations_url":"https://api.github.com/users/rackerlabs/orgs","repos_url":"https://api.github.com/users/rackerlabs/repos","events_url":"https://api.github.com/users/rackerlabs/events{/privacy}","received_events_url":"https://api.github.com/users/rackerlabs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/rackerlabs/otter","description":"Rackspace Auto Scale","fork":false,"url":"https://api.github.com/repos/rackerlabs/otter","forks_url":"https://api.github.com/repos/rackerlabs/otter/forks","keys_url":"https://api.github.com/repos/rackerlabs/otter/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rackerlabs/otter/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rackerlabs/otter/teams","hooks_url":"https://api.github.com/repos/rackerlabs/otter/hooks","issue_events_url":"https://api.github.com/repos/rackerlabs/otter/issues/events{/number}","events_url":"https://api.github.com/repos/rackerlabs/otter/events","assignees_url":"https://api.github.com/repos/rackerlabs/otter/assignees{/user}","branches_url":"https://api.github.com/repos/rackerlabs/otter/branches{/branch}","tags_url":"https://api.github.com/repos/rackerlabs/otter/tags","blobs_url":"https://api.github.com/repos/rackerlabs/otter/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rackerlabs/otter/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rackerlabs/otter/git/refs{/sha}","trees_url":"https://api.github.com/repos/rackerlabs/otter/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rackerlabs/otter/statuses/{sha}","languages_url":"https://api.github.com/repos/rackerlabs/otter/languages","stargazers_url":"https://api.github.com/repos/rackerlabs/otter/stargazers","contributors_url":"https://api.github.com/repos/rackerlabs/otter/contributors","subscribers_url":"https://api.github.com/repos/rackerlabs/otter/subscribers","subscription_url":"https://api.github.com/repos/rackerlabs/otter/subscription","commits_url":"https://api.github.com/repos/rackerlabs/otter/commits{/sha}","git_commits_url":"https://api.github.com/repos/rackerlabs/otter/git/commits{/sha}","comments_url":"https://api.github.com/repos/rackerlabs/otter/comments{/number}","issue_comment_url":"https://api.github.com/repos/rackerlabs/otter/issues/comments{/number}","contents_url":"https://api.github.com/repos/rackerlabs/otter/contents/{+path}","compare_url":"https://api.github.com/repos/rackerlabs/otter/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rackerlabs/otter/merges","archive_url":"https://api.github.com/repos/rackerlabs/otter/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rackerlabs/otter/downloads","issues_url":"https://api.github.com/repos/rackerlabs/otter/issues{/number}","pulls_url":"https://api.github.com/repos/rackerlabs/otter/pulls{/number}","milestones_url":"https://api.github.com/repos/rackerlabs/otter/milestones{/number}","notifications_url":"https://api.github.com/repos/rackerlabs/otter/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rackerlabs/otter/labels{/name}","releases_url":"https://api.github.com/repos/rackerlabs/otter/releases{/id}","created_at":"2012-10-05T21:35:59Z","updated_at":"2015-05-08T20:48:42Z","pushed_at":"2015-05-29T20:51:25Z","git_url":"git://github.com/rackerlabs/otter.git","ssh_url":"git@github.com:rackerlabs/otter.git","clone_url":"https://github.com/rackerlabs/otter.git","svn_url":"https://github.com/rackerlabs/otter","homepage":"http://www.rackspace.com/cloud/auto-scale/","size":49063,"stargazers_count":43,"watchers_count":43,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":17,"mirror_url":null,"open_issues_count":95,"forks":17,"open_issues":95,"watchers":43,"default_branch":"master"}},"base":{"label":"rackerlabs:master","ref":"master","sha":"83469cbf4148cd9fd721903579aba9abaee3ae24","user":{"login":"rackerlabs","id":84293,"avatar_url":"https://avatars.githubusercontent.com/u/84293?v=3","gravatar_id":"","url":"https://api.github.com/users/rackerlabs","html_url":"https://github.com/rackerlabs","followers_url":"https://api.github.com/users/rackerlabs/followers","following_url":"https://api.github.com/users/rackerlabs/following{/other_user}","gists_url":"https://api.github.com/users/rackerlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/rackerlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rackerlabs/subscriptions","organizations_url":"https://api.github.com/users/rackerlabs/orgs","repos_url":"https://api.github.com/users/rackerlabs/repos","events_url":"https://api.github.com/users/rackerlabs/events{/privacy}","received_events_url":"https://api.github.com/users/rackerlabs/received_events","type":"Organization","site_admin":false},"repo":{"id":6097139,"name":"otter","full_name":"rackerlabs/otter","owner":{"login":"rackerlabs","id":84293,"avatar_url":"https://avatars.githubusercontent.com/u/84293?v=3","gravatar_id":"","url":"https://api.github.com/users/rackerlabs","html_url":"https://github.com/rackerlabs","followers_url":"https://api.github.com/users/rackerlabs/followers","following_url":"https://api.github.com/users/rackerlabs/following{/other_user}","gists_url":"https://api.github.com/users/rackerlabs/gists{/gist_id}","starred_url":"https://api.github.com/users/rackerlabs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rackerlabs/subscriptions","organizations_url":"https://api.github.com/users/rackerlabs/orgs","repos_url":"https://api.github.com/users/rackerlabs/repos","events_url":"https://api.github.com/users/rackerlabs/events{/privacy}","received_events_url":"https://api.github.com/users/rackerlabs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/rackerlabs/otter","description":"Rackspace Auto Scale","fork":false,"url":"https://api.github.com/repos/rackerlabs/otter","forks_url":"https://api.github.com/repos/rackerlabs/otter/forks","keys_url":"https://api.github.com/repos/rackerlabs/otter/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rackerlabs/otter/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rackerlabs/otter/teams","hooks_url":"https://api.github.com/repos/rackerlabs/otter/hooks","issue_events_url":"https://api.github.com/repos/rackerlabs/otter/issues/events{/number}","events_url":"https://api.github.com/repos/rackerlabs/otter/events","assignees_url":"https://api.github.com/repos/rackerlabs/otter/assignees{/user}","branches_url":"https://api.github.com/repos/rackerlabs/otter/branches{/branch}","tags_url":"https://api.github.com/repos/rackerlabs/otter/tags","blobs_url":"https://api.github.com/repos/rackerlabs/otter/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rackerlabs/otter/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rackerlabs/otter/git/refs{/sha}","trees_url":"https://api.github.com/repos/rackerlabs/otter/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rackerlabs/otter/statuses/{sha}","languages_url":"https://api.github.com/repos/rackerlabs/otter/languages","stargazers_url":"https://api.github.com/repos/rackerlabs/otter/stargazers","contributors_url":"https://api.github.com/repos/rackerlabs/otter/contributors","subscribers_url":"https://api.github.com/repos/rackerlabs/otter/subscribers","subscription_url":"https://api.github.com/repos/rackerlabs/otter/subscription","commits_url":"https://api.github.com/repos/rackerlabs/otter/commits{/sha}","git_commits_url":"https://api.github.com/repos/rackerlabs/otter/git/commits{/sha}","comments_url":"https://api.github.com/repos/rackerlabs/otter/comments{/number}","issue_comment_url":"https://api.github.com/repos/rackerlabs/otter/issues/comments{/number}","contents_url":"https://api.github.com/repos/rackerlabs/otter/contents/{+path}","compare_url":"https://api.github.com/repos/rackerlabs/otter/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rackerlabs/otter/merges","archive_url":"https://api.github.com/repos/rackerlabs/otter/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rackerlabs/otter/downloads","issues_url":"https://api.github.com/repos/rackerlabs/otter/issues{/number}","pulls_url":"https://api.github.com/repos/rackerlabs/otter/pulls{/number}","milestones_url":"https://api.github.com/repos/rackerlabs/otter/milestones{/number}","notifications_url":"https://api.github.com/repos/rackerlabs/otter/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rackerlabs/otter/labels{/name}","releases_url":"https://api.github.com/repos/rackerlabs/otter/releases{/id}","created_at":"2012-10-05T21:35:59Z","updated_at":"2015-05-08T20:48:42Z","pushed_at":"2015-05-29T20:51:25Z","git_url":"git://github.com/rackerlabs/otter.git","ssh_url":"git@github.com:rackerlabs/otter.git","clone_url":"https://github.com/rackerlabs/otter.git","svn_url":"https://github.com/rackerlabs/otter","homepage":"http://www.rackspace.com/cloud/auto-scale/","size":49063,"stargazers_count":43,"watchers_count":43,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":17,"mirror_url":null,"open_issues_count":95,"forks":17,"open_issues":95,"watchers":43,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rackerlabs/otter/pulls/1458"},"html":{"href":"https://github.com/rackerlabs/otter/pull/1458"},"issue":{"href":"https://api.github.com/repos/rackerlabs/otter/issues/1458"},"comments":{"href":"https://api.github.com/repos/rackerlabs/otter/issues/1458/comments"},"review_comments":{"href":"https://api.github.com/repos/rackerlabs/otter/pulls/1458/comments"},"review_comment":{"href":"https://api.github.com/repos/rackerlabs/otter/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/rackerlabs/otter/pulls/1458/commits"},"statuses":{"href":"https://api.github.com/repos/rackerlabs/otter/statuses/702b6b491e2311cce7e6b39e8159fd7812a105ed"}}}}