{"action":"closed","number":4479,"pull_request":{"url":"https://api.github.com/repos/antirez/redis/pulls/4479","id":154922478,"html_url":"https://github.com/antirez/redis/pull/4479","diff_url":"https://github.com/antirez/redis/pull/4479.diff","patch_url":"https://github.com/antirez/redis/pull/4479.patch","issue_url":"https://api.github.com/repos/antirez/redis/issues/4479","number":4479,"state":"closed","locked":false,"title":"Keyspace notifications API for modules","user":{"login":"dvirsky","id":503226,"avatar_url":"https://avatars2.githubusercontent.com/u/503226?v=4","gravatar_id":"","url":"https://api.github.com/users/dvirsky","html_url":"https://github.com/dvirsky","followers_url":"https://api.github.com/users/dvirsky/followers","following_url":"https://api.github.com/users/dvirsky/following{/other_user}","gists_url":"https://api.github.com/users/dvirsky/gists{/gist_id}","starred_url":"https://api.github.com/users/dvirsky/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dvirsky/subscriptions","organizations_url":"https://api.github.com/users/dvirsky/orgs","repos_url":"https://api.github.com/users/dvirsky/repos","events_url":"https://api.github.com/users/dvirsky/events{/privacy}","received_events_url":"https://api.github.com/users/dvirsky/received_events","type":"User","site_admin":false},"body":"This PR implements a mechanism for keyspace notifications in modules. \r\nThe implementation details and API are documented inside, but here is the gist of it:\r\n\r\n1. The module subscribes to notifications based on a mask of event types (identical to what core redis uses).\r\n2. When notifying modules, the dispatchers selects the subscribers by flags.\r\n3. It is the subscriber's job to filter further by key name, actual event, etc.\r\n4. Notifications aren't reentrant - i.e. if you subscribe to SET, and you set something from within the notification callback, this will not trigger the callback again (that would crash redis). \r\n5. However subscriber A can call a command that will trigger subscriber B (but B cannot trigger A back). \r\n6. Subscriptions work without any configuration - the server only dispatches events to modules if there are actualy subsribers. Checking if there are doesn't reduce performance in a measurable way (profiled to take 0.1% CPU time during purely write loads.\r\n\r\nThe test module now includes an example of a working notification subscriber. \r\n","created_at":"2017-11-27T21:35:27Z","updated_at":"2018-02-14T19:27:08Z","closed_at":"2018-02-14T19:27:08Z","merged_at":null,"merge_commit_sha":"b37b7e4a68d5a666cd0c02d3457989f12abb1ab3","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/antirez/redis/pulls/4479/commits","review_comments_url":"https://api.github.com/repos/antirez/redis/pulls/4479/comments","review_comment_url":"https://api.github.com/repos/antirez/redis/pulls/comments{/number}","comments_url":"https://api.github.com/repos/antirez/redis/issues/4479/comments","statuses_url":"https://api.github.com/repos/antirez/redis/statuses/2ee256ee63ac1bc58e4f5ea6beb20b4f5d58e0d5","head":{"label":"dvirsky:notify","ref":"notify","sha":"2ee256ee63ac1bc58e4f5ea6beb20b4f5d58e0d5","user":{"login":"dvirsky","id":503226,"avatar_url":"https://avatars2.githubusercontent.com/u/503226?v=4","gravatar_id":"","url":"https://api.github.com/users/dvirsky","html_url":"https://github.com/dvirsky","followers_url":"https://api.github.com/users/dvirsky/followers","following_url":"https://api.github.com/users/dvirsky/following{/other_user}","gists_url":"https://api.github.com/users/dvirsky/gists{/gist_id}","starred_url":"https://api.github.com/users/dvirsky/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dvirsky/subscriptions","organizations_url":"https://api.github.com/users/dvirsky/orgs","repos_url":"https://api.github.com/users/dvirsky/repos","events_url":"https://api.github.com/users/dvirsky/events{/privacy}","received_events_url":"https://api.github.com/users/dvirsky/received_events","type":"User","site_admin":false},"repo":{"id":59026059,"name":"redis","full_name":"dvirsky/redis","owner":{"login":"dvirsky","id":503226,"avatar_url":"https://avatars2.githubusercontent.com/u/503226?v=4","gravatar_id":"","url":"https://api.github.com/users/dvirsky","html_url":"https://github.com/dvirsky","followers_url":"https://api.github.com/users/dvirsky/followers","following_url":"https://api.github.com/users/dvirsky/following{/other_user}","gists_url":"https://api.github.com/users/dvirsky/gists{/gist_id}","starred_url":"https://api.github.com/users/dvirsky/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dvirsky/subscriptions","organizations_url":"https://api.github.com/users/dvirsky/orgs","repos_url":"https://api.github.com/users/dvirsky/repos","events_url":"https://api.github.com/users/dvirsky/events{/privacy}","received_events_url":"https://api.github.com/users/dvirsky/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/dvirsky/redis","description":"Redis is an in-memory database that persists on disk. The data model is key-value, but many different kind of values are supported: Strings, Lists, Sets, Sorted Sets, Hashes, HyperLogLogs, Bitmaps.","fork":true,"url":"https://api.github.com/repos/dvirsky/redis","forks_url":"https://api.github.com/repos/dvirsky/redis/forks","keys_url":"https://api.github.com/repos/dvirsky/redis/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dvirsky/redis/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dvirsky/redis/teams","hooks_url":"https://api.github.com/repos/dvirsky/redis/hooks","issue_events_url":"https://api.github.com/repos/dvirsky/redis/issues/events{/number}","events_url":"https://api.github.com/repos/dvirsky/redis/events","assignees_url":"https://api.github.com/repos/dvirsky/redis/assignees{/user}","branches_url":"https://api.github.com/repos/dvirsky/redis/branches{/branch}","tags_url":"https://api.github.com/repos/dvirsky/redis/tags","blobs_url":"https://api.github.com/repos/dvirsky/redis/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dvirsky/redis/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dvirsky/redis/git/refs{/sha}","trees_url":"https://api.github.com/repos/dvirsky/redis/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dvirsky/redis/statuses/{sha}","languages_url":"https://api.github.com/repos/dvirsky/redis/languages","stargazers_url":"https://api.github.com/repos/dvirsky/redis/stargazers","contributors_url":"https://api.github.com/repos/dvirsky/redis/contributors","subscribers_url":"https://api.github.com/repos/dvirsky/redis/subscribers","subscription_url":"https://api.github.com/repos/dvirsky/redis/subscription","commits_url":"https://api.github.com/repos/dvirsky/redis/commits{/sha}","git_commits_url":"https://api.github.com/repos/dvirsky/redis/git/commits{/sha}","comments_url":"https://api.github.com/repos/dvirsky/redis/comments{/number}","issue_comment_url":"https://api.github.com/repos/dvirsky/redis/issues/comments{/number}","contents_url":"https://api.github.com/repos/dvirsky/redis/contents/{+path}","compare_url":"https://api.github.com/repos/dvirsky/redis/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dvirsky/redis/merges","archive_url":"https://api.github.com/repos/dvirsky/redis/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dvirsky/redis/downloads","issues_url":"https://api.github.com/repos/dvirsky/redis/issues{/number}","pulls_url":"https://api.github.com/repos/dvirsky/redis/pulls{/number}","milestones_url":"https://api.github.com/repos/dvirsky/redis/milestones{/number}","notifications_url":"https://api.github.com/repos/dvirsky/redis/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dvirsky/redis/labels{/name}","releases_url":"https://api.github.com/repos/dvirsky/redis/releases{/id}","deployments_url":"https://api.github.com/repos/dvirsky/redis/deployments","created_at":"2016-05-17T13:42:15Z","updated_at":"2016-05-17T13:42:24Z","pushed_at":"2018-01-22T22:30:45Z","git_url":"git://github.com/dvirsky/redis.git","ssh_url":"git@github.com:dvirsky/redis.git","clone_url":"https://github.com/dvirsky/redis.git","svn_url":"https://github.com/dvirsky/redis","homepage":"http://redis.io","size":70149,"stargazers_count":0,"watchers_count":0,"language":"C","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"unstable"}},"base":{"label":"antirez:unstable","ref":"unstable","sha":"c2fa4b8a60c7d3c11c016f16f85d37188fa5c3f6","user":{"login":"antirez","id":65632,"avatar_url":"https://avatars0.githubusercontent.com/u/65632?v=4","gravatar_id":"","url":"https://api.github.com/users/antirez","html_url":"https://github.com/antirez","followers_url":"https://api.github.com/users/antirez/followers","following_url":"https://api.github.com/users/antirez/following{/other_user}","gists_url":"https://api.github.com/users/antirez/gists{/gist_id}","starred_url":"https://api.github.com/users/antirez/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/antirez/subscriptions","organizations_url":"https://api.github.com/users/antirez/orgs","repos_url":"https://api.github.com/users/antirez/repos","events_url":"https://api.github.com/users/antirez/events{/privacy}","received_events_url":"https://api.github.com/users/antirez/received_events","type":"User","site_admin":false},"repo":{"id":156018,"name":"redis","full_name":"antirez/redis","owner":{"login":"antirez","id":65632,"avatar_url":"https://avatars0.githubusercontent.com/u/65632?v=4","gravatar_id":"","url":"https://api.github.com/users/antirez","html_url":"https://github.com/antirez","followers_url":"https://api.github.com/users/antirez/followers","following_url":"https://api.github.com/users/antirez/following{/other_user}","gists_url":"https://api.github.com/users/antirez/gists{/gist_id}","starred_url":"https://api.github.com/users/antirez/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/antirez/subscriptions","organizations_url":"https://api.github.com/users/antirez/orgs","repos_url":"https://api.github.com/users/antirez/repos","events_url":"https://api.github.com/users/antirez/events{/privacy}","received_events_url":"https://api.github.com/users/antirez/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/antirez/redis","description":"Redis is an in-memory database that persists on disk. The data model is key-value, but many different kind of values are supported: Strings, Lists, Sets, Sorted Sets, Hashes, HyperLogLogs, Bitmaps.","fork":false,"url":"https://api.github.com/repos/antirez/redis","forks_url":"https://api.github.com/repos/antirez/redis/forks","keys_url":"https://api.github.com/repos/antirez/redis/keys{/key_id}","collaborators_url":"https://api.github.com/repos/antirez/redis/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/antirez/redis/teams","hooks_url":"https://api.github.com/repos/antirez/redis/hooks","issue_events_url":"https://api.github.com/repos/antirez/redis/issues/events{/number}","events_url":"https://api.github.com/repos/antirez/redis/events","assignees_url":"https://api.github.com/repos/antirez/redis/assignees{/user}","branches_url":"https://api.github.com/repos/antirez/redis/branches{/branch}","tags_url":"https://api.github.com/repos/antirez/redis/tags","blobs_url":"https://api.github.com/repos/antirez/redis/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/antirez/redis/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/antirez/redis/git/refs{/sha}","trees_url":"https://api.github.com/repos/antirez/redis/git/trees{/sha}","statuses_url":"https://api.github.com/repos/antirez/redis/statuses/{sha}","languages_url":"https://api.github.com/repos/antirez/redis/languages","stargazers_url":"https://api.github.com/repos/antirez/redis/stargazers","contributors_url":"https://api.github.com/repos/antirez/redis/contributors","subscribers_url":"https://api.github.com/repos/antirez/redis/subscribers","subscription_url":"https://api.github.com/repos/antirez/redis/subscription","commits_url":"https://api.github.com/repos/antirez/redis/commits{/sha}","git_commits_url":"https://api.github.com/repos/antirez/redis/git/commits{/sha}","comments_url":"https://api.github.com/repos/antirez/redis/comments{/number}","issue_comment_url":"https://api.github.com/repos/antirez/redis/issues/comments{/number}","contents_url":"https://api.github.com/repos/antirez/redis/contents/{+path}","compare_url":"https://api.github.com/repos/antirez/redis/compare/{base}...{head}","merges_url":"https://api.github.com/repos/antirez/redis/merges","archive_url":"https://api.github.com/repos/antirez/redis/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/antirez/redis/downloads","issues_url":"https://api.github.com/repos/antirez/redis/issues{/number}","pulls_url":"https://api.github.com/repos/antirez/redis/pulls{/number}","milestones_url":"https://api.github.com/repos/antirez/redis/milestones{/number}","notifications_url":"https://api.github.com/repos/antirez/redis/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/antirez/redis/labels{/name}","releases_url":"https://api.github.com/repos/antirez/redis/releases{/id}","deployments_url":"https://api.github.com/repos/antirez/redis/deployments","created_at":"2009-03-21T22:32:25Z","updated_at":"2018-02-14T19:08:18Z","pushed_at":"2018-02-14T02:57:45Z","git_url":"git://github.com/antirez/redis.git","ssh_url":"git@github.com:antirez/redis.git","clone_url":"https://github.com/antirez/redis.git","svn_url":"https://github.com/antirez/redis","homepage":"http://redis.io","size":71321,"stargazers_count":27532,"watchers_count":27532,"language":"C","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":10562,"mirror_url":null,"archived":false,"open_issues_count":1580,"license":{"key":"bsd-3-clause","name":"BSD 3-Clause \"New\" or \"Revised\" License","spdx_id":"BSD-3-Clause","url":"https://api.github.com/licenses/bsd-3-clause"},"forks":10562,"open_issues":1580,"watchers":27532,"default_branch":"unstable"}},"_links":{"self":{"href":"https://api.github.com/repos/antirez/redis/pulls/4479"},"html":{"href":"https://github.com/antirez/redis/pull/4479"},"issue":{"href":"https://api.github.com/repos/antirez/redis/issues/4479"},"comments":{"href":"https://api.github.com/repos/antirez/redis/issues/4479/comments"},"review_comments":{"href":"https://api.github.com/repos/antirez/redis/pulls/4479/comments"},"review_comment":{"href":"https://api.github.com/repos/antirez/redis/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/antirez/redis/pulls/4479/commits"},"statuses":{"href":"https://api.github.com/repos/antirez/redis/statuses/2ee256ee63ac1bc58e4f5ea6beb20b4f5d58e0d5"}},"author_association":"CONTRIBUTOR","merged":false,"mergeable":false,"rebaseable":false,"mergeable_state":"dirty","merged_by":null,"comments":28,"review_comments":4,"maintainer_can_modify":false,"commits":8,"additions":298,"deletions":36,"changed_files":5}}
{"actor":{"display_login":"dvirsky"}}