{"action":"created","comment":{"url":"https://api.github.com/repos/coxmediagroup/django-massimport/pulls/comments/27411664","id":27411664,"diff_hunk":"@@ -192,6 +196,59 @@ def collector_unsubscribe(self, feed_url, collector_name):\n             # Could raise FeedDoesNotExist, but this is simpler\n             raise CollectorDoesNotExist\n \n+    #\n+    # Access methods for the item cache\n+    #\n+\n+    def get_item_key(self, item, feed_sub):\n+        \"\"\"Calculate a unique cache key for the item, given a parsed feed\n+        item and a Feed Subscription.\n+\n+        :param item: dictionary containing an item in the standard document model.\n+        :type item: dict\n+        :param feed_sub: FeedSubscription object containing the item.\n+        :type feed_sub: FeedSubscription\n+\n+        :returns: str\n+        \"\"\"\n+        # XXX is it cheating to use the GUID here?\n+        cache_key = 'item:{0}:{1}'.format(feed_sub.pk, item.get('guid'))\n+        return cache_key\n+\n+    def store_item(self, item, feed_sub):\n+        \"\"\"Store an item into the cache, returning its cache key.\n+\n+        :param item: dictionary containing an item in the standard document model.\n+        :type item: dict\n+        :param feed_sub: FeedSubscription object containing the item.\n+        :type feed_sub: FeedSubscription\n+\n+        :returns: str\n+\n+        \"\"\"\n+        rdc = utils.get_redis_client(redis_db=settings.REDIS_CACHE_DB)\n+        key = self.get_item_key(item, feed_sub)\n+        rdc.set(key, json.dumps(item))\n+        return key\n+        # XXX store key in subscription database for later retrieval\n+        # (XXX by what? B-02816 says each Collector will get a message in\n+        # the NotifyCollectors queue.)\n+\n+    def get_item(self, cache_key):\n+        \"\"\"Retrieve a cached item.\n+\n+        :param cache_key: string containing a cache key\n+        :type item: str\n+\n+        :returns: dict\n+        \"\"\"\n+        rdc = utils.get_redis_client(redis_db=settings.REDIS_CACHE_DB)\n+        item_json = rdc.get(cache_key)\n+        if item_json is None:","path":"feeds/models.py","position":65,"original_position":65,"commit_id":"fc6383330287955adb9fc374a065b4a4125257b1","original_commit_id":"fc6383330287955adb9fc374a065b4a4125257b1","user":{"login":"aarcro","id":279725,"avatar_url":"https://avatars.githubusercontent.com/u/279725?v=3","gravatar_id":"","url":"https://api.github.com/users/aarcro","html_url":"https://github.com/aarcro","followers_url":"https://api.github.com/users/aarcro/followers","following_url":"https://api.github.com/users/aarcro/following{/other_user}","gists_url":"https://api.github.com/users/aarcro/gists{/gist_id}","starred_url":"https://api.github.com/users/aarcro/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aarcro/subscriptions","organizations_url":"https://api.github.com/users/aarcro/orgs","repos_url":"https://api.github.com/users/aarcro/repos","events_url":"https://api.github.com/users/aarcro/events{/privacy}","received_events_url":"https://api.github.com/users/aarcro/received_events","type":"User","site_admin":false},"body":"Yeah, we need to define an interface. Already some methods return None and some raise exceptions, but maybe that's OK.\r\n\r\nReturning None from a get that couldn't be found means you always have to check the return value for None - and weird things (like ValueErrors) will happen later if you don't.\r\n\r\nRaising from get when there is no match means you have to `except` it somewhere, or there's a 500. Fails fast loud and accurate.\r\n\r\nSooooo... Maybe we should always raise when there are missing things, and not return None. Shouldn't raise out the ValueError anyway, but our own MissingFooItemException.","created_at":"2015-03-30T17:24:10Z","updated_at":"2015-03-30T17:24:10Z","html_url":"https://github.com/coxmediagroup/django-massimport/pull/3#discussion_r27411664","pull_request_url":"https://api.github.com/repos/coxmediagroup/django-massimport/pulls/3","_links":{"self":{"href":"https://api.github.com/repos/coxmediagroup/django-massimport/pulls/comments/27411664"},"html":{"href":"https://github.com/coxmediagroup/django-massimport/pull/3#discussion_r27411664"},"pull_request":{"href":"https://api.github.com/repos/coxmediagroup/django-massimport/pulls/3"}}},"pull_request":{"url":"https://api.github.com/repos/coxmediagroup/django-massimport/pulls/3","id":32231042,"html_url":"https://github.com/coxmediagroup/django-massimport/pull/3","diff_url":"https://github.com/coxmediagroup/django-massimport/pull/3.diff","patch_url":"https://github.com/coxmediagroup/django-massimport/pull/3.patch","issue_url":"https://api.github.com/repos/coxmediagroup/django-massimport/issues/3","number":3,"state":"open","locked":false,"title":"B 03538","user":{"login":"akuchling","id":204654,"avatar_url":"https://avatars.githubusercontent.com/u/204654?v=3","gravatar_id":"","url":"https://api.github.com/users/akuchling","html_url":"https://github.com/akuchling","followers_url":"https://api.github.com/users/akuchling/followers","following_url":"https://api.github.com/users/akuchling/following{/other_user}","gists_url":"https://api.github.com/users/akuchling/gists{/gist_id}","starred_url":"https://api.github.com/users/akuchling/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akuchling/subscriptions","organizations_url":"https://api.github.com/users/akuchling/orgs","repos_url":"https://api.github.com/users/akuchling/repos","events_url":"https://api.github.com/users/akuchling/events{/privacy}","received_events_url":"https://api.github.com/users/akuchling/received_events","type":"User","site_admin":false},"body":"Implement methods for producing cache keys for items (described in the standard document model).\r\n","created_at":"2015-03-30T14:24:39Z","updated_at":"2015-03-30T17:24:10Z","closed_at":null,"merged_at":null,"merge_commit_sha":"7928b12e2abc5a97667c11011d9413dcb85f6c9d","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/coxmediagroup/django-massimport/pulls/3/commits","review_comments_url":"https://api.github.com/repos/coxmediagroup/django-massimport/pulls/3/comments","review_comment_url":"https://api.github.com/repos/coxmediagroup/django-massimport/pulls/comments{/number}","comments_url":"https://api.github.com/repos/coxmediagroup/django-massimport/issues/3/comments","statuses_url":"https://api.github.com/repos/coxmediagroup/django-massimport/statuses/fc6383330287955adb9fc374a065b4a4125257b1","head":{"label":"coxmediagroup:B-03538","ref":"B-03538","sha":"fc6383330287955adb9fc374a065b4a4125257b1","user":{"login":"coxmediagroup","id":370145,"avatar_url":"https://avatars.githubusercontent.com/u/370145?v=3","gravatar_id":"","url":"https://api.github.com/users/coxmediagroup","html_url":"https://github.com/coxmediagroup","followers_url":"https://api.github.com/users/coxmediagroup/followers","following_url":"https://api.github.com/users/coxmediagroup/following{/other_user}","gists_url":"https://api.github.com/users/coxmediagroup/gists{/gist_id}","starred_url":"https://api.github.com/users/coxmediagroup/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coxmediagroup/subscriptions","organizations_url":"https://api.github.com/users/coxmediagroup/orgs","repos_url":"https://api.github.com/users/coxmediagroup/repos","events_url":"https://api.github.com/users/coxmediagroup/events{/privacy}","received_events_url":"https://api.github.com/users/coxmediagroup/received_events","type":"Organization","site_admin":false},"repo":{"id":31384849,"name":"django-massimport","full_name":"coxmediagroup/django-massimport","owner":{"login":"coxmediagroup","id":370145,"avatar_url":"https://avatars.githubusercontent.com/u/370145?v=3","gravatar_id":"","url":"https://api.github.com/users/coxmediagroup","html_url":"https://github.com/coxmediagroup","followers_url":"https://api.github.com/users/coxmediagroup/followers","following_url":"https://api.github.com/users/coxmediagroup/following{/other_user}","gists_url":"https://api.github.com/users/coxmediagroup/gists{/gist_id}","starred_url":"https://api.github.com/users/coxmediagroup/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coxmediagroup/subscriptions","organizations_url":"https://api.github.com/users/coxmediagroup/orgs","repos_url":"https://api.github.com/users/coxmediagroup/repos","events_url":"https://api.github.com/users/coxmediagroup/events{/privacy}","received_events_url":"https://api.github.com/users/coxmediagroup/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/coxmediagroup/django-massimport","description":"Mass Import Service","fork":false,"url":"https://api.github.com/repos/coxmediagroup/django-massimport","forks_url":"https://api.github.com/repos/coxmediagroup/django-massimport/forks","keys_url":"https://api.github.com/repos/coxmediagroup/django-massimport/keys{/key_id}","collaborators_url":"https://api.github.com/repos/coxmediagroup/django-massimport/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/coxmediagroup/django-massimport/teams","hooks_url":"https://api.github.com/repos/coxmediagroup/django-massimport/hooks","issue_events_url":"https://api.github.com/repos/coxmediagroup/django-massimport/issues/events{/number}","events_url":"https://api.github.com/repos/coxmediagroup/django-massimport/events","assignees_url":"https://api.github.com/repos/coxmediagroup/django-massimport/assignees{/user}","branches_url":"https://api.github.com/repos/coxmediagroup/django-massimport/branches{/branch}","tags_url":"https://api.github.com/repos/coxmediagroup/django-massimport/tags","blobs_url":"https://api.github.com/repos/coxmediagroup/django-massimport/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/coxmediagroup/django-massimport/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/coxmediagroup/django-massimport/git/refs{/sha}","trees_url":"https://api.github.com/repos/coxmediagroup/django-massimport/git/trees{/sha}","statuses_url":"https://api.github.com/repos/coxmediagroup/django-massimport/statuses/{sha}","languages_url":"https://api.github.com/repos/coxmediagroup/django-massimport/languages","stargazers_url":"https://api.github.com/repos/coxmediagroup/django-massimport/stargazers","contributors_url":"https://api.github.com/repos/coxmediagroup/django-massimport/contributors","subscribers_url":"https://api.github.com/repos/coxmediagroup/django-massimport/subscribers","subscription_url":"https://api.github.com/repos/coxmediagroup/django-massimport/subscription","commits_url":"https://api.github.com/repos/coxmediagroup/django-massimport/commits{/sha}","git_commits_url":"https://api.github.com/repos/coxmediagroup/django-massimport/git/commits{/sha}","comments_url":"https://api.github.com/repos/coxmediagroup/django-massimport/comments{/number}","issue_comment_url":"https://api.github.com/repos/coxmediagroup/django-massimport/issues/comments{/number}","contents_url":"https://api.github.com/repos/coxmediagroup/django-massimport/contents/{+path}","compare_url":"https://api.github.com/repos/coxmediagroup/django-massimport/compare/{base}...{head}","merges_url":"https://api.github.com/repos/coxmediagroup/django-massimport/merges","archive_url":"https://api.github.com/repos/coxmediagroup/django-massimport/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/coxmediagroup/django-massimport/downloads","issues_url":"https://api.github.com/repos/coxmediagroup/django-massimport/issues{/number}","pulls_url":"https://api.github.com/repos/coxmediagroup/django-massimport/pulls{/number}","milestones_url":"https://api.github.com/repos/coxmediagroup/django-massimport/milestones{/number}","notifications_url":"https://api.github.com/repos/coxmediagroup/django-massimport/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/coxmediagroup/django-massimport/labels{/name}","releases_url":"https://api.github.com/repos/coxmediagroup/django-massimport/releases{/id}","created_at":"2015-02-26T19:31:24Z","updated_at":"2015-03-25T20:28:58Z","pushed_at":"2015-03-30T17:23:11Z","git_url":"git://github.com/coxmediagroup/django-massimport.git","ssh_url":"git@github.com:coxmediagroup/django-massimport.git","clone_url":"https://github.com/coxmediagroup/django-massimport.git","svn_url":"https://github.com/coxmediagroup/django-massimport","homepage":null,"size":328,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":2,"forks":0,"open_issues":2,"watchers":0,"default_branch":"master"}},"base":{"label":"coxmediagroup:master","ref":"master","sha":"567539e8cd27258812fc74b10219b824e22adaa7","user":{"login":"coxmediagroup","id":370145,"avatar_url":"https://avatars.githubusercontent.com/u/370145?v=3","gravatar_id":"","url":"https://api.github.com/users/coxmediagroup","html_url":"https://github.com/coxmediagroup","followers_url":"https://api.github.com/users/coxmediagroup/followers","following_url":"https://api.github.com/users/coxmediagroup/following{/other_user}","gists_url":"https://api.github.com/users/coxmediagroup/gists{/gist_id}","starred_url":"https://api.github.com/users/coxmediagroup/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coxmediagroup/subscriptions","organizations_url":"https://api.github.com/users/coxmediagroup/orgs","repos_url":"https://api.github.com/users/coxmediagroup/repos","events_url":"https://api.github.com/users/coxmediagroup/events{/privacy}","received_events_url":"https://api.github.com/users/coxmediagroup/received_events","type":"Organization","site_admin":false},"repo":{"id":31384849,"name":"django-massimport","full_name":"coxmediagroup/django-massimport","owner":{"login":"coxmediagroup","id":370145,"avatar_url":"https://avatars.githubusercontent.com/u/370145?v=3","gravatar_id":"","url":"https://api.github.com/users/coxmediagroup","html_url":"https://github.com/coxmediagroup","followers_url":"https://api.github.com/users/coxmediagroup/followers","following_url":"https://api.github.com/users/coxmediagroup/following{/other_user}","gists_url":"https://api.github.com/users/coxmediagroup/gists{/gist_id}","starred_url":"https://api.github.com/users/coxmediagroup/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coxmediagroup/subscriptions","organizations_url":"https://api.github.com/users/coxmediagroup/orgs","repos_url":"https://api.github.com/users/coxmediagroup/repos","events_url":"https://api.github.com/users/coxmediagroup/events{/privacy}","received_events_url":"https://api.github.com/users/coxmediagroup/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/coxmediagroup/django-massimport","description":"Mass Import Service","fork":false,"url":"https://api.github.com/repos/coxmediagroup/django-massimport","forks_url":"https://api.github.com/repos/coxmediagroup/django-massimport/forks","keys_url":"https://api.github.com/repos/coxmediagroup/django-massimport/keys{/key_id}","collaborators_url":"https://api.github.com/repos/coxmediagroup/django-massimport/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/coxmediagroup/django-massimport/teams","hooks_url":"https://api.github.com/repos/coxmediagroup/django-massimport/hooks","issue_events_url":"https://api.github.com/repos/coxmediagroup/django-massimport/issues/events{/number}","events_url":"https://api.github.com/repos/coxmediagroup/django-massimport/events","assignees_url":"https://api.github.com/repos/coxmediagroup/django-massimport/assignees{/user}","branches_url":"https://api.github.com/repos/coxmediagroup/django-massimport/branches{/branch}","tags_url":"https://api.github.com/repos/coxmediagroup/django-massimport/tags","blobs_url":"https://api.github.com/repos/coxmediagroup/django-massimport/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/coxmediagroup/django-massimport/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/coxmediagroup/django-massimport/git/refs{/sha}","trees_url":"https://api.github.com/repos/coxmediagroup/django-massimport/git/trees{/sha}","statuses_url":"https://api.github.com/repos/coxmediagroup/django-massimport/statuses/{sha}","languages_url":"https://api.github.com/repos/coxmediagroup/django-massimport/languages","stargazers_url":"https://api.github.com/repos/coxmediagroup/django-massimport/stargazers","contributors_url":"https://api.github.com/repos/coxmediagroup/django-massimport/contributors","subscribers_url":"https://api.github.com/repos/coxmediagroup/django-massimport/subscribers","subscription_url":"https://api.github.com/repos/coxmediagroup/django-massimport/subscription","commits_url":"https://api.github.com/repos/coxmediagroup/django-massimport/commits{/sha}","git_commits_url":"https://api.github.com/repos/coxmediagroup/django-massimport/git/commits{/sha}","comments_url":"https://api.github.com/repos/coxmediagroup/django-massimport/comments{/number}","issue_comment_url":"https://api.github.com/repos/coxmediagroup/django-massimport/issues/comments{/number}","contents_url":"https://api.github.com/repos/coxmediagroup/django-massimport/contents/{+path}","compare_url":"https://api.github.com/repos/coxmediagroup/django-massimport/compare/{base}...{head}","merges_url":"https://api.github.com/repos/coxmediagroup/django-massimport/merges","archive_url":"https://api.github.com/repos/coxmediagroup/django-massimport/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/coxmediagroup/django-massimport/downloads","issues_url":"https://api.github.com/repos/coxmediagroup/django-massimport/issues{/number}","pulls_url":"https://api.github.com/repos/coxmediagroup/django-massimport/pulls{/number}","milestones_url":"https://api.github.com/repos/coxmediagroup/django-massimport/milestones{/number}","notifications_url":"https://api.github.com/repos/coxmediagroup/django-massimport/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/coxmediagroup/django-massimport/labels{/name}","releases_url":"https://api.github.com/repos/coxmediagroup/django-massimport/releases{/id}","created_at":"2015-02-26T19:31:24Z","updated_at":"2015-03-25T20:28:58Z","pushed_at":"2015-03-30T17:23:11Z","git_url":"git://github.com/coxmediagroup/django-massimport.git","ssh_url":"git@github.com:coxmediagroup/django-massimport.git","clone_url":"https://github.com/coxmediagroup/django-massimport.git","svn_url":"https://github.com/coxmediagroup/django-massimport","homepage":null,"size":328,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":2,"forks":0,"open_issues":2,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/coxmediagroup/django-massimport/pulls/3"},"html":{"href":"https://github.com/coxmediagroup/django-massimport/pull/3"},"issue":{"href":"https://api.github.com/repos/coxmediagroup/django-massimport/issues/3"},"comments":{"href":"https://api.github.com/repos/coxmediagroup/django-massimport/issues/3/comments"},"review_comments":{"href":"https://api.github.com/repos/coxmediagroup/django-massimport/pulls/3/comments"},"review_comment":{"href":"https://api.github.com/repos/coxmediagroup/django-massimport/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/coxmediagroup/django-massimport/pulls/3/commits"},"statuses":{"href":"https://api.github.com/repos/coxmediagroup/django-massimport/statuses/fc6383330287955adb9fc374a065b4a4125257b1"}}}}