activejob 5.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +80 -0
- data/MIT-LICENSE +21 -0
- data/README.md +126 -0
- data/lib/active_job.rb +39 -0
- data/lib/active_job/arguments.rb +165 -0
- data/lib/active_job/base.rb +74 -0
- data/lib/active_job/callbacks.rb +155 -0
- data/lib/active_job/configured_job.rb +18 -0
- data/lib/active_job/core.rb +158 -0
- data/lib/active_job/enqueuing.rb +59 -0
- data/lib/active_job/exceptions.rb +134 -0
- data/lib/active_job/execution.rb +49 -0
- data/lib/active_job/gem_version.rb +17 -0
- data/lib/active_job/logging.rb +130 -0
- data/lib/active_job/queue_adapter.rb +60 -0
- data/lib/active_job/queue_adapters.rb +139 -0
- data/lib/active_job/queue_adapters/async_adapter.rb +116 -0
- data/lib/active_job/queue_adapters/backburner_adapter.rb +36 -0
- data/lib/active_job/queue_adapters/delayed_job_adapter.rb +47 -0
- data/lib/active_job/queue_adapters/inline_adapter.rb +23 -0
- data/lib/active_job/queue_adapters/qu_adapter.rb +46 -0
- data/lib/active_job/queue_adapters/que_adapter.rb +39 -0
- data/lib/active_job/queue_adapters/queue_classic_adapter.rb +58 -0
- data/lib/active_job/queue_adapters/resque_adapter.rb +53 -0
- data/lib/active_job/queue_adapters/sidekiq_adapter.rb +47 -0
- data/lib/active_job/queue_adapters/sneakers_adapter.rb +48 -0
- data/lib/active_job/queue_adapters/sucker_punch_adapter.rb +49 -0
- data/lib/active_job/queue_adapters/test_adapter.rb +67 -0
- data/lib/active_job/queue_name.rb +49 -0
- data/lib/active_job/queue_priority.rb +43 -0
- data/lib/active_job/railtie.rb +34 -0
- data/lib/active_job/test_case.rb +11 -0
- data/lib/active_job/test_helper.rb +456 -0
- data/lib/active_job/translation.rb +13 -0
- data/lib/active_job/version.rb +10 -0
- data/lib/rails/generators/job/job_generator.rb +40 -0
- data/lib/rails/generators/job/templates/application_job.rb.tt +9 -0
- data/lib/rails/generators/job/templates/job.rb.tt +9 -0
- metadata +110 -0
@@ -0,0 +1,155 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/callbacks"
|
4
|
+
|
5
|
+
module ActiveJob
|
6
|
+
# = Active Job Callbacks
|
7
|
+
#
|
8
|
+
# Active Job provides hooks during the life cycle of a job. Callbacks allow you
|
9
|
+
# to trigger logic during this cycle. Available callbacks are:
|
10
|
+
#
|
11
|
+
# * <tt>before_enqueue</tt>
|
12
|
+
# * <tt>around_enqueue</tt>
|
13
|
+
# * <tt>after_enqueue</tt>
|
14
|
+
# * <tt>before_perform</tt>
|
15
|
+
# * <tt>around_perform</tt>
|
16
|
+
# * <tt>after_perform</tt>
|
17
|
+
#
|
18
|
+
# NOTE: Calling the same callback multiple times will overwrite previous callback definitions.
|
19
|
+
#
|
20
|
+
module Callbacks
|
21
|
+
extend ActiveSupport::Concern
|
22
|
+
include ActiveSupport::Callbacks
|
23
|
+
|
24
|
+
class << self
|
25
|
+
include ActiveSupport::Callbacks
|
26
|
+
define_callbacks :execute
|
27
|
+
end
|
28
|
+
|
29
|
+
included do
|
30
|
+
define_callbacks :perform
|
31
|
+
define_callbacks :enqueue
|
32
|
+
end
|
33
|
+
|
34
|
+
# These methods will be included into any Active Job object, adding
|
35
|
+
# callbacks for +perform+ and +enqueue+ methods.
|
36
|
+
module ClassMethods
|
37
|
+
# Defines a callback that will get called right before the
|
38
|
+
# job's perform method is executed.
|
39
|
+
#
|
40
|
+
# class VideoProcessJob < ActiveJob::Base
|
41
|
+
# queue_as :default
|
42
|
+
#
|
43
|
+
# before_perform do |job|
|
44
|
+
# UserMailer.notify_video_started_processing(job.arguments.first)
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# def perform(video_id)
|
48
|
+
# Video.find(video_id).process
|
49
|
+
# end
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
def before_perform(*filters, &blk)
|
53
|
+
set_callback(:perform, :before, *filters, &blk)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Defines a callback that will get called right after the
|
57
|
+
# job's perform method has finished.
|
58
|
+
#
|
59
|
+
# class VideoProcessJob < ActiveJob::Base
|
60
|
+
# queue_as :default
|
61
|
+
#
|
62
|
+
# after_perform do |job|
|
63
|
+
# UserMailer.notify_video_processed(job.arguments.first)
|
64
|
+
# end
|
65
|
+
#
|
66
|
+
# def perform(video_id)
|
67
|
+
# Video.find(video_id).process
|
68
|
+
# end
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
def after_perform(*filters, &blk)
|
72
|
+
set_callback(:perform, :after, *filters, &blk)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Defines a callback that will get called around the job's perform method.
|
76
|
+
#
|
77
|
+
# class VideoProcessJob < ActiveJob::Base
|
78
|
+
# queue_as :default
|
79
|
+
#
|
80
|
+
# around_perform do |job, block|
|
81
|
+
# UserMailer.notify_video_started_processing(job.arguments.first)
|
82
|
+
# block.call
|
83
|
+
# UserMailer.notify_video_processed(job.arguments.first)
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
# def perform(video_id)
|
87
|
+
# Video.find(video_id).process
|
88
|
+
# end
|
89
|
+
# end
|
90
|
+
#
|
91
|
+
def around_perform(*filters, &blk)
|
92
|
+
set_callback(:perform, :around, *filters, &blk)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Defines a callback that will get called right before the
|
96
|
+
# job is enqueued.
|
97
|
+
#
|
98
|
+
# class VideoProcessJob < ActiveJob::Base
|
99
|
+
# queue_as :default
|
100
|
+
#
|
101
|
+
# before_enqueue do |job|
|
102
|
+
# $statsd.increment "enqueue-video-job.try"
|
103
|
+
# end
|
104
|
+
#
|
105
|
+
# def perform(video_id)
|
106
|
+
# Video.find(video_id).process
|
107
|
+
# end
|
108
|
+
# end
|
109
|
+
#
|
110
|
+
def before_enqueue(*filters, &blk)
|
111
|
+
set_callback(:enqueue, :before, *filters, &blk)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Defines a callback that will get called right after the
|
115
|
+
# job is enqueued.
|
116
|
+
#
|
117
|
+
# class VideoProcessJob < ActiveJob::Base
|
118
|
+
# queue_as :default
|
119
|
+
#
|
120
|
+
# after_enqueue do |job|
|
121
|
+
# $statsd.increment "enqueue-video-job.success"
|
122
|
+
# end
|
123
|
+
#
|
124
|
+
# def perform(video_id)
|
125
|
+
# Video.find(video_id).process
|
126
|
+
# end
|
127
|
+
# end
|
128
|
+
#
|
129
|
+
def after_enqueue(*filters, &blk)
|
130
|
+
set_callback(:enqueue, :after, *filters, &blk)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Defines a callback that will get called around the enqueueing
|
134
|
+
# of the job.
|
135
|
+
#
|
136
|
+
# class VideoProcessJob < ActiveJob::Base
|
137
|
+
# queue_as :default
|
138
|
+
#
|
139
|
+
# around_enqueue do |job, block|
|
140
|
+
# $statsd.time "video-job.process" do
|
141
|
+
# block.call
|
142
|
+
# end
|
143
|
+
# end
|
144
|
+
#
|
145
|
+
# def perform(video_id)
|
146
|
+
# Video.find(video_id).process
|
147
|
+
# end
|
148
|
+
# end
|
149
|
+
#
|
150
|
+
def around_enqueue(*filters, &blk)
|
151
|
+
set_callback(:enqueue, :around, *filters, &blk)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveJob
|
4
|
+
class ConfiguredJob #:nodoc:
|
5
|
+
def initialize(job_class, options = {})
|
6
|
+
@options = options
|
7
|
+
@job_class = job_class
|
8
|
+
end
|
9
|
+
|
10
|
+
def perform_now(*args)
|
11
|
+
@job_class.new(*args).perform_now
|
12
|
+
end
|
13
|
+
|
14
|
+
def perform_later(*args)
|
15
|
+
@job_class.new(*args).enqueue @options
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveJob
|
4
|
+
# Provides general behavior that will be included into every Active Job
|
5
|
+
# object that inherits from ActiveJob::Base.
|
6
|
+
module Core
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
# Job arguments
|
11
|
+
attr_accessor :arguments
|
12
|
+
attr_writer :serialized_arguments
|
13
|
+
|
14
|
+
# Timestamp when the job should be performed
|
15
|
+
attr_accessor :scheduled_at
|
16
|
+
|
17
|
+
# Job Identifier
|
18
|
+
attr_accessor :job_id
|
19
|
+
|
20
|
+
# Queue in which the job will reside.
|
21
|
+
attr_writer :queue_name
|
22
|
+
|
23
|
+
# Priority that the job will have (lower is more priority).
|
24
|
+
attr_writer :priority
|
25
|
+
|
26
|
+
# ID optionally provided by adapter
|
27
|
+
attr_accessor :provider_job_id
|
28
|
+
|
29
|
+
# Number of times this job has been executed (which increments on every retry, like after an exception).
|
30
|
+
attr_accessor :executions
|
31
|
+
|
32
|
+
# I18n.locale to be used during the job.
|
33
|
+
attr_accessor :locale
|
34
|
+
end
|
35
|
+
|
36
|
+
# These methods will be included into any Active Job object, adding
|
37
|
+
# helpers for de/serialization and creation of job instances.
|
38
|
+
module ClassMethods
|
39
|
+
# Creates a new job instance from a hash created with +serialize+
|
40
|
+
def deserialize(job_data)
|
41
|
+
job = job_data["job_class"].constantize.new
|
42
|
+
job.deserialize(job_data)
|
43
|
+
job
|
44
|
+
end
|
45
|
+
|
46
|
+
# Creates a job preconfigured with the given options. You can call
|
47
|
+
# perform_later with the job arguments to enqueue the job with the
|
48
|
+
# preconfigured options
|
49
|
+
#
|
50
|
+
# ==== Options
|
51
|
+
# * <tt>:wait</tt> - Enqueues the job with the specified delay
|
52
|
+
# * <tt>:wait_until</tt> - Enqueues the job at the time specified
|
53
|
+
# * <tt>:queue</tt> - Enqueues the job on the specified queue
|
54
|
+
# * <tt>:priority</tt> - Enqueues the job with the specified priority
|
55
|
+
#
|
56
|
+
# ==== Examples
|
57
|
+
#
|
58
|
+
# VideoJob.set(queue: :some_queue).perform_later(Video.last)
|
59
|
+
# VideoJob.set(wait: 5.minutes).perform_later(Video.last)
|
60
|
+
# VideoJob.set(wait_until: Time.now.tomorrow).perform_later(Video.last)
|
61
|
+
# VideoJob.set(queue: :some_queue, wait: 5.minutes).perform_later(Video.last)
|
62
|
+
# VideoJob.set(queue: :some_queue, wait_until: Time.now.tomorrow).perform_later(Video.last)
|
63
|
+
# VideoJob.set(queue: :some_queue, wait: 5.minutes, priority: 10).perform_later(Video.last)
|
64
|
+
def set(options = {})
|
65
|
+
ConfiguredJob.new(self, options)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Creates a new job instance. Takes the arguments that will be
|
70
|
+
# passed to the perform method.
|
71
|
+
def initialize(*arguments)
|
72
|
+
@arguments = arguments
|
73
|
+
@job_id = SecureRandom.uuid
|
74
|
+
@queue_name = self.class.queue_name
|
75
|
+
@priority = self.class.priority
|
76
|
+
@executions = 0
|
77
|
+
end
|
78
|
+
|
79
|
+
# Returns a hash with the job data that can safely be passed to the
|
80
|
+
# queueing adapter.
|
81
|
+
def serialize
|
82
|
+
{
|
83
|
+
"job_class" => self.class.name,
|
84
|
+
"job_id" => job_id,
|
85
|
+
"provider_job_id" => provider_job_id,
|
86
|
+
"queue_name" => queue_name,
|
87
|
+
"priority" => priority,
|
88
|
+
"arguments" => serialize_arguments_if_needed(arguments),
|
89
|
+
"executions" => executions,
|
90
|
+
"locale" => I18n.locale.to_s
|
91
|
+
}
|
92
|
+
end
|
93
|
+
|
94
|
+
# Attaches the stored job data to the current instance. Receives a hash
|
95
|
+
# returned from +serialize+
|
96
|
+
#
|
97
|
+
# ==== Examples
|
98
|
+
#
|
99
|
+
# class DeliverWebhookJob < ActiveJob::Base
|
100
|
+
# attr_writer :attempt_number
|
101
|
+
#
|
102
|
+
# def attempt_number
|
103
|
+
# @attempt_number ||= 0
|
104
|
+
# end
|
105
|
+
#
|
106
|
+
# def serialize
|
107
|
+
# super.merge('attempt_number' => attempt_number + 1)
|
108
|
+
# end
|
109
|
+
#
|
110
|
+
# def deserialize(job_data)
|
111
|
+
# super
|
112
|
+
# self.attempt_number = job_data['attempt_number']
|
113
|
+
# end
|
114
|
+
#
|
115
|
+
# rescue_from(Timeout::Error) do |exception|
|
116
|
+
# raise exception if attempt_number > 5
|
117
|
+
# retry_job(wait: 10)
|
118
|
+
# end
|
119
|
+
# end
|
120
|
+
def deserialize(job_data)
|
121
|
+
self.job_id = job_data["job_id"]
|
122
|
+
self.provider_job_id = job_data["provider_job_id"]
|
123
|
+
self.queue_name = job_data["queue_name"]
|
124
|
+
self.priority = job_data["priority"]
|
125
|
+
self.serialized_arguments = job_data["arguments"]
|
126
|
+
self.executions = job_data["executions"]
|
127
|
+
self.locale = job_data["locale"] || I18n.locale.to_s
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
def serialize_arguments_if_needed(arguments)
|
132
|
+
if arguments_serialized?
|
133
|
+
@serialized_arguments
|
134
|
+
else
|
135
|
+
serialize_arguments(arguments)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def deserialize_arguments_if_needed
|
140
|
+
if arguments_serialized?
|
141
|
+
@arguments = deserialize_arguments(@serialized_arguments)
|
142
|
+
@serialized_arguments = nil
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def serialize_arguments(arguments)
|
147
|
+
Arguments.serialize(arguments)
|
148
|
+
end
|
149
|
+
|
150
|
+
def deserialize_arguments(serialized_args)
|
151
|
+
Arguments.deserialize(serialized_args)
|
152
|
+
end
|
153
|
+
|
154
|
+
def arguments_serialized?
|
155
|
+
defined?(@serialized_arguments) && @serialized_arguments
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_job/arguments"
|
4
|
+
|
5
|
+
module ActiveJob
|
6
|
+
# Provides behavior for enqueuing jobs.
|
7
|
+
module Enqueuing
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
# Includes the +perform_later+ method for job initialization.
|
11
|
+
module ClassMethods
|
12
|
+
# Push a job onto the queue. The arguments must be legal JSON types
|
13
|
+
# (+string+, +int+, +float+, +nil+, +true+, +false+, +hash+ or +array+) or
|
14
|
+
# GlobalID::Identification instances. Arbitrary Ruby objects
|
15
|
+
# are not supported.
|
16
|
+
#
|
17
|
+
# Returns an instance of the job class queued with arguments available in
|
18
|
+
# Job#arguments.
|
19
|
+
def perform_later(*args)
|
20
|
+
job_or_instantiate(*args).enqueue
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
def job_or_instantiate(*args) # :doc:
|
25
|
+
args.first.is_a?(self) ? args.first : new(*args)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Enqueues the job to be performed by the queue adapter.
|
30
|
+
#
|
31
|
+
# ==== Options
|
32
|
+
# * <tt>:wait</tt> - Enqueues the job with the specified delay
|
33
|
+
# * <tt>:wait_until</tt> - Enqueues the job at the time specified
|
34
|
+
# * <tt>:queue</tt> - Enqueues the job on the specified queue
|
35
|
+
# * <tt>:priority</tt> - Enqueues the job with the specified priority
|
36
|
+
#
|
37
|
+
# ==== Examples
|
38
|
+
#
|
39
|
+
# my_job_instance.enqueue
|
40
|
+
# my_job_instance.enqueue wait: 5.minutes
|
41
|
+
# my_job_instance.enqueue queue: :important
|
42
|
+
# my_job_instance.enqueue wait_until: Date.tomorrow.midnight
|
43
|
+
# my_job_instance.enqueue priority: 10
|
44
|
+
def enqueue(options = {})
|
45
|
+
self.scheduled_at = options[:wait].seconds.from_now.to_f if options[:wait]
|
46
|
+
self.scheduled_at = options[:wait_until].to_f if options[:wait_until]
|
47
|
+
self.queue_name = self.class.queue_name_from_part(options[:queue]) if options[:queue]
|
48
|
+
self.priority = options[:priority].to_i if options[:priority]
|
49
|
+
run_callbacks :enqueue do
|
50
|
+
if scheduled_at
|
51
|
+
self.class.queue_adapter.enqueue_at self, scheduled_at
|
52
|
+
else
|
53
|
+
self.class.queue_adapter.enqueue self
|
54
|
+
end
|
55
|
+
end
|
56
|
+
self
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/numeric/time"
|
4
|
+
|
5
|
+
module ActiveJob
|
6
|
+
# Provides behavior for retrying and discarding jobs on exceptions.
|
7
|
+
module Exceptions
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
# Catch the exception and reschedule job for re-execution after so many seconds, for a specific number of attempts.
|
12
|
+
# If the exception keeps getting raised beyond the specified number of attempts, the exception is allowed to
|
13
|
+
# bubble up to the underlying queuing system, which may have its own retry mechanism or place it in a
|
14
|
+
# holding queue for inspection.
|
15
|
+
#
|
16
|
+
# You can also pass a block that'll be invoked if the retry attempts fail for custom logic rather than letting
|
17
|
+
# the exception bubble up. This block is yielded with the job instance as the first and the error instance as the second parameter.
|
18
|
+
#
|
19
|
+
# ==== Options
|
20
|
+
# * <tt>:wait</tt> - Re-enqueues the job with a delay specified either in seconds (default: 3 seconds),
|
21
|
+
# as a computing proc that the number of executions so far as an argument, or as a symbol reference of
|
22
|
+
# <tt>:exponentially_longer</tt>, which applies the wait algorithm of <tt>(executions ** 4) + 2</tt>
|
23
|
+
# (first wait 3s, then 18s, then 83s, etc)
|
24
|
+
# * <tt>:attempts</tt> - Re-enqueues the job the specified number of times (default: 5 attempts)
|
25
|
+
# * <tt>:queue</tt> - Re-enqueues the job on a different queue
|
26
|
+
# * <tt>:priority</tt> - Re-enqueues the job with a different priority
|
27
|
+
#
|
28
|
+
# ==== Examples
|
29
|
+
#
|
30
|
+
# class RemoteServiceJob < ActiveJob::Base
|
31
|
+
# retry_on CustomAppException # defaults to 3s wait, 5 attempts
|
32
|
+
# retry_on AnotherCustomAppException, wait: ->(executions) { executions * 2 }
|
33
|
+
# retry_on(YetAnotherCustomAppException) do |job, error|
|
34
|
+
# ExceptionNotifier.caught(error)
|
35
|
+
# end
|
36
|
+
# retry_on ActiveRecord::Deadlocked, wait: 5.seconds, attempts: 3
|
37
|
+
# retry_on Net::OpenTimeout, wait: :exponentially_longer, attempts: 10
|
38
|
+
#
|
39
|
+
# def perform(*args)
|
40
|
+
# # Might raise CustomAppException, AnotherCustomAppException, or YetAnotherCustomAppException for something domain specific
|
41
|
+
# # Might raise ActiveRecord::Deadlocked when a local db deadlock is detected
|
42
|
+
# # Might raise Net::OpenTimeout when the remote service is down
|
43
|
+
# end
|
44
|
+
# end
|
45
|
+
def retry_on(exception, wait: 3.seconds, attempts: 5, queue: nil, priority: nil)
|
46
|
+
rescue_from exception do |error|
|
47
|
+
if executions < attempts
|
48
|
+
logger.error "Retrying #{self.class} in #{wait} seconds, due to a #{exception}. The original exception was #{error.cause.inspect}."
|
49
|
+
retry_job wait: determine_delay(wait), queue: queue, priority: priority
|
50
|
+
else
|
51
|
+
if block_given?
|
52
|
+
yield self, error
|
53
|
+
else
|
54
|
+
logger.error "Stopped retrying #{self.class} due to a #{exception}, which reoccurred on #{executions} attempts. The original exception was #{error.cause.inspect}."
|
55
|
+
raise error
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Discard the job with no attempts to retry, if the exception is raised. This is useful when the subject of the job,
|
62
|
+
# like an Active Record, is no longer available, and the job is thus no longer relevant.
|
63
|
+
#
|
64
|
+
# You can also pass a block that'll be invoked. This block is yielded with the job instance as the first and the error instance as the second parameter.
|
65
|
+
#
|
66
|
+
# ==== Example
|
67
|
+
#
|
68
|
+
# class SearchIndexingJob < ActiveJob::Base
|
69
|
+
# discard_on ActiveJob::DeserializationError
|
70
|
+
# discard_on(CustomAppException) do |job, error|
|
71
|
+
# ExceptionNotifier.caught(error)
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# def perform(record)
|
75
|
+
# # Will raise ActiveJob::DeserializationError if the record can't be deserialized
|
76
|
+
# # Might raise CustomAppException for something domain specific
|
77
|
+
# end
|
78
|
+
# end
|
79
|
+
def discard_on(exception)
|
80
|
+
rescue_from exception do |error|
|
81
|
+
if block_given?
|
82
|
+
yield self, error
|
83
|
+
else
|
84
|
+
logger.error "Discarded #{self.class} due to a #{exception}. The original exception was #{error.cause.inspect}."
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Reschedules the job to be re-executed. This is useful in combination
|
91
|
+
# with the +rescue_from+ option. When you rescue an exception from your job
|
92
|
+
# you can ask Active Job to retry performing your job.
|
93
|
+
#
|
94
|
+
# ==== Options
|
95
|
+
# * <tt>:wait</tt> - Enqueues the job with the specified delay in seconds
|
96
|
+
# * <tt>:wait_until</tt> - Enqueues the job at the time specified
|
97
|
+
# * <tt>:queue</tt> - Enqueues the job on the specified queue
|
98
|
+
# * <tt>:priority</tt> - Enqueues the job with the specified priority
|
99
|
+
#
|
100
|
+
# ==== Examples
|
101
|
+
#
|
102
|
+
# class SiteScraperJob < ActiveJob::Base
|
103
|
+
# rescue_from(ErrorLoadingSite) do
|
104
|
+
# retry_job queue: :low_priority
|
105
|
+
# end
|
106
|
+
#
|
107
|
+
# def perform(*args)
|
108
|
+
# # raise ErrorLoadingSite if cannot scrape
|
109
|
+
# end
|
110
|
+
# end
|
111
|
+
def retry_job(options = {})
|
112
|
+
enqueue options
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
def determine_delay(seconds_or_duration_or_algorithm)
|
117
|
+
case seconds_or_duration_or_algorithm
|
118
|
+
when :exponentially_longer
|
119
|
+
(executions**4) + 2
|
120
|
+
when ActiveSupport::Duration
|
121
|
+
duration = seconds_or_duration_or_algorithm
|
122
|
+
duration.to_i
|
123
|
+
when Integer
|
124
|
+
seconds = seconds_or_duration_or_algorithm
|
125
|
+
seconds
|
126
|
+
when Proc
|
127
|
+
algorithm = seconds_or_duration_or_algorithm
|
128
|
+
algorithm.call(executions)
|
129
|
+
else
|
130
|
+
raise "Couldn't determine a delay based on #{seconds_or_duration_or_algorithm.inspect}"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|