{"action":"created","comment":{"url":"https://api.github.com/repos/rails/rails/pulls/comments/72862885","id":72862885,"diff_hunk":"@@ -0,0 +1,78 @@\n+require 'active_support/core_ext/numeric/time'\n+\n+module ActiveJob\n+  # Provides behavior for retrying and discarding jobs on exceptions.\n+  module Exceptions\n+    extend ActiveSupport::Concern\n+\n+    module ClassMethods\n+      # Catch the exception and reschedule job for re-execution after so many seconds, for a specific number of attempts.\n+      # If the exception keeps getting raised beyond the specified number of attempts, the exception is allowed to\n+      # bubble up to the underlying queuing system, which may have its own retry mechanism or place it in a\n+      # holding queue for inspection.\n+      #\n+      # ==== Options\n+      # * <tt>:wait</tt> - Re-enqueues the job with the specified delay in seconds (default: 3 seconds)\n+      # * <tt>:attempts</tt> - Re-enqueues the job the specified number of times (default: 5 attempts)\n+      #\n+      # ==== Examples\n+      #\n+      #  class RemoteServiceJob < ActiveJob::Base\n+      #    retry_on Net::OpenTimeout, wait: 30.seconds, attempts: 10\n+      #\n+      #    def perform(*args)\n+      #      # Might raise Net::OpenTimeout when the remote service is down\n+      #    end\n+      #  end\n+      def retry_on(exception, wait: 3.seconds, attempts: 5)\n+        rescue_from exception do |error|\n+          logger.error \"Retrying #{self.class} in #{wait} seconds, due to a #{exception}. The original exception was #{error.cause.inspect}.\"\n+          retry_job wait: wait if executions < attempts\n+        end\n+      end\n+\n+      # Discard the job with no attempts to retry, if the exception is raised. This is useful when the subject of the job,\n+      # like an Active Record, is no longer available, and the job is thus no longer relevant.\n+      #\n+      # ==== Example\n+      #\n+      #  class SearchIndexingJob < ActiveJob::Base\n+      #    discard_on ActiveJob::DeserializationError\n+      #\n+      #    def perform(record)\n+      #      # Will raise ActiveJob::DeserializationError if the record can't be deserialized","path":"activejob/lib/active_job/exceptions.rb","position":43,"original_position":43,"commit_id":"b00214d214c6b0a2208d5861de1a7b158accddf0","original_commit_id":"b00214d214c6b0a2208d5861de1a7b158accddf0","user":{"login":"kaspth","id":350807,"avatar_url":"https://avatars.githubusercontent.com/u/350807?v=3","gravatar_id":"","url":"https://api.github.com/users/kaspth","html_url":"https://github.com/kaspth","followers_url":"https://api.github.com/users/kaspth/followers","following_url":"https://api.github.com/users/kaspth/following{/other_user}","gists_url":"https://api.github.com/users/kaspth/gists{/gist_id}","starred_url":"https://api.github.com/users/kaspth/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kaspth/subscriptions","organizations_url":"https://api.github.com/users/kaspth/orgs","repos_url":"https://api.github.com/users/kaspth/repos","events_url":"https://api.github.com/users/kaspth/events{/privacy}","received_events_url":"https://api.github.com/users/kaspth/received_events","type":"User","site_admin":false},"body":"I think our practice is to add a period to comments. Same goes for the other examples.","created_at":"2016-07-29T21:22:03Z","updated_at":"2016-07-29T21:22:04Z","html_url":"https://github.com/rails/rails/pull/25991#discussion_r72862885","pull_request_url":"https://api.github.com/repos/rails/rails/pulls/25991","_links":{"self":{"href":"https://api.github.com/repos/rails/rails/pulls/comments/72862885"},"html":{"href":"https://github.com/rails/rails/pull/25991#discussion_r72862885"},"pull_request":{"href":"https://api.github.com/repos/rails/rails/pulls/25991"}}},"pull_request":{"url":"https://api.github.com/repos/rails/rails/pulls/25991","id":79422905,"html_url":"https://github.com/rails/rails/pull/25991","diff_url":"https://github.com/rails/rails/pull/25991.diff","patch_url":"https://github.com/rails/rails/pull/25991.patch","issue_url":"https://api.github.com/repos/rails/rails/issues/25991","number":25991,"state":"open","locked":false,"title":"Add retry_on/discard_on for better exception handling","user":{"login":"dhh","id":2741,"avatar_url":"https://avatars.githubusercontent.com/u/2741?v=3","gravatar_id":"","url":"https://api.github.com/users/dhh","html_url":"https://github.com/dhh","followers_url":"https://api.github.com/users/dhh/followers","following_url":"https://api.github.com/users/dhh/following{/other_user}","gists_url":"https://api.github.com/users/dhh/gists{/gist_id}","starred_url":"https://api.github.com/users/dhh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dhh/subscriptions","organizations_url":"https://api.github.com/users/dhh/orgs","repos_url":"https://api.github.com/users/dhh/repos","events_url":"https://api.github.com/users/dhh/events{/privacy}","received_events_url":"https://api.github.com/users/dhh/received_events","type":"User","site_admin":false},"body":"Declarative exception handling of the most common kind: retrying and discarding.\r\n\r\n```ruby\r\nclass RemoteServiceJob < ActiveJob::Base\r\n  retry_on Net::OpenTimeout, wait: 30.seconds, attempts: 10\r\n\r\n  def perform(*args)\r\n    # Might raise Net::OpenTimeout when the remote service is down\r\n  end\r\nend\r\n\r\nclass SearchIndexingJob < ActiveJob::Base\r\n  discard_on ActiveJob::DeserializationError\r\n\r\n  def perform(record)\r\n    # Will raise ActiveJob::DeserializationError if the record can't be deserialized\r\n  end\r\nend\r\n```","created_at":"2016-07-29T20:55:19Z","updated_at":"2016-07-29T21:22:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a2d424d0caea02ec72693a35b691e4f0f7d6c93c","assignee":{"login":"dhh","id":2741,"avatar_url":"https://avatars.githubusercontent.com/u/2741?v=3","gravatar_id":"","url":"https://api.github.com/users/dhh","html_url":"https://github.com/dhh","followers_url":"https://api.github.com/users/dhh/followers","following_url":"https://api.github.com/users/dhh/following{/other_user}","gists_url":"https://api.github.com/users/dhh/gists{/gist_id}","starred_url":"https://api.github.com/users/dhh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dhh/subscriptions","organizations_url":"https://api.github.com/users/dhh/orgs","repos_url":"https://api.github.com/users/dhh/repos","events_url":"https://api.github.com/users/dhh/events{/privacy}","received_events_url":"https://api.github.com/users/dhh/received_events","type":"User","site_admin":false},"assignees":[{"login":"dhh","id":2741,"avatar_url":"https://avatars.githubusercontent.com/u/2741?v=3","gravatar_id":"","url":"https://api.github.com/users/dhh","html_url":"https://github.com/dhh","followers_url":"https://api.github.com/users/dhh/followers","following_url":"https://api.github.com/users/dhh/following{/other_user}","gists_url":"https://api.github.com/users/dhh/gists{/gist_id}","starred_url":"https://api.github.com/users/dhh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dhh/subscriptions","organizations_url":"https://api.github.com/users/dhh/orgs","repos_url":"https://api.github.com/users/dhh/repos","events_url":"https://api.github.com/users/dhh/events{/privacy}","received_events_url":"https://api.github.com/users/dhh/received_events","type":"User","site_admin":false}],"milestone":{"url":"https://api.github.com/repos/rails/rails/milestones/49","html_url":"https://github.com/rails/rails/milestones/5.1.0","labels_url":"https://api.github.com/repos/rails/rails/milestones/49/labels","id":1601639,"number":49,"title":"5.1.0","description":"","creator":{"login":"rafaelfranca","id":47848,"avatar_url":"https://avatars.githubusercontent.com/u/47848?v=3","gravatar_id":"","url":"https://api.github.com/users/rafaelfranca","html_url":"https://github.com/rafaelfranca","followers_url":"https://api.github.com/users/rafaelfranca/followers","following_url":"https://api.github.com/users/rafaelfranca/following{/other_user}","gists_url":"https://api.github.com/users/rafaelfranca/gists{/gist_id}","starred_url":"https://api.github.com/users/rafaelfranca/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rafaelfranca/subscriptions","organizations_url":"https://api.github.com/users/rafaelfranca/orgs","repos_url":"https://api.github.com/users/rafaelfranca/repos","events_url":"https://api.github.com/users/rafaelfranca/events{/privacy}","received_events_url":"https://api.github.com/users/rafaelfranca/received_events","type":"User","site_admin":false},"open_issues":20,"closed_issues":10,"state":"open","created_at":"2016-02-24T03:19:34Z","updated_at":"2016-07-29T21:06:50Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/rails/rails/pulls/25991/commits","review_comments_url":"https://api.github.com/repos/rails/rails/pulls/25991/comments","review_comment_url":"https://api.github.com/repos/rails/rails/pulls/comments{/number}","comments_url":"https://api.github.com/repos/rails/rails/issues/25991/comments","statuses_url":"https://api.github.com/repos/rails/rails/statuses/b00214d214c6b0a2208d5861de1a7b158accddf0","head":{"label":"rails:retry-and-discard-jobs","ref":"retry-and-discard-jobs","sha":"b00214d214c6b0a2208d5861de1a7b158accddf0","user":{"login":"rails","id":4223,"avatar_url":"https://avatars.githubusercontent.com/u/4223?v=3","gravatar_id":"","url":"https://api.github.com/users/rails","html_url":"https://github.com/rails","followers_url":"https://api.github.com/users/rails/followers","following_url":"https://api.github.com/users/rails/following{/other_user}","gists_url":"https://api.github.com/users/rails/gists{/gist_id}","starred_url":"https://api.github.com/users/rails/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rails/subscriptions","organizations_url":"https://api.github.com/users/rails/orgs","repos_url":"https://api.github.com/users/rails/repos","events_url":"https://api.github.com/users/rails/events{/privacy}","received_events_url":"https://api.github.com/users/rails/received_events","type":"Organization","site_admin":false},"repo":{"id":8514,"name":"rails","full_name":"rails/rails","owner":{"login":"rails","id":4223,"avatar_url":"https://avatars.githubusercontent.com/u/4223?v=3","gravatar_id":"","url":"https://api.github.com/users/rails","html_url":"https://github.com/rails","followers_url":"https://api.github.com/users/rails/followers","following_url":"https://api.github.com/users/rails/following{/other_user}","gists_url":"https://api.github.com/users/rails/gists{/gist_id}","starred_url":"https://api.github.com/users/rails/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rails/subscriptions","organizations_url":"https://api.github.com/users/rails/orgs","repos_url":"https://api.github.com/users/rails/repos","events_url":"https://api.github.com/users/rails/events{/privacy}","received_events_url":"https://api.github.com/users/rails/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/rails/rails","description":"Ruby on Rails","fork":false,"url":"https://api.github.com/repos/rails/rails","forks_url":"https://api.github.com/repos/rails/rails/forks","keys_url":"https://api.github.com/repos/rails/rails/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rails/rails/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rails/rails/teams","hooks_url":"https://api.github.com/repos/rails/rails/hooks","issue_events_url":"https://api.github.com/repos/rails/rails/issues/events{/number}","events_url":"https://api.github.com/repos/rails/rails/events","assignees_url":"https://api.github.com/repos/rails/rails/assignees{/user}","branches_url":"https://api.github.com/repos/rails/rails/branches{/branch}","tags_url":"https://api.github.com/repos/rails/rails/tags","blobs_url":"https://api.github.com/repos/rails/rails/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rails/rails/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rails/rails/git/refs{/sha}","trees_url":"https://api.github.com/repos/rails/rails/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rails/rails/statuses/{sha}","languages_url":"https://api.github.com/repos/rails/rails/languages","stargazers_url":"https://api.github.com/repos/rails/rails/stargazers","contributors_url":"https://api.github.com/repos/rails/rails/contributors","subscribers_url":"https://api.github.com/repos/rails/rails/subscribers","subscription_url":"https://api.github.com/repos/rails/rails/subscription","commits_url":"https://api.github.com/repos/rails/rails/commits{/sha}","git_commits_url":"https://api.github.com/repos/rails/rails/git/commits{/sha}","comments_url":"https://api.github.com/repos/rails/rails/comments{/number}","issue_comment_url":"https://api.github.com/repos/rails/rails/issues/comments{/number}","contents_url":"https://api.github.com/repos/rails/rails/contents/{+path}","compare_url":"https://api.github.com/repos/rails/rails/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rails/rails/merges","archive_url":"https://api.github.com/repos/rails/rails/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rails/rails/downloads","issues_url":"https://api.github.com/repos/rails/rails/issues{/number}","pulls_url":"https://api.github.com/repos/rails/rails/pulls{/number}","milestones_url":"https://api.github.com/repos/rails/rails/milestones{/number}","notifications_url":"https://api.github.com/repos/rails/rails/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rails/rails/labels{/name}","releases_url":"https://api.github.com/repos/rails/rails/releases{/id}","deployments_url":"https://api.github.com/repos/rails/rails/deployments","created_at":"2008-04-11T02:19:47Z","updated_at":"2016-07-29T20:11:14Z","pushed_at":"2016-07-29T21:21:10Z","git_url":"git://github.com/rails/rails.git","ssh_url":"git@github.com:rails/rails.git","clone_url":"https://github.com/rails/rails.git","svn_url":"https://github.com/rails/rails","homepage":"http://rubyonrails.org","size":334098,"stargazers_count":32195,"watchers_count":32195,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":13072,"mirror_url":null,"open_issues_count":1106,"forks":13072,"open_issues":1106,"watchers":32195,"default_branch":"master"}},"base":{"label":"rails:master","ref":"master","sha":"3916656f8e9700eb5f1cfc441ff66e1f12173683","user":{"login":"rails","id":4223,"avatar_url":"https://avatars.githubusercontent.com/u/4223?v=3","gravatar_id":"","url":"https://api.github.com/users/rails","html_url":"https://github.com/rails","followers_url":"https://api.github.com/users/rails/followers","following_url":"https://api.github.com/users/rails/following{/other_user}","gists_url":"https://api.github.com/users/rails/gists{/gist_id}","starred_url":"https://api.github.com/users/rails/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rails/subscriptions","organizations_url":"https://api.github.com/users/rails/orgs","repos_url":"https://api.github.com/users/rails/repos","events_url":"https://api.github.com/users/rails/events{/privacy}","received_events_url":"https://api.github.com/users/rails/received_events","type":"Organization","site_admin":false},"repo":{"id":8514,"name":"rails","full_name":"rails/rails","owner":{"login":"rails","id":4223,"avatar_url":"https://avatars.githubusercontent.com/u/4223?v=3","gravatar_id":"","url":"https://api.github.com/users/rails","html_url":"https://github.com/rails","followers_url":"https://api.github.com/users/rails/followers","following_url":"https://api.github.com/users/rails/following{/other_user}","gists_url":"https://api.github.com/users/rails/gists{/gist_id}","starred_url":"https://api.github.com/users/rails/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rails/subscriptions","organizations_url":"https://api.github.com/users/rails/orgs","repos_url":"https://api.github.com/users/rails/repos","events_url":"https://api.github.com/users/rails/events{/privacy}","received_events_url":"https://api.github.com/users/rails/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/rails/rails","description":"Ruby on Rails","fork":false,"url":"https://api.github.com/repos/rails/rails","forks_url":"https://api.github.com/repos/rails/rails/forks","keys_url":"https://api.github.com/repos/rails/rails/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rails/rails/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rails/rails/teams","hooks_url":"https://api.github.com/repos/rails/rails/hooks","issue_events_url":"https://api.github.com/repos/rails/rails/issues/events{/number}","events_url":"https://api.github.com/repos/rails/rails/events","assignees_url":"https://api.github.com/repos/rails/rails/assignees{/user}","branches_url":"https://api.github.com/repos/rails/rails/branches{/branch}","tags_url":"https://api.github.com/repos/rails/rails/tags","blobs_url":"https://api.github.com/repos/rails/rails/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rails/rails/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rails/rails/git/refs{/sha}","trees_url":"https://api.github.com/repos/rails/rails/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rails/rails/statuses/{sha}","languages_url":"https://api.github.com/repos/rails/rails/languages","stargazers_url":"https://api.github.com/repos/rails/rails/stargazers","contributors_url":"https://api.github.com/repos/rails/rails/contributors","subscribers_url":"https://api.github.com/repos/rails/rails/subscribers","subscription_url":"https://api.github.com/repos/rails/rails/subscription","commits_url":"https://api.github.com/repos/rails/rails/commits{/sha}","git_commits_url":"https://api.github.com/repos/rails/rails/git/commits{/sha}","comments_url":"https://api.github.com/repos/rails/rails/comments{/number}","issue_comment_url":"https://api.github.com/repos/rails/rails/issues/comments{/number}","contents_url":"https://api.github.com/repos/rails/rails/contents/{+path}","compare_url":"https://api.github.com/repos/rails/rails/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rails/rails/merges","archive_url":"https://api.github.com/repos/rails/rails/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rails/rails/downloads","issues_url":"https://api.github.com/repos/rails/rails/issues{/number}","pulls_url":"https://api.github.com/repos/rails/rails/pulls{/number}","milestones_url":"https://api.github.com/repos/rails/rails/milestones{/number}","notifications_url":"https://api.github.com/repos/rails/rails/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rails/rails/labels{/name}","releases_url":"https://api.github.com/repos/rails/rails/releases{/id}","deployments_url":"https://api.github.com/repos/rails/rails/deployments","created_at":"2008-04-11T02:19:47Z","updated_at":"2016-07-29T20:11:14Z","pushed_at":"2016-07-29T21:21:10Z","git_url":"git://github.com/rails/rails.git","ssh_url":"git@github.com:rails/rails.git","clone_url":"https://github.com/rails/rails.git","svn_url":"https://github.com/rails/rails","homepage":"http://rubyonrails.org","size":334098,"stargazers_count":32195,"watchers_count":32195,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":13072,"mirror_url":null,"open_issues_count":1106,"forks":13072,"open_issues":1106,"watchers":32195,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rails/rails/pulls/25991"},"html":{"href":"https://github.com/rails/rails/pull/25991"},"issue":{"href":"https://api.github.com/repos/rails/rails/issues/25991"},"comments":{"href":"https://api.github.com/repos/rails/rails/issues/25991/comments"},"review_comments":{"href":"https://api.github.com/repos/rails/rails/pulls/25991/comments"},"review_comment":{"href":"https://api.github.com/repos/rails/rails/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/rails/rails/pulls/25991/commits"},"statuses":{"href":"https://api.github.com/repos/rails/rails/statuses/b00214d214c6b0a2208d5861de1a7b158accddf0"}}}}
{"actor":{"display_login":"kaspth"}}