{"action":"closed","number":160,"pull_request":{"url":"https://api.github.com/repos/hanami/utils/pulls/160","id":89417352,"html_url":"https://github.com/hanami/utils/pull/160","diff_url":"https://github.com/hanami/utils/pull/160.diff","patch_url":"https://github.com/hanami/utils/pull/160.patch","issue_url":"https://api.github.com/repos/hanami/utils/issues/160","number":160,"state":"closed","locked":false,"title":"Introducing Hanami::Events","user":{"login":"jodosha","id":5089,"avatar_url":"https://avatars.githubusercontent.com/u/5089?v=3","gravatar_id":"","url":"https://api.github.com/users/jodosha","html_url":"https://github.com/jodosha","followers_url":"https://api.github.com/users/jodosha/followers","following_url":"https://api.github.com/users/jodosha/following{/other_user}","gists_url":"https://api.github.com/users/jodosha/gists{/gist_id}","starred_url":"https://api.github.com/users/jodosha/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jodosha/subscriptions","organizations_url":"https://api.github.com/users/jodosha/orgs","repos_url":"https://api.github.com/users/jodosha/repos","events_url":"https://api.github.com/users/jodosha/events{/privacy}","received_events_url":"https://api.github.com/users/jodosha/received_events","type":"User","site_admin":false},"body":"## Basic events framework for Hanami\n### Usage\n#### Subscribe With A Proc\n\n``` ruby\nrequire 'concurrent'\nrequire 'hanami/events'\nrequire 'ostruct'\n\nHanami::Events.subscribe('signup') do |event|\n  puts \"New signup: #{event[:user].email}\"\nend\n\nuser = OpenStruct.new(id: 1, email: \"user@hanamirb.org\")\nHanami::Events.broadcast('signup', user: user)\n\n  # => \"New signup: user@hanamirb.org\n```\n#### Subscribe With An object\n\n``` ruby\nrequire 'concurrent'\nrequire 'hanami/events'\nrequire 'ostruct'\n\nclass WelcomeMailer\n  def call(event)\n    puts \"New welcome message for: #{event[:user].email}\"\n  end\nend\n\nHanami::Events.subscribe('signup', WelcomeMailer.new)\n\nuser = OpenStruct.new(id: 1, email: \"user@hanamirb.org\")\nHanami::Events.broadcast('signup', user: user)\n\n  # => \"New welcome message for: user@hanamirb.org\n```\n#### Include Mixin\n\n``` ruby\nrequire 'concurrent'\nrequire 'hanami/events'\nrequire 'ostruct'\n\nclass Signup\n  include Hanami::Events\n\n  def call(params)\n    user = OpenStruct.new(params)\n    broadcast('signup', user: user)\n  end\nend\n\nHanami::Events.subscribe('signup') do |event|\n  puts \"New signup: #{event[:user].email}\"\nend\n\nSignup.new.call(email: \"user@hanamirb.org\")\n  # => \"New signup: user@hanamirb.org\n```\n\n---\n### Useful for\n\nThis can be useful for:\n- Automatic logging https://github.com/hanami/hanami/issues/484\n- Move mailers to apps https://github.com/hanami/hanami/issues/648\n- Async/distributed jobs\n#### Automatic Logging\n\nAll the Hanami frameworks can broadcast events for operations that we want to automatically log. Things like action response, rendered templates/layouts, database queries/commands. The logger can subscribe to these events and emit a new entry.\n#### Move mailers to apps\n\nSee https://github.com/hanami/hanami/issues/648#issuecomment-253855250\n#### Async/Distributed Jobs\n\nThe proposed implementation ships with a memory backend as dispatcher for the events. Which is fine for basic setups, but it has the downside of being volatile.\n\nIn the future, third-party devs can implement a backend for async/distributed mechanisms like Sidekiq or Apache Kafka.\n\n---\n\n@hanami/core-team @hanami/contributors Please review. 💚 \n","created_at":"2016-10-14T16:47:41Z","updated_at":"2016-12-20T08:47:48Z","closed_at":"2016-12-20T08:47:48Z","merged_at":null,"merge_commit_sha":"37590da2106f0b1c5160fe53ccf00f12ab359204","assignee":{"login":"jodosha","id":5089,"avatar_url":"https://avatars.githubusercontent.com/u/5089?v=3","gravatar_id":"","url":"https://api.github.com/users/jodosha","html_url":"https://github.com/jodosha","followers_url":"https://api.github.com/users/jodosha/followers","following_url":"https://api.github.com/users/jodosha/following{/other_user}","gists_url":"https://api.github.com/users/jodosha/gists{/gist_id}","starred_url":"https://api.github.com/users/jodosha/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jodosha/subscriptions","organizations_url":"https://api.github.com/users/jodosha/orgs","repos_url":"https://api.github.com/users/jodosha/repos","events_url":"https://api.github.com/users/jodosha/events{/privacy}","received_events_url":"https://api.github.com/users/jodosha/received_events","type":"User","site_admin":false},"assignees":[{"login":"jodosha","id":5089,"avatar_url":"https://avatars.githubusercontent.com/u/5089?v=3","gravatar_id":"","url":"https://api.github.com/users/jodosha","html_url":"https://github.com/jodosha","followers_url":"https://api.github.com/users/jodosha/followers","following_url":"https://api.github.com/users/jodosha/following{/other_user}","gists_url":"https://api.github.com/users/jodosha/gists{/gist_id}","starred_url":"https://api.github.com/users/jodosha/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jodosha/subscriptions","organizations_url":"https://api.github.com/users/jodosha/orgs","repos_url":"https://api.github.com/users/jodosha/repos","events_url":"https://api.github.com/users/jodosha/events{/privacy}","received_events_url":"https://api.github.com/users/jodosha/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/hanami/utils/pulls/160/commits","review_comments_url":"https://api.github.com/repos/hanami/utils/pulls/160/comments","review_comment_url":"https://api.github.com/repos/hanami/utils/pulls/comments{/number}","comments_url":"https://api.github.com/repos/hanami/utils/issues/160/comments","statuses_url":"https://api.github.com/repos/hanami/utils/statuses/31a48101176cbaca2f3354421a3fab6ebe2d3ae9","head":{"label":"hanami:hanami-events","ref":"hanami-events","sha":"31a48101176cbaca2f3354421a3fab6ebe2d3ae9","user":{"login":"hanami","id":3210273,"avatar_url":"https://avatars.githubusercontent.com/u/3210273?v=3","gravatar_id":"","url":"https://api.github.com/users/hanami","html_url":"https://github.com/hanami","followers_url":"https://api.github.com/users/hanami/followers","following_url":"https://api.github.com/users/hanami/following{/other_user}","gists_url":"https://api.github.com/users/hanami/gists{/gist_id}","starred_url":"https://api.github.com/users/hanami/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hanami/subscriptions","organizations_url":"https://api.github.com/users/hanami/orgs","repos_url":"https://api.github.com/users/hanami/repos","events_url":"https://api.github.com/users/hanami/events{/privacy}","received_events_url":"https://api.github.com/users/hanami/received_events","type":"Organization","site_admin":false},"repo":{"id":11949423,"name":"utils","full_name":"hanami/utils","owner":{"login":"hanami","id":3210273,"avatar_url":"https://avatars.githubusercontent.com/u/3210273?v=3","gravatar_id":"","url":"https://api.github.com/users/hanami","html_url":"https://github.com/hanami","followers_url":"https://api.github.com/users/hanami/followers","following_url":"https://api.github.com/users/hanami/following{/other_user}","gists_url":"https://api.github.com/users/hanami/gists{/gist_id}","starred_url":"https://api.github.com/users/hanami/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hanami/subscriptions","organizations_url":"https://api.github.com/users/hanami/orgs","repos_url":"https://api.github.com/users/hanami/repos","events_url":"https://api.github.com/users/hanami/events{/privacy}","received_events_url":"https://api.github.com/users/hanami/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/hanami/utils","description":"Ruby core extentions and class utilities for Hanami","fork":false,"url":"https://api.github.com/repos/hanami/utils","forks_url":"https://api.github.com/repos/hanami/utils/forks","keys_url":"https://api.github.com/repos/hanami/utils/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hanami/utils/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hanami/utils/teams","hooks_url":"https://api.github.com/repos/hanami/utils/hooks","issue_events_url":"https://api.github.com/repos/hanami/utils/issues/events{/number}","events_url":"https://api.github.com/repos/hanami/utils/events","assignees_url":"https://api.github.com/repos/hanami/utils/assignees{/user}","branches_url":"https://api.github.com/repos/hanami/utils/branches{/branch}","tags_url":"https://api.github.com/repos/hanami/utils/tags","blobs_url":"https://api.github.com/repos/hanami/utils/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hanami/utils/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hanami/utils/git/refs{/sha}","trees_url":"https://api.github.com/repos/hanami/utils/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hanami/utils/statuses/{sha}","languages_url":"https://api.github.com/repos/hanami/utils/languages","stargazers_url":"https://api.github.com/repos/hanami/utils/stargazers","contributors_url":"https://api.github.com/repos/hanami/utils/contributors","subscribers_url":"https://api.github.com/repos/hanami/utils/subscribers","subscription_url":"https://api.github.com/repos/hanami/utils/subscription","commits_url":"https://api.github.com/repos/hanami/utils/commits{/sha}","git_commits_url":"https://api.github.com/repos/hanami/utils/git/commits{/sha}","comments_url":"https://api.github.com/repos/hanami/utils/comments{/number}","issue_comment_url":"https://api.github.com/repos/hanami/utils/issues/comments{/number}","contents_url":"https://api.github.com/repos/hanami/utils/contents/{+path}","compare_url":"https://api.github.com/repos/hanami/utils/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hanami/utils/merges","archive_url":"https://api.github.com/repos/hanami/utils/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hanami/utils/downloads","issues_url":"https://api.github.com/repos/hanami/utils/issues{/number}","pulls_url":"https://api.github.com/repos/hanami/utils/pulls{/number}","milestones_url":"https://api.github.com/repos/hanami/utils/milestones{/number}","notifications_url":"https://api.github.com/repos/hanami/utils/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hanami/utils/labels{/name}","releases_url":"https://api.github.com/repos/hanami/utils/releases{/id}","deployments_url":"https://api.github.com/repos/hanami/utils/deployments","created_at":"2013-08-07T12:29:45Z","updated_at":"2016-11-13T19:55:08Z","pushed_at":"2016-12-20T08:46:02Z","git_url":"git://github.com/hanami/utils.git","ssh_url":"git@github.com:hanami/utils.git","clone_url":"https://github.com/hanami/utils.git","svn_url":"https://github.com/hanami/utils","homepage":"http://hanamirb.org","size":621,"stargazers_count":109,"watchers_count":109,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":78,"mirror_url":null,"open_issues_count":1,"forks":78,"open_issues":1,"watchers":109,"default_branch":"master"}},"base":{"label":"hanami:master","ref":"master","sha":"444cc6625ac217cafb21a4a6caf20747216fddbe","user":{"login":"hanami","id":3210273,"avatar_url":"https://avatars.githubusercontent.com/u/3210273?v=3","gravatar_id":"","url":"https://api.github.com/users/hanami","html_url":"https://github.com/hanami","followers_url":"https://api.github.com/users/hanami/followers","following_url":"https://api.github.com/users/hanami/following{/other_user}","gists_url":"https://api.github.com/users/hanami/gists{/gist_id}","starred_url":"https://api.github.com/users/hanami/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hanami/subscriptions","organizations_url":"https://api.github.com/users/hanami/orgs","repos_url":"https://api.github.com/users/hanami/repos","events_url":"https://api.github.com/users/hanami/events{/privacy}","received_events_url":"https://api.github.com/users/hanami/received_events","type":"Organization","site_admin":false},"repo":{"id":11949423,"name":"utils","full_name":"hanami/utils","owner":{"login":"hanami","id":3210273,"avatar_url":"https://avatars.githubusercontent.com/u/3210273?v=3","gravatar_id":"","url":"https://api.github.com/users/hanami","html_url":"https://github.com/hanami","followers_url":"https://api.github.com/users/hanami/followers","following_url":"https://api.github.com/users/hanami/following{/other_user}","gists_url":"https://api.github.com/users/hanami/gists{/gist_id}","starred_url":"https://api.github.com/users/hanami/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hanami/subscriptions","organizations_url":"https://api.github.com/users/hanami/orgs","repos_url":"https://api.github.com/users/hanami/repos","events_url":"https://api.github.com/users/hanami/events{/privacy}","received_events_url":"https://api.github.com/users/hanami/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/hanami/utils","description":"Ruby core extentions and class utilities for Hanami","fork":false,"url":"https://api.github.com/repos/hanami/utils","forks_url":"https://api.github.com/repos/hanami/utils/forks","keys_url":"https://api.github.com/repos/hanami/utils/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hanami/utils/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hanami/utils/teams","hooks_url":"https://api.github.com/repos/hanami/utils/hooks","issue_events_url":"https://api.github.com/repos/hanami/utils/issues/events{/number}","events_url":"https://api.github.com/repos/hanami/utils/events","assignees_url":"https://api.github.com/repos/hanami/utils/assignees{/user}","branches_url":"https://api.github.com/repos/hanami/utils/branches{/branch}","tags_url":"https://api.github.com/repos/hanami/utils/tags","blobs_url":"https://api.github.com/repos/hanami/utils/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hanami/utils/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hanami/utils/git/refs{/sha}","trees_url":"https://api.github.com/repos/hanami/utils/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hanami/utils/statuses/{sha}","languages_url":"https://api.github.com/repos/hanami/utils/languages","stargazers_url":"https://api.github.com/repos/hanami/utils/stargazers","contributors_url":"https://api.github.com/repos/hanami/utils/contributors","subscribers_url":"https://api.github.com/repos/hanami/utils/subscribers","subscription_url":"https://api.github.com/repos/hanami/utils/subscription","commits_url":"https://api.github.com/repos/hanami/utils/commits{/sha}","git_commits_url":"https://api.github.com/repos/hanami/utils/git/commits{/sha}","comments_url":"https://api.github.com/repos/hanami/utils/comments{/number}","issue_comment_url":"https://api.github.com/repos/hanami/utils/issues/comments{/number}","contents_url":"https://api.github.com/repos/hanami/utils/contents/{+path}","compare_url":"https://api.github.com/repos/hanami/utils/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hanami/utils/merges","archive_url":"https://api.github.com/repos/hanami/utils/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hanami/utils/downloads","issues_url":"https://api.github.com/repos/hanami/utils/issues{/number}","pulls_url":"https://api.github.com/repos/hanami/utils/pulls{/number}","milestones_url":"https://api.github.com/repos/hanami/utils/milestones{/number}","notifications_url":"https://api.github.com/repos/hanami/utils/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hanami/utils/labels{/name}","releases_url":"https://api.github.com/repos/hanami/utils/releases{/id}","deployments_url":"https://api.github.com/repos/hanami/utils/deployments","created_at":"2013-08-07T12:29:45Z","updated_at":"2016-11-13T19:55:08Z","pushed_at":"2016-12-20T08:46:02Z","git_url":"git://github.com/hanami/utils.git","ssh_url":"git@github.com:hanami/utils.git","clone_url":"https://github.com/hanami/utils.git","svn_url":"https://github.com/hanami/utils","homepage":"http://hanamirb.org","size":621,"stargazers_count":109,"watchers_count":109,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":78,"mirror_url":null,"open_issues_count":1,"forks":78,"open_issues":1,"watchers":109,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/hanami/utils/pulls/160"},"html":{"href":"https://github.com/hanami/utils/pull/160"},"issue":{"href":"https://api.github.com/repos/hanami/utils/issues/160"},"comments":{"href":"https://api.github.com/repos/hanami/utils/issues/160/comments"},"review_comments":{"href":"https://api.github.com/repos/hanami/utils/pulls/160/comments"},"review_comment":{"href":"https://api.github.com/repos/hanami/utils/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/hanami/utils/pulls/160/commits"},"statuses":{"href":"https://api.github.com/repos/hanami/utils/statuses/31a48101176cbaca2f3354421a3fab6ebe2d3ae9"}},"merged":false,"mergeable":false,"mergeable_state":"dirty","merged_by":null,"comments":20,"review_comments":8,"commits":2,"additions":444,"deletions":5,"changed_files":7}}
{"actor":{"display_login":"jodosha"}}