activejob 7.0.8.4 → 7.1.0.beta1
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 +4 -4
- data/CHANGELOG.md +109 -167
- data/MIT-LICENSE +1 -1
- data/README.md +2 -2
- data/lib/active_job/arguments.rb +14 -25
- data/lib/active_job/base.rb +1 -1
- data/lib/active_job/callbacks.rb +1 -4
- data/lib/active_job/configured_job.rb +4 -0
- data/lib/active_job/core.rb +3 -1
- data/lib/active_job/deprecator.rb +7 -0
- data/lib/active_job/enqueuing.rb +30 -0
- data/lib/active_job/exceptions.rb +30 -0
- data/lib/active_job/execution.rb +5 -1
- data/lib/active_job/gem_version.rb +4 -4
- data/lib/active_job/instrumentation.rb +18 -10
- data/lib/active_job/log_subscriber.rb +77 -7
- data/lib/active_job/queue_adapter.rb +13 -2
- data/lib/active_job/queue_adapters/async_adapter.rb +2 -2
- data/lib/active_job/queue_adapters/backburner_adapter.rb +7 -3
- data/lib/active_job/queue_adapters/delayed_job_adapter.rb +1 -1
- data/lib/active_job/queue_adapters/inline_adapter.rb +1 -1
- data/lib/active_job/queue_adapters/queue_classic_adapter.rb +4 -4
- data/lib/active_job/queue_adapters/resque_adapter.rb +1 -1
- data/lib/active_job/queue_adapters/sidekiq_adapter.rb +42 -14
- data/lib/active_job/queue_adapters/sneakers_adapter.rb +1 -1
- data/lib/active_job/queue_adapters/sucker_punch_adapter.rb +2 -2
- data/lib/active_job/queue_adapters/test_adapter.rb +2 -2
- data/lib/active_job/queue_adapters.rb +8 -7
- data/lib/active_job/queue_priority.rb +18 -1
- data/lib/active_job/railtie.rb +25 -6
- data/lib/active_job/serializers/big_decimal_serializer.rb +22 -0
- data/lib/active_job/serializers/duration_serializer.rb +4 -2
- data/lib/active_job/serializers.rb +7 -3
- data/lib/active_job/test_helper.rb +23 -3
- data/lib/active_job/version.rb +1 -1
- data/lib/active_job.rb +26 -4
- data/lib/rails/generators/job/USAGE +19 -0
- data/lib/rails/generators/job/job_generator.rb +6 -2
- data/lib/rails/generators/job/templates/job.rb.tt +1 -1
- metadata +13 -11
- data/lib/active_job/queue_adapters/que_adapter.rb +0 -61
@@ -1,6 +1,18 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveJob
|
4
|
+
class << self
|
5
|
+
private
|
6
|
+
def instrument_enqueue_all(queue_adapter, jobs)
|
7
|
+
payload = { adapter: queue_adapter, jobs: jobs }
|
8
|
+
ActiveSupport::Notifications.instrument("enqueue_all.active_job", payload) do
|
9
|
+
result = yield payload
|
10
|
+
payload[:enqueued_count] = result
|
11
|
+
result
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
4
16
|
module Instrumentation # :nodoc:
|
5
17
|
extend ActiveSupport::Concern
|
6
18
|
|
@@ -21,19 +33,15 @@ module ActiveJob
|
|
21
33
|
end
|
22
34
|
|
23
35
|
def instrument(operation, payload = {}, &block)
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
if defined?(@_halted_callback_hook_called) && @_halted_callback_hook_called
|
28
|
-
event_payload[:aborted] = true
|
29
|
-
@_halted_callback_hook_called = nil
|
30
|
-
end
|
36
|
+
payload[:job] = self
|
37
|
+
payload[:adapter] = queue_adapter
|
31
38
|
|
39
|
+
ActiveSupport::Notifications.instrument("#{operation}.active_job", payload) do
|
40
|
+
value = block.call if block
|
41
|
+
payload[:aborted] = @_halted_callback_hook_called if defined?(@_halted_callback_hook_called)
|
42
|
+
@_halted_callback_hook_called = nil
|
32
43
|
value
|
33
44
|
end
|
34
|
-
|
35
|
-
ActiveSupport::Notifications.instrument \
|
36
|
-
"#{operation}.active_job", payload.merge(adapter: queue_adapter, job: self), &enhanced_block
|
37
45
|
end
|
38
46
|
|
39
47
|
def halted_callback_hook(*)
|
@@ -1,10 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/core_ext/string/filters"
|
4
3
|
require "active_support/log_subscriber"
|
5
4
|
|
6
5
|
module ActiveJob
|
7
6
|
class LogSubscriber < ActiveSupport::LogSubscriber # :nodoc:
|
7
|
+
class_attribute :backtrace_cleaner, default: ActiveSupport::BacktraceCleaner.new
|
8
|
+
|
8
9
|
def enqueue(event)
|
9
10
|
job = event.payload[:job]
|
10
11
|
ex = event.payload[:exception_object] || job.enqueue_error
|
@@ -23,6 +24,7 @@ module ActiveJob
|
|
23
24
|
end
|
24
25
|
end
|
25
26
|
end
|
27
|
+
subscribe_log_level :enqueue, :info
|
26
28
|
|
27
29
|
def enqueue_at(event)
|
28
30
|
job = event.payload[:job]
|
@@ -38,10 +40,38 @@ module ActiveJob
|
|
38
40
|
end
|
39
41
|
else
|
40
42
|
info do
|
41
|
-
"Enqueued #{job.class.name} (Job ID: #{job.job_id}) to #{queue_name(event)} at #{scheduled_at(event)
|
43
|
+
"Enqueued #{job.class.name} (Job ID: #{job.job_id}) to #{queue_name(event)} at #{scheduled_at(event)}" + args_info(job)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
subscribe_log_level :enqueue_at, :info
|
48
|
+
|
49
|
+
def enqueue_all(event)
|
50
|
+
info do
|
51
|
+
jobs = event.payload[:jobs]
|
52
|
+
adapter = event.payload[:adapter]
|
53
|
+
enqueued_count = event.payload[:enqueued_count]
|
54
|
+
|
55
|
+
if enqueued_count == jobs.size
|
56
|
+
enqueued_jobs_message(adapter, jobs)
|
57
|
+
elsif jobs.any?(&:successfully_enqueued?)
|
58
|
+
enqueued_jobs = jobs.select(&:successfully_enqueued?)
|
59
|
+
|
60
|
+
failed_enqueue_count = jobs.size - enqueued_count
|
61
|
+
if failed_enqueue_count == 0
|
62
|
+
enqueued_jobs_message(adapter, enqueued_jobs)
|
63
|
+
else
|
64
|
+
"#{enqueued_jobs_message(adapter, enqueued_jobs)}. "\
|
65
|
+
"Failed enqueuing #{failed_enqueue_count} #{'job'.pluralize(failed_enqueue_count)}"
|
66
|
+
end
|
67
|
+
else
|
68
|
+
failed_enqueue_count = jobs.size - enqueued_count
|
69
|
+
"Failed enqueuing #{failed_enqueue_count} #{'job'.pluralize(failed_enqueue_count)} "\
|
70
|
+
"to #{ActiveJob.adapter_name(adapter)}"
|
42
71
|
end
|
43
72
|
end
|
44
73
|
end
|
74
|
+
subscribe_log_level :enqueue_all, :info
|
45
75
|
|
46
76
|
def perform_start(event)
|
47
77
|
info do
|
@@ -49,6 +79,7 @@ module ActiveJob
|
|
49
79
|
"Performing #{job.class.name} (Job ID: #{job.job_id}) from #{queue_name(event)} enqueued at #{job.enqueued_at}" + args_info(job)
|
50
80
|
end
|
51
81
|
end
|
82
|
+
subscribe_log_level :perform_start, :info
|
52
83
|
|
53
84
|
def perform(event)
|
54
85
|
job = event.payload[:job]
|
@@ -67,6 +98,7 @@ module ActiveJob
|
|
67
98
|
end
|
68
99
|
end
|
69
100
|
end
|
101
|
+
subscribe_log_level :perform, :info
|
70
102
|
|
71
103
|
def enqueue_retry(event)
|
72
104
|
job = event.payload[:job]
|
@@ -75,34 +107,37 @@ module ActiveJob
|
|
75
107
|
|
76
108
|
info do
|
77
109
|
if ex
|
78
|
-
"Retrying #{job.class} in #{wait.to_i} seconds, due to a #{ex.class}."
|
110
|
+
"Retrying #{job.class} (Job ID: #{job.job_id}) after #{job.executions} attempts in #{wait.to_i} seconds, due to a #{ex.class} (#{ex.message})."
|
79
111
|
else
|
80
|
-
"Retrying #{job.class} in #{wait.to_i} seconds."
|
112
|
+
"Retrying #{job.class} (Job ID: #{job.job_id}) after #{job.executions} attempts in #{wait.to_i} seconds."
|
81
113
|
end
|
82
114
|
end
|
83
115
|
end
|
116
|
+
subscribe_log_level :enqueue_retry, :info
|
84
117
|
|
85
118
|
def retry_stopped(event)
|
86
119
|
job = event.payload[:job]
|
87
120
|
ex = event.payload[:error]
|
88
121
|
|
89
122
|
error do
|
90
|
-
"Stopped retrying #{job.class} due to a #{ex.class}, which reoccurred on #{job.executions} attempts."
|
123
|
+
"Stopped retrying #{job.class} (Job ID: #{job.job_id}) due to a #{ex.class} (#{ex.message}), which reoccurred on #{job.executions} attempts."
|
91
124
|
end
|
92
125
|
end
|
126
|
+
subscribe_log_level :enqueue_retry, :error
|
93
127
|
|
94
128
|
def discard(event)
|
95
129
|
job = event.payload[:job]
|
96
130
|
ex = event.payload[:error]
|
97
131
|
|
98
132
|
error do
|
99
|
-
"Discarded #{job.class} due to a #{ex.class}."
|
133
|
+
"Discarded #{job.class} (Job ID: #{job.job_id}) due to a #{ex.class} (#{ex.message})."
|
100
134
|
end
|
101
135
|
end
|
136
|
+
subscribe_log_level :discard, :error
|
102
137
|
|
103
138
|
private
|
104
139
|
def queue_name(event)
|
105
|
-
event.payload[:adapter]
|
140
|
+
ActiveJob.adapter_name(event.payload[:adapter]) + "(#{event.payload[:job].queue_name})"
|
106
141
|
end
|
107
142
|
|
108
143
|
def args_info(job)
|
@@ -134,6 +169,41 @@ module ActiveJob
|
|
134
169
|
def logger
|
135
170
|
ActiveJob::Base.logger
|
136
171
|
end
|
172
|
+
|
173
|
+
def info(progname = nil, &block)
|
174
|
+
return unless super
|
175
|
+
|
176
|
+
if ActiveJob.verbose_enqueue_logs
|
177
|
+
log_enqueue_source
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def error(progname = nil, &block)
|
182
|
+
return unless super
|
183
|
+
|
184
|
+
if ActiveJob.verbose_enqueue_logs
|
185
|
+
log_enqueue_source
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def log_enqueue_source
|
190
|
+
source = extract_enqueue_source_location(caller)
|
191
|
+
|
192
|
+
if source
|
193
|
+
logger.info("↳ #{source}")
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def extract_enqueue_source_location(locations)
|
198
|
+
backtrace_cleaner.clean(locations.lazy).first
|
199
|
+
end
|
200
|
+
|
201
|
+
def enqueued_jobs_message(adapter, enqueued_jobs)
|
202
|
+
enqueued_count = enqueued_jobs.size
|
203
|
+
job_classes_counts = enqueued_jobs.map(&:class).tally.sort_by { |_k, v| -v }
|
204
|
+
"Enqueued #{enqueued_count} #{'job'.pluralize(enqueued_count)} to #{ActiveJob.adapter_name(adapter)}"\
|
205
|
+
" (#{job_classes_counts.map { |klass, count| "#{count} #{klass}" }.join(', ')})"
|
206
|
+
end
|
137
207
|
end
|
138
208
|
end
|
139
209
|
|
@@ -3,7 +3,18 @@
|
|
3
3
|
require "active_support/core_ext/string/inflections"
|
4
4
|
|
5
5
|
module ActiveJob
|
6
|
-
|
6
|
+
class << self
|
7
|
+
def adapter_name(adapter) # :nodoc:
|
8
|
+
return adapter.queue_adapter_name if adapter.respond_to?(:queue_adapter_name)
|
9
|
+
|
10
|
+
adapter_class = adapter.is_a?(Module) ? adapter : adapter.class
|
11
|
+
"#{adapter_class.name.demodulize.delete_suffix('Adapter')}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# = Active Job Queue adapter
|
16
|
+
#
|
17
|
+
# The +ActiveJob::QueueAdapter+ module is used to load the
|
7
18
|
# correct adapter. The default queue adapter is the +:async+ queue.
|
8
19
|
module QueueAdapter # :nodoc:
|
9
20
|
extend ActiveSupport::Concern
|
@@ -41,7 +52,7 @@ module ActiveJob
|
|
41
52
|
assign_adapter(name_or_adapter.to_s, queue_adapter)
|
42
53
|
else
|
43
54
|
if queue_adapter?(name_or_adapter)
|
44
|
-
adapter_name =
|
55
|
+
adapter_name = ActiveJob.adapter_name(name_or_adapter).underscore
|
45
56
|
assign_adapter(adapter_name, name_or_adapter)
|
46
57
|
else
|
47
58
|
raise ArgumentError
|
@@ -7,7 +7,7 @@ require "concurrent/utility/processor_counter"
|
|
7
7
|
|
8
8
|
module ActiveJob
|
9
9
|
module QueueAdapters
|
10
|
-
#
|
10
|
+
# = Active Job Async adapter
|
11
11
|
#
|
12
12
|
# The Async adapter runs jobs with an in-process thread pool.
|
13
13
|
#
|
@@ -95,7 +95,7 @@ module ActiveJob
|
|
95
95
|
|
96
96
|
def enqueue_at(job, timestamp, queue_name:)
|
97
97
|
delay = timestamp - Time.current.to_f
|
98
|
-
if delay > 0
|
98
|
+
if !immediate && delay > 0
|
99
99
|
Concurrent::ScheduledTask.execute(delay, args: [job], executor: executor, &:perform)
|
100
100
|
else
|
101
101
|
enqueue(job, queue_name: queue_name)
|
@@ -4,7 +4,7 @@ require "backburner"
|
|
4
4
|
|
5
5
|
module ActiveJob
|
6
6
|
module QueueAdapters
|
7
|
-
#
|
7
|
+
# = Backburner adapter for Active Job
|
8
8
|
#
|
9
9
|
# Backburner is a beanstalkd-powered job queue that can handle a very
|
10
10
|
# high volume of jobs. You create background jobs and place them on
|
@@ -16,12 +16,16 @@ module ActiveJob
|
|
16
16
|
# Rails.application.config.active_job.queue_adapter = :backburner
|
17
17
|
class BackburnerAdapter
|
18
18
|
def enqueue(job) # :nodoc:
|
19
|
-
Backburner::Worker.enqueue(JobWrapper, [job.serialize], queue: job.queue_name, pri: job.priority)
|
19
|
+
response = Backburner::Worker.enqueue(JobWrapper, [job.serialize], queue: job.queue_name, pri: job.priority)
|
20
|
+
job.provider_job_id = response[:id] if response.is_a?(Hash)
|
21
|
+
response
|
20
22
|
end
|
21
23
|
|
22
24
|
def enqueue_at(job, timestamp) # :nodoc:
|
23
25
|
delay = timestamp - Time.current.to_f
|
24
|
-
Backburner::Worker.enqueue(JobWrapper, [job.serialize], queue: job.queue_name, pri: job.priority, delay: delay)
|
26
|
+
response = Backburner::Worker.enqueue(JobWrapper, [job.serialize], queue: job.queue_name, pri: job.priority, delay: delay)
|
27
|
+
job.provider_job_id = response[:id] if response.is_a?(Hash)
|
28
|
+
response
|
25
29
|
end
|
26
30
|
|
27
31
|
class JobWrapper # :nodoc:
|
@@ -5,7 +5,7 @@ require "active_support/core_ext/string/inflections"
|
|
5
5
|
|
6
6
|
module ActiveJob
|
7
7
|
module QueueAdapters
|
8
|
-
#
|
8
|
+
# = Delayed Job adapter for Active Job
|
9
9
|
#
|
10
10
|
# Delayed::Job (or DJ) encapsulates the common pattern of asynchronously
|
11
11
|
# executing longer tasks in the background. Although DJ can have many
|
@@ -4,7 +4,7 @@ require "queue_classic"
|
|
4
4
|
|
5
5
|
module ActiveJob
|
6
6
|
module QueueAdapters
|
7
|
-
#
|
7
|
+
# = queue_classic adapter for Active Job
|
8
8
|
#
|
9
9
|
# queue_classic provides a simple interface to a PostgreSQL-backed message
|
10
10
|
# queue. queue_classic specializes in concurrent locking and minimizing
|
@@ -37,10 +37,10 @@ module ActiveJob
|
|
37
37
|
qc_job
|
38
38
|
end
|
39
39
|
|
40
|
-
# Builds a
|
40
|
+
# Builds a +QC::Queue+ object to schedule jobs on.
|
41
41
|
#
|
42
|
-
# If you have a custom
|
43
|
-
#
|
42
|
+
# If you have a custom +QC::Queue+ subclass you'll need to subclass
|
43
|
+
# +ActiveJob::QueueAdapters::QueueClassicAdapter+ and override the
|
44
44
|
# <tt>build_queue</tt> method.
|
45
45
|
def build_queue(queue_name)
|
46
46
|
QC::Queue.new(queue_name)
|
@@ -16,7 +16,7 @@ end
|
|
16
16
|
|
17
17
|
module ActiveJob
|
18
18
|
module QueueAdapters
|
19
|
-
#
|
19
|
+
# = Resque adapter for Active Job
|
20
20
|
#
|
21
21
|
# Resque (pronounced like "rescue") is a Redis-backed library for creating
|
22
22
|
# background jobs, placing those jobs on multiple queues, and processing
|
@@ -1,14 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
gem "sidekiq", ">= 4.1.0"
|
3
4
|
require "sidekiq"
|
4
5
|
|
5
6
|
module ActiveJob
|
6
7
|
module QueueAdapters
|
7
|
-
#
|
8
|
+
# = Sidekiq adapter for Active Job
|
8
9
|
#
|
9
10
|
# Simple, efficient background processing for Ruby. Sidekiq uses threads to
|
10
11
|
# handle many jobs at the same time in the same process. It does not
|
11
|
-
# require Rails but will integrate tightly with it to make background
|
12
|
+
# require \Rails but will integrate tightly with it to make background
|
12
13
|
# processing dead simple.
|
13
14
|
#
|
14
15
|
# Read more about Sidekiq {here}[http://sidekiq.org].
|
@@ -18,21 +19,48 @@ module ActiveJob
|
|
18
19
|
# Rails.application.config.active_job.queue_adapter = :sidekiq
|
19
20
|
class SidekiqAdapter
|
20
21
|
def enqueue(job) # :nodoc:
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
"queue" => job.queue_name,
|
26
|
-
"args" => [ job.serialize ]
|
22
|
+
job.provider_job_id = JobWrapper.set(
|
23
|
+
wrapped: job.class,
|
24
|
+
queue: job.queue_name
|
25
|
+
).perform_async(job.serialize)
|
27
26
|
end
|
28
27
|
|
29
28
|
def enqueue_at(job, timestamp) # :nodoc:
|
30
|
-
job.provider_job_id =
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
29
|
+
job.provider_job_id = JobWrapper.set(
|
30
|
+
wrapped: job.class,
|
31
|
+
queue: job.queue_name,
|
32
|
+
).perform_at(timestamp, job.serialize)
|
33
|
+
end
|
34
|
+
|
35
|
+
def enqueue_all(jobs) # :nodoc:
|
36
|
+
enqueued_count = 0
|
37
|
+
jobs.group_by(&:class).each do |job_class, same_class_jobs|
|
38
|
+
same_class_jobs.group_by(&:queue_name).each do |queue, same_class_and_queue_jobs|
|
39
|
+
immediate_jobs, scheduled_jobs = same_class_and_queue_jobs.partition { |job| job.scheduled_at.nil? }
|
40
|
+
|
41
|
+
if immediate_jobs.any?
|
42
|
+
jids = Sidekiq::Client.push_bulk(
|
43
|
+
"class" => JobWrapper,
|
44
|
+
"wrapped" => job_class,
|
45
|
+
"queue" => queue,
|
46
|
+
"args" => immediate_jobs.map { |job| [job.serialize] },
|
47
|
+
)
|
48
|
+
enqueued_count += jids.compact.size
|
49
|
+
end
|
50
|
+
|
51
|
+
if scheduled_jobs.any?
|
52
|
+
jids = Sidekiq::Client.push_bulk(
|
53
|
+
"class" => JobWrapper,
|
54
|
+
"wrapped" => job_class,
|
55
|
+
"queue" => queue,
|
56
|
+
"args" => scheduled_jobs.map { |job| [job.serialize] },
|
57
|
+
"at" => scheduled_jobs.map { |job| job.scheduled_at }
|
58
|
+
)
|
59
|
+
enqueued_count += jids.compact.size
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
enqueued_count
|
36
64
|
end
|
37
65
|
|
38
66
|
class JobWrapper # :nodoc:
|
@@ -5,7 +5,7 @@ require "monitor"
|
|
5
5
|
|
6
6
|
module ActiveJob
|
7
7
|
module QueueAdapters
|
8
|
-
#
|
8
|
+
# = Sneakers adapter for Active Job
|
9
9
|
#
|
10
10
|
# A high-performance RabbitMQ background processing framework for Ruby.
|
11
11
|
# Sneakers is being used in production for both I/O and CPU intensive
|
@@ -4,13 +4,13 @@ require "sucker_punch"
|
|
4
4
|
|
5
5
|
module ActiveJob
|
6
6
|
module QueueAdapters
|
7
|
-
#
|
7
|
+
# = Sucker Punch adapter for Active Job
|
8
8
|
#
|
9
9
|
# Sucker Punch is a single-process Ruby asynchronous processing library.
|
10
10
|
# This reduces the cost of hosting on a service like Heroku along
|
11
11
|
# with the memory footprint of having to maintain additional jobs if
|
12
12
|
# hosting on a dedicated server. All queues can run within a
|
13
|
-
# single application (e.g. Rails, Sinatra, etc.) process.
|
13
|
+
# single application (e.g. \Rails, Sinatra, etc.) process.
|
14
14
|
#
|
15
15
|
# Read more about Sucker Punch {here}[https://github.com/brandonhilkert/sucker_punch].
|
16
16
|
#
|
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
module ActiveJob
|
4
4
|
module QueueAdapters
|
5
|
-
#
|
5
|
+
# = Test adapter for Active Job
|
6
6
|
#
|
7
7
|
# The test adapter should be used only in testing. Along with
|
8
8
|
# ActiveJob::TestCase and ActiveJob::TestHelper
|
9
|
-
# it makes a great tool to test your Rails application.
|
9
|
+
# it makes a great tool to test your \Rails application.
|
10
10
|
#
|
11
11
|
# To use the test adapter set +queue_adapter+ config to +:test+.
|
12
12
|
#
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveJob
|
4
|
-
#
|
4
|
+
# = Active Job adapters
|
5
5
|
#
|
6
6
|
# Active Job has adapters for the following queuing backends:
|
7
7
|
#
|
@@ -13,10 +13,14 @@ module ActiveJob
|
|
13
13
|
# * {Sidekiq}[https://sidekiq.org]
|
14
14
|
# * {Sneakers}[https://github.com/jondot/sneakers]
|
15
15
|
# * {Sucker Punch}[https://github.com/brandonhilkert/sucker_punch]
|
16
|
-
# * {Active Job Async Job}[https://api.rubyonrails.org/classes/ActiveJob/QueueAdapters/AsyncAdapter.html]
|
17
|
-
# * {Active Job Inline}[https://api.rubyonrails.org/classes/ActiveJob/QueueAdapters/InlineAdapter.html]
|
18
16
|
# * Please Note: We are not accepting pull requests for new adapters. See the {README}[link:files/activejob/README_md.html] for more details.
|
19
17
|
#
|
18
|
+
# For testing and development Active Job has three built-in adapters:
|
19
|
+
#
|
20
|
+
# * {Active Job Async}[https://api.rubyonrails.org/classes/ActiveJob/QueueAdapters/AsyncAdapter.html]
|
21
|
+
# * {Active Job Inline}[https://api.rubyonrails.org/classes/ActiveJob/QueueAdapters/InlineAdapter.html]
|
22
|
+
# * {Active Job Test}[https://api.rubyonrails.org/classes/ActiveJob/QueueAdapters/TestAdapter.html]
|
23
|
+
#
|
20
24
|
# === Backends Features
|
21
25
|
#
|
22
26
|
# | | Async | Queues | Delayed | Priorities | Timeout | Retries |
|
@@ -31,6 +35,7 @@ module ActiveJob
|
|
31
35
|
# | Sucker Punch | Yes | Yes | Yes | No | No | No |
|
32
36
|
# | Active Job Async | Yes | Yes | Yes | No | No | No |
|
33
37
|
# | Active Job Inline | No | Yes | N/A | N/A | N/A | N/A |
|
38
|
+
# | Active Job Test | No | Yes | N/A | N/A | N/A | N/A |
|
34
39
|
#
|
35
40
|
# ==== Async
|
36
41
|
#
|
@@ -106,10 +111,6 @@ module ActiveJob
|
|
106
111
|
# N/A: The adapter does not run in a separate process, and therefore doesn't
|
107
112
|
# support retries.
|
108
113
|
#
|
109
|
-
# === Async and Inline Queue Adapters
|
110
|
-
#
|
111
|
-
# Active Job has two built-in queue adapters intended for development and
|
112
|
-
# testing: +:async+ and +:inline+.
|
113
114
|
module QueueAdapters
|
114
115
|
extend ActiveSupport::Autoload
|
115
116
|
|
@@ -18,7 +18,24 @@ module ActiveJob
|
|
18
18
|
# end
|
19
19
|
# end
|
20
20
|
#
|
21
|
-
#
|
21
|
+
# Can be given a block that will evaluate in the context of the job
|
22
|
+
# so that a dynamic priority can be applied:
|
23
|
+
#
|
24
|
+
# class PublishToFeedJob < ApplicationJob
|
25
|
+
# queue_with_priority do
|
26
|
+
# post = self.arguments.first
|
27
|
+
#
|
28
|
+
# if post.paid?
|
29
|
+
# 10
|
30
|
+
# else
|
31
|
+
# 50
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# def perform(post)
|
36
|
+
# post.to_feed!
|
37
|
+
# end
|
38
|
+
# end
|
22
39
|
def queue_with_priority(priority = nil, &block)
|
23
40
|
if block_given?
|
24
41
|
self.priority = block
|
data/lib/active_job/railtie.rb
CHANGED
@@ -10,6 +10,10 @@ module ActiveJob
|
|
10
10
|
config.active_job.custom_serializers = []
|
11
11
|
config.active_job.log_query_tags_around_perform = true
|
12
12
|
|
13
|
+
initializer "active_job.deprecator", before: :load_environment_config do |app|
|
14
|
+
app.deprecators[:active_job] = ActiveJob.deprecator
|
15
|
+
end
|
16
|
+
|
13
17
|
initializer "active_job.logger" do
|
14
18
|
ActiveSupport.on_load(:active_job) { self.logger = ::Rails.logger }
|
15
19
|
end
|
@@ -25,6 +29,15 @@ module ActiveJob
|
|
25
29
|
options = app.config.active_job
|
26
30
|
options.queue_adapter ||= :async
|
27
31
|
|
32
|
+
config.after_initialize do
|
33
|
+
options.each do |k, v|
|
34
|
+
k = "#{k}="
|
35
|
+
if ActiveJob.respond_to?(k)
|
36
|
+
ActiveJob.send(k, v)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
28
41
|
ActiveSupport.on_load(:active_job) do
|
29
42
|
# Configs used in other initializers
|
30
43
|
options = options.except(
|
@@ -32,19 +45,19 @@ module ActiveJob
|
|
32
45
|
:custom_serializers
|
33
46
|
)
|
34
47
|
|
35
|
-
options.each do
|
48
|
+
options.each do |k, v|
|
36
49
|
k = "#{k}="
|
37
|
-
|
50
|
+
if ActiveJob.respond_to?(k)
|
51
|
+
ActiveJob.send(k, v)
|
52
|
+
elsif respond_to? k
|
53
|
+
send(k, v)
|
54
|
+
end
|
38
55
|
end
|
39
56
|
end
|
40
57
|
|
41
58
|
ActiveSupport.on_load(:action_dispatch_integration_test) do
|
42
59
|
include ActiveJob::TestHelper
|
43
60
|
end
|
44
|
-
|
45
|
-
ActiveSupport.on_load(:active_record) do
|
46
|
-
self.destroy_association_async_job = ActiveRecord::DestroyAssociationAsyncJob
|
47
|
-
end
|
48
61
|
end
|
49
62
|
|
50
63
|
initializer "active_job.set_reloader_hook" do |app|
|
@@ -70,5 +83,11 @@ module ActiveJob
|
|
70
83
|
end
|
71
84
|
end
|
72
85
|
end
|
86
|
+
|
87
|
+
initializer "active_job.backtrace_cleaner" do
|
88
|
+
ActiveSupport.on_load(:active_job) do
|
89
|
+
LogSubscriber.backtrace_cleaner = ::Rails.backtrace_cleaner
|
90
|
+
end
|
91
|
+
end
|
73
92
|
end
|
74
93
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bigdecimal"
|
4
|
+
|
5
|
+
module ActiveJob
|
6
|
+
module Serializers
|
7
|
+
class BigDecimalSerializer < ObjectSerializer # :nodoc:
|
8
|
+
def serialize(big_decimal)
|
9
|
+
super("value" => big_decimal.to_s)
|
10
|
+
end
|
11
|
+
|
12
|
+
def deserialize(hash)
|
13
|
+
BigDecimal(hash["value"])
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def klass
|
18
|
+
BigDecimal
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -4,14 +4,16 @@ module ActiveJob
|
|
4
4
|
module Serializers
|
5
5
|
class DurationSerializer < ObjectSerializer # :nodoc:
|
6
6
|
def serialize(duration)
|
7
|
+
# Ideally duration.parts would be wrapped in an array before passing to Arguments.serialize,
|
8
|
+
# but we continue passing the bare hash for backwards compatibility:
|
7
9
|
super("value" => duration.value, "parts" => Arguments.serialize(duration.parts))
|
8
10
|
end
|
9
11
|
|
10
12
|
def deserialize(hash)
|
11
13
|
value = hash["value"]
|
12
14
|
parts = Arguments.deserialize(hash["parts"])
|
13
|
-
|
14
|
-
klass.new(value, parts)
|
15
|
+
# `parts` is originally a hash, but will have been flattened to an array by Arguments.serialize
|
16
|
+
klass.new(value, parts.to_h)
|
15
17
|
end
|
16
18
|
|
17
19
|
private
|
@@ -3,7 +3,9 @@
|
|
3
3
|
require "set"
|
4
4
|
|
5
5
|
module ActiveJob
|
6
|
-
#
|
6
|
+
# = Active Job \Serializers
|
7
|
+
#
|
8
|
+
# The +ActiveJob::Serializers+ module is used to store a list of known serializers
|
7
9
|
# and to add new ones. It also has helpers to serialize/deserialize objects.
|
8
10
|
module Serializers # :nodoc:
|
9
11
|
extend ActiveSupport::Autoload
|
@@ -18,6 +20,7 @@ module ActiveJob
|
|
18
20
|
autoload :TimeSerializer
|
19
21
|
autoload :ModuleSerializer
|
20
22
|
autoload :RangeSerializer
|
23
|
+
autoload :BigDecimalSerializer
|
21
24
|
|
22
25
|
mattr_accessor :_additional_serializers
|
23
26
|
self._additional_serializers = Set.new
|
@@ -25,7 +28,7 @@ module ActiveJob
|
|
25
28
|
class << self
|
26
29
|
# Returns serialized representative of the passed object.
|
27
30
|
# Will look up through all known serializers.
|
28
|
-
# Raises
|
31
|
+
# Raises ActiveJob::SerializationError if it can't find a proper serializer.
|
29
32
|
def serialize(argument)
|
30
33
|
serializer = serializers.detect { |s| s.serialize?(argument) }
|
31
34
|
raise SerializationError.new("Unsupported argument type: #{argument.class.name}") unless serializer
|
@@ -63,6 +66,7 @@ module ActiveJob
|
|
63
66
|
TimeWithZoneSerializer,
|
64
67
|
TimeSerializer,
|
65
68
|
ModuleSerializer,
|
66
|
-
RangeSerializer
|
69
|
+
RangeSerializer,
|
70
|
+
BigDecimalSerializer
|
67
71
|
end
|
68
72
|
end
|