activejob 5.2.8.1 → 6.1.6.1
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 +118 -57
- data/MIT-LICENSE +1 -2
- data/README.md +18 -13
- data/lib/active_job/arguments.rb +80 -30
- data/lib/active_job/base.rb +6 -1
- data/lib/active_job/callbacks.rb +46 -3
- data/lib/active_job/configured_job.rb +2 -0
- data/lib/active_job/core.rb +40 -21
- data/lib/active_job/enqueuing.rb +20 -7
- data/lib/active_job/exceptions.rb +60 -28
- data/lib/active_job/execution.rb +11 -2
- data/lib/active_job/gem_version.rb +3 -3
- data/lib/active_job/instrumentation.rb +40 -0
- data/lib/active_job/log_subscriber.rb +140 -0
- data/lib/active_job/logging.rb +3 -101
- data/lib/active_job/queue_adapter.rb +5 -0
- data/lib/active_job/queue_adapters/async_adapter.rb +1 -1
- data/lib/active_job/queue_adapters/backburner_adapter.rb +2 -2
- data/lib/active_job/queue_adapters/inline_adapter.rb +1 -1
- data/lib/active_job/queue_adapters/que_adapter.rb +2 -2
- data/lib/active_job/queue_adapters/sidekiq_adapter.rb +2 -2
- data/lib/active_job/queue_adapters/sucker_punch_adapter.rb +1 -1
- data/lib/active_job/queue_adapters/test_adapter.rb +32 -14
- data/lib/active_job/queue_adapters.rb +13 -11
- data/lib/active_job/queue_name.rb +23 -3
- data/lib/active_job/railtie.rb +20 -1
- data/lib/active_job/serializers/date_serializer.rb +20 -0
- data/lib/active_job/serializers/date_time_serializer.rb +16 -0
- data/lib/active_job/serializers/duration_serializer.rb +23 -0
- data/lib/active_job/serializers/module_serializer.rb +20 -0
- data/lib/active_job/serializers/object_serializer.rb +53 -0
- data/lib/active_job/serializers/symbol_serializer.rb +20 -0
- data/lib/active_job/serializers/time_object_serializer.rb +13 -0
- data/lib/active_job/serializers/time_serializer.rb +16 -0
- data/lib/active_job/serializers/time_with_zone_serializer.rb +16 -0
- data/lib/active_job/serializers.rb +66 -0
- data/lib/active_job/test_helper.rb +317 -68
- data/lib/active_job/timezones.rb +13 -0
- data/lib/active_job/translation.rb +1 -1
- data/lib/active_job.rb +2 -1
- data/lib/rails/generators/job/job_generator.rb +4 -0
- metadata +25 -9
- data/lib/active_job/queue_adapters/qu_adapter.rb +0 -46
data/lib/active_job/logging.rb
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "active_support/core_ext/hash/transform_values"
|
|
4
|
-
require "active_support/core_ext/string/filters"
|
|
5
3
|
require "active_support/tagged_logging"
|
|
6
4
|
require "active_support/logger"
|
|
7
5
|
|
|
@@ -11,32 +9,10 @@ module ActiveJob
|
|
|
11
9
|
|
|
12
10
|
included do
|
|
13
11
|
cattr_accessor :logger, default: ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDOUT))
|
|
12
|
+
class_attribute :log_arguments, instance_accessor: false, default: true
|
|
14
13
|
|
|
15
|
-
around_enqueue
|
|
16
|
-
|
|
17
|
-
block.call
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
around_perform do |job, block, _|
|
|
22
|
-
tag_logger(job.class.name, job.job_id) do
|
|
23
|
-
payload = { adapter: job.class.queue_adapter, job: job }
|
|
24
|
-
ActiveSupport::Notifications.instrument("perform_start.active_job", payload.dup)
|
|
25
|
-
ActiveSupport::Notifications.instrument("perform.active_job", payload) do
|
|
26
|
-
block.call
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
after_enqueue do |job|
|
|
32
|
-
if job.scheduled_at
|
|
33
|
-
ActiveSupport::Notifications.instrument "enqueue_at.active_job",
|
|
34
|
-
adapter: job.class.queue_adapter, job: job
|
|
35
|
-
else
|
|
36
|
-
ActiveSupport::Notifications.instrument "enqueue.active_job",
|
|
37
|
-
adapter: job.class.queue_adapter, job: job
|
|
38
|
-
end
|
|
39
|
-
end
|
|
14
|
+
around_enqueue { |_, block| tag_logger(&block) }
|
|
15
|
+
around_perform { |job, block| tag_logger(job.class.name, job.job_id, &block) }
|
|
40
16
|
end
|
|
41
17
|
|
|
42
18
|
private
|
|
@@ -52,79 +28,5 @@ module ActiveJob
|
|
|
52
28
|
def logger_tagged_by_active_job?
|
|
53
29
|
logger.formatter.current_tags.include?("ActiveJob")
|
|
54
30
|
end
|
|
55
|
-
|
|
56
|
-
class LogSubscriber < ActiveSupport::LogSubscriber #:nodoc:
|
|
57
|
-
def enqueue(event)
|
|
58
|
-
info do
|
|
59
|
-
job = event.payload[:job]
|
|
60
|
-
"Enqueued #{job.class.name} (Job ID: #{job.job_id}) to #{queue_name(event)}" + args_info(job)
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def enqueue_at(event)
|
|
65
|
-
info do
|
|
66
|
-
job = event.payload[:job]
|
|
67
|
-
"Enqueued #{job.class.name} (Job ID: #{job.job_id}) to #{queue_name(event)} at #{scheduled_at(event)}" + args_info(job)
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def perform_start(event)
|
|
72
|
-
info do
|
|
73
|
-
job = event.payload[:job]
|
|
74
|
-
"Performing #{job.class.name} (Job ID: #{job.job_id}) from #{queue_name(event)}" + args_info(job)
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
def perform(event)
|
|
79
|
-
job = event.payload[:job]
|
|
80
|
-
ex = event.payload[:exception_object]
|
|
81
|
-
if ex
|
|
82
|
-
error do
|
|
83
|
-
"Error performing #{job.class.name} (Job ID: #{job.job_id}) from #{queue_name(event)} in #{event.duration.round(2)}ms: #{ex.class} (#{ex.message}):\n" + Array(ex.backtrace).join("\n")
|
|
84
|
-
end
|
|
85
|
-
else
|
|
86
|
-
info do
|
|
87
|
-
"Performed #{job.class.name} (Job ID: #{job.job_id}) from #{queue_name(event)} in #{event.duration.round(2)}ms"
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
private
|
|
93
|
-
def queue_name(event)
|
|
94
|
-
event.payload[:adapter].class.name.demodulize.remove("Adapter") + "(#{event.payload[:job].queue_name})"
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
def args_info(job)
|
|
98
|
-
if job.arguments.any?
|
|
99
|
-
" with arguments: " +
|
|
100
|
-
job.arguments.map { |arg| format(arg).inspect }.join(", ")
|
|
101
|
-
else
|
|
102
|
-
""
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def format(arg)
|
|
107
|
-
case arg
|
|
108
|
-
when Hash
|
|
109
|
-
arg.transform_values { |value| format(value) }
|
|
110
|
-
when Array
|
|
111
|
-
arg.map { |value| format(value) }
|
|
112
|
-
when GlobalID::Identification
|
|
113
|
-
arg.to_global_id rescue arg
|
|
114
|
-
else
|
|
115
|
-
arg
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
def scheduled_at(event)
|
|
120
|
-
Time.at(event.payload[:job].scheduled_at).utc
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
def logger
|
|
124
|
-
ActiveJob::Base.logger
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
31
|
end
|
|
128
32
|
end
|
|
129
|
-
|
|
130
|
-
ActiveJob::Logging::LogSubscriber.attach_to :active_job
|
|
@@ -11,6 +11,9 @@ module ActiveJob
|
|
|
11
11
|
included do
|
|
12
12
|
class_attribute :_queue_adapter_name, instance_accessor: false, instance_predicate: false
|
|
13
13
|
class_attribute :_queue_adapter, instance_accessor: false, instance_predicate: false
|
|
14
|
+
|
|
15
|
+
delegate :queue_adapter, to: :class
|
|
16
|
+
|
|
14
17
|
self.queue_adapter = :async
|
|
15
18
|
end
|
|
16
19
|
|
|
@@ -22,6 +25,8 @@ module ActiveJob
|
|
|
22
25
|
_queue_adapter
|
|
23
26
|
end
|
|
24
27
|
|
|
28
|
+
# Returns string denoting the name of the configured queue adapter.
|
|
29
|
+
# By default returns <tt>"async"</tt>.
|
|
25
30
|
def queue_adapter_name
|
|
26
31
|
_queue_adapter_name
|
|
27
32
|
end
|
|
@@ -31,7 +31,7 @@ module ActiveJob
|
|
|
31
31
|
# jobs. Since jobs share a single thread pool, long-running jobs will block
|
|
32
32
|
# short-lived jobs. Fine for dev/test; bad for production.
|
|
33
33
|
class AsyncAdapter
|
|
34
|
-
# See {Concurrent::ThreadPoolExecutor}[https://ruby-concurrency.github.io/concurrent-ruby/Concurrent/ThreadPoolExecutor.html] for executor options.
|
|
34
|
+
# See {Concurrent::ThreadPoolExecutor}[https://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent/ThreadPoolExecutor.html] for executor options.
|
|
35
35
|
def initialize(**executor_options)
|
|
36
36
|
@scheduler = Scheduler.new(**executor_options)
|
|
37
37
|
end
|
|
@@ -16,12 +16,12 @@ 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
|
|
19
|
+
Backburner::Worker.enqueue(JobWrapper, [job.serialize], queue: job.queue_name, pri: job.priority)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def enqueue_at(job, timestamp) #:nodoc:
|
|
23
23
|
delay = timestamp - Time.current.to_f
|
|
24
|
-
Backburner::Worker.enqueue
|
|
24
|
+
Backburner::Worker.enqueue(JobWrapper, [job.serialize], queue: job.queue_name, pri: job.priority, delay: delay)
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
class JobWrapper #:nodoc:
|
|
@@ -16,7 +16,7 @@ module ActiveJob
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def enqueue_at(*) #:nodoc:
|
|
19
|
-
raise NotImplementedError, "Use a queueing backend to enqueue jobs in the future. Read more at
|
|
19
|
+
raise NotImplementedError, "Use a queueing backend to enqueue jobs in the future. Read more at https://guides.rubyonrails.org/active_job_basics.html"
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
end
|
|
@@ -18,13 +18,13 @@ module ActiveJob
|
|
|
18
18
|
# Rails.application.config.active_job.queue_adapter = :que
|
|
19
19
|
class QueAdapter
|
|
20
20
|
def enqueue(job) #:nodoc:
|
|
21
|
-
que_job = JobWrapper.enqueue job.serialize, priority: job.priority
|
|
21
|
+
que_job = JobWrapper.enqueue job.serialize, priority: job.priority, queue: job.queue_name
|
|
22
22
|
job.provider_job_id = que_job.attrs["job_id"]
|
|
23
23
|
que_job
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def enqueue_at(job, timestamp) #:nodoc:
|
|
27
|
-
que_job = JobWrapper.enqueue job.serialize, priority: job.priority, run_at: Time.at(timestamp)
|
|
27
|
+
que_job = JobWrapper.enqueue job.serialize, priority: job.priority, queue: job.queue_name, run_at: Time.at(timestamp)
|
|
28
28
|
job.provider_job_id = que_job.attrs["job_id"]
|
|
29
29
|
que_job
|
|
30
30
|
end
|
|
@@ -21,7 +21,7 @@ module ActiveJob
|
|
|
21
21
|
# Sidekiq::Client does not support symbols as keys
|
|
22
22
|
job.provider_job_id = Sidekiq::Client.push \
|
|
23
23
|
"class" => JobWrapper,
|
|
24
|
-
"wrapped" => job.class
|
|
24
|
+
"wrapped" => job.class,
|
|
25
25
|
"queue" => job.queue_name,
|
|
26
26
|
"args" => [ job.serialize ]
|
|
27
27
|
end
|
|
@@ -29,7 +29,7 @@ module ActiveJob
|
|
|
29
29
|
def enqueue_at(job, timestamp) #:nodoc:
|
|
30
30
|
job.provider_job_id = Sidekiq::Client.push \
|
|
31
31
|
"class" => JobWrapper,
|
|
32
|
-
"wrapped" => job.class
|
|
32
|
+
"wrapped" => job.class,
|
|
33
33
|
"queue" => job.queue_name,
|
|
34
34
|
"args" => [ job.serialize ],
|
|
35
35
|
"at" => timestamp
|
|
@@ -10,7 +10,7 @@ module ActiveJob
|
|
|
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 (
|
|
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
|
#
|
|
@@ -12,7 +12,7 @@ module ActiveJob
|
|
|
12
12
|
#
|
|
13
13
|
# Rails.application.config.active_job.queue_adapter = :test
|
|
14
14
|
class TestAdapter
|
|
15
|
-
attr_accessor(:perform_enqueued_jobs, :perform_enqueued_at_jobs, :filter, :reject)
|
|
15
|
+
attr_accessor(:perform_enqueued_jobs, :perform_enqueued_at_jobs, :filter, :reject, :queue, :at)
|
|
16
16
|
attr_writer(:enqueued_jobs, :performed_jobs)
|
|
17
17
|
|
|
18
18
|
# Provides a store of all the enqueued jobs with the TestAdapter so you can check them.
|
|
@@ -26,42 +26,60 @@ module ActiveJob
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def enqueue(job) #:nodoc:
|
|
29
|
-
return if filtered?(job)
|
|
30
|
-
|
|
31
29
|
job_data = job_to_hash(job)
|
|
32
|
-
|
|
30
|
+
perform_or_enqueue(perform_enqueued_jobs && !filtered?(job), job, job_data)
|
|
33
31
|
end
|
|
34
32
|
|
|
35
33
|
def enqueue_at(job, timestamp) #:nodoc:
|
|
36
|
-
return if filtered?(job)
|
|
37
|
-
|
|
38
34
|
job_data = job_to_hash(job, at: timestamp)
|
|
39
|
-
|
|
35
|
+
perform_or_enqueue(perform_enqueued_at_jobs && !filtered?(job), job, job_data)
|
|
40
36
|
end
|
|
41
37
|
|
|
42
38
|
private
|
|
43
39
|
def job_to_hash(job, extras = {})
|
|
44
|
-
|
|
40
|
+
job.serialize.tap do |job_data|
|
|
41
|
+
job_data[:job] = job.class
|
|
42
|
+
job_data[:args] = job_data.fetch("arguments")
|
|
43
|
+
job_data[:queue] = job_data.fetch("queue_name")
|
|
44
|
+
end.merge(extras)
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
-
def
|
|
47
|
+
def perform_or_enqueue(perform, job, job_data)
|
|
48
48
|
if perform
|
|
49
49
|
performed_jobs << job_data
|
|
50
|
-
Base.execute
|
|
50
|
+
Base.execute(job.serialize)
|
|
51
51
|
else
|
|
52
52
|
enqueued_jobs << job_data
|
|
53
53
|
end
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
def filtered?(job)
|
|
57
|
+
filtered_queue?(job) || filtered_job_class?(job) || filtered_time?(job)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def filtered_time?(job)
|
|
61
|
+
job.scheduled_at > at.to_f if at && job.scheduled_at
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def filtered_queue?(job)
|
|
65
|
+
if queue
|
|
66
|
+
job.queue_name != queue.to_s
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def filtered_job_class?(job)
|
|
57
71
|
if filter
|
|
58
|
-
!
|
|
72
|
+
!filter_as_proc(filter).call(job)
|
|
59
73
|
elsif reject
|
|
60
|
-
|
|
61
|
-
else
|
|
62
|
-
false
|
|
74
|
+
filter_as_proc(reject).call(job)
|
|
63
75
|
end
|
|
64
76
|
end
|
|
77
|
+
|
|
78
|
+
def filter_as_proc(filter)
|
|
79
|
+
return filter if filter.is_a?(Proc)
|
|
80
|
+
|
|
81
|
+
->(job) { Array(filter).include?(job.class) }
|
|
82
|
+
end
|
|
65
83
|
end
|
|
66
84
|
end
|
|
67
85
|
end
|
|
@@ -3,19 +3,19 @@
|
|
|
3
3
|
module ActiveJob
|
|
4
4
|
# == Active Job adapters
|
|
5
5
|
#
|
|
6
|
-
# Active Job has adapters for the following
|
|
6
|
+
# Active Job has adapters for the following queuing backends:
|
|
7
7
|
#
|
|
8
8
|
# * {Backburner}[https://github.com/nesquena/backburner]
|
|
9
9
|
# * {Delayed Job}[https://github.com/collectiveidea/delayed_job]
|
|
10
|
-
# * {Qu}[https://github.com/bkeepers/qu]
|
|
11
10
|
# * {Que}[https://github.com/chanks/que]
|
|
12
11
|
# * {queue_classic}[https://github.com/QueueClassic/queue_classic]
|
|
13
12
|
# * {Resque}[https://github.com/resque/resque]
|
|
14
|
-
# * {Sidekiq}[
|
|
13
|
+
# * {Sidekiq}[https://sidekiq.org]
|
|
15
14
|
# * {Sneakers}[https://github.com/jondot/sneakers]
|
|
16
15
|
# * {Sucker Punch}[https://github.com/brandonhilkert/sucker_punch]
|
|
17
|
-
# * {Active Job Async Job}[
|
|
18
|
-
# * {Active Job Inline}[
|
|
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
|
+
# * Please Note: We are not accepting pull requests for new adapters. See the {README}[link:files/activejob/README_md.html] for more details.
|
|
19
19
|
#
|
|
20
20
|
# === Backends Features
|
|
21
21
|
#
|
|
@@ -23,7 +23,6 @@ module ActiveJob
|
|
|
23
23
|
# |-------------------|-------|--------|------------|------------|---------|---------|
|
|
24
24
|
# | Backburner | Yes | Yes | Yes | Yes | Job | Global |
|
|
25
25
|
# | Delayed Job | Yes | Yes | Yes | Job | Global | Global |
|
|
26
|
-
# | Qu | Yes | Yes | No | No | No | Global |
|
|
27
26
|
# | Que | Yes | Yes | Yes | Job | No | Job |
|
|
28
27
|
# | queue_classic | Yes | Yes | Yes* | No | No | No |
|
|
29
28
|
# | Resque | Yes | Yes | Yes (Gem) | Queue | Global | Yes |
|
|
@@ -53,7 +52,7 @@ module ActiveJob
|
|
|
53
52
|
#
|
|
54
53
|
# No: The adapter will run jobs at the next opportunity and cannot use perform_later.
|
|
55
54
|
#
|
|
56
|
-
# N/A: The adapter does not support
|
|
55
|
+
# N/A: The adapter does not support queuing.
|
|
57
56
|
#
|
|
58
57
|
# NOTE:
|
|
59
58
|
# queue_classic supports job scheduling since version 3.1.
|
|
@@ -73,9 +72,9 @@ module ActiveJob
|
|
|
73
72
|
# Yes: Allows the priority to be set on the job object, at the queue level or
|
|
74
73
|
# as default configuration option.
|
|
75
74
|
#
|
|
76
|
-
# No:
|
|
75
|
+
# No: The adapter does not allow the priority of jobs to be configured.
|
|
77
76
|
#
|
|
78
|
-
# N/A: The adapter does not support
|
|
77
|
+
# N/A: The adapter does not support queuing, and therefore sorting them.
|
|
79
78
|
#
|
|
80
79
|
# ==== Timeout
|
|
81
80
|
#
|
|
@@ -87,6 +86,8 @@ module ActiveJob
|
|
|
87
86
|
#
|
|
88
87
|
# Global: The adapter is configured that all jobs have a maximum run time.
|
|
89
88
|
#
|
|
89
|
+
# No: The adapter does not allow the timeout of jobs to be configured.
|
|
90
|
+
#
|
|
90
91
|
# N/A: This adapter does not run in a separate process, and therefore timeout
|
|
91
92
|
# is unsupported.
|
|
92
93
|
#
|
|
@@ -100,6 +101,8 @@ module ActiveJob
|
|
|
100
101
|
#
|
|
101
102
|
# Global: The adapter has a global number of retries.
|
|
102
103
|
#
|
|
104
|
+
# No: The adapter does not allow the number of retries to be configured.
|
|
105
|
+
#
|
|
103
106
|
# N/A: The adapter does not run in a separate process, and therefore doesn't
|
|
104
107
|
# support retries.
|
|
105
108
|
#
|
|
@@ -114,7 +117,6 @@ module ActiveJob
|
|
|
114
117
|
autoload :InlineAdapter
|
|
115
118
|
autoload :BackburnerAdapter
|
|
116
119
|
autoload :DelayedJobAdapter
|
|
117
|
-
autoload :QuAdapter
|
|
118
120
|
autoload :QueAdapter
|
|
119
121
|
autoload :QueueClassicAdapter
|
|
120
122
|
autoload :ResqueAdapter
|
|
@@ -123,7 +125,7 @@ module ActiveJob
|
|
|
123
125
|
autoload :SuckerPunchAdapter
|
|
124
126
|
autoload :TestAdapter
|
|
125
127
|
|
|
126
|
-
ADAPTER = "Adapter"
|
|
128
|
+
ADAPTER = "Adapter"
|
|
127
129
|
private_constant :ADAPTER
|
|
128
130
|
|
|
129
131
|
class << self
|
|
@@ -6,7 +6,6 @@ module ActiveJob
|
|
|
6
6
|
|
|
7
7
|
# Includes the ability to override the default queue name and prefix.
|
|
8
8
|
module ClassMethods
|
|
9
|
-
mattr_accessor :queue_name_prefix
|
|
10
9
|
mattr_accessor :default_queue_name, default: "default"
|
|
11
10
|
|
|
12
11
|
# Specifies the name of the queue to process the job on.
|
|
@@ -18,6 +17,26 @@ module ActiveJob
|
|
|
18
17
|
# post.to_feed!
|
|
19
18
|
# end
|
|
20
19
|
# end
|
|
20
|
+
#
|
|
21
|
+
# Can be given a block that will evaluate in the context of the job
|
|
22
|
+
# allowing +self.arguments+ to be accessed so that a dynamic queue name
|
|
23
|
+
# can be applied:
|
|
24
|
+
#
|
|
25
|
+
# class PublishToFeedJob < ApplicationJob
|
|
26
|
+
# queue_as do
|
|
27
|
+
# post = self.arguments.first
|
|
28
|
+
#
|
|
29
|
+
# if post.paid?
|
|
30
|
+
# :paid_feeds
|
|
31
|
+
# else
|
|
32
|
+
# :feeds
|
|
33
|
+
# end
|
|
34
|
+
# end
|
|
35
|
+
#
|
|
36
|
+
# def perform(post)
|
|
37
|
+
# post.to_feed!
|
|
38
|
+
# end
|
|
39
|
+
# end
|
|
21
40
|
def queue_as(part_name = nil, &block)
|
|
22
41
|
if block_given?
|
|
23
42
|
self.queue_name = block
|
|
@@ -29,13 +48,14 @@ module ActiveJob
|
|
|
29
48
|
def queue_name_from_part(part_name) #:nodoc:
|
|
30
49
|
queue_name = part_name || default_queue_name
|
|
31
50
|
name_parts = [queue_name_prefix.presence, queue_name]
|
|
32
|
-
name_parts.compact.join(queue_name_delimiter)
|
|
51
|
+
-name_parts.compact.join(queue_name_delimiter)
|
|
33
52
|
end
|
|
34
53
|
end
|
|
35
54
|
|
|
36
55
|
included do
|
|
37
|
-
class_attribute :queue_name, instance_accessor: false, default: default_queue_name
|
|
56
|
+
class_attribute :queue_name, instance_accessor: false, default: -> { self.class.default_queue_name }
|
|
38
57
|
class_attribute :queue_name_delimiter, instance_accessor: false, default: "_"
|
|
58
|
+
class_attribute :queue_name_prefix
|
|
39
59
|
end
|
|
40
60
|
|
|
41
61
|
# Returns the name of the queue the job will be run on.
|
data/lib/active_job/railtie.rb
CHANGED
|
@@ -7,17 +7,36 @@ module ActiveJob
|
|
|
7
7
|
# = Active Job Railtie
|
|
8
8
|
class Railtie < Rails::Railtie # :nodoc:
|
|
9
9
|
config.active_job = ActiveSupport::OrderedOptions.new
|
|
10
|
+
config.active_job.custom_serializers = []
|
|
10
11
|
|
|
11
12
|
initializer "active_job.logger" do
|
|
12
13
|
ActiveSupport.on_load(:active_job) { self.logger = ::Rails.logger }
|
|
13
14
|
end
|
|
14
15
|
|
|
16
|
+
initializer "active_job.custom_serializers" do |app|
|
|
17
|
+
config.after_initialize do
|
|
18
|
+
custom_serializers = app.config.active_job.delete(:custom_serializers)
|
|
19
|
+
ActiveJob::Serializers.add_serializers custom_serializers
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
15
23
|
initializer "active_job.set_configs" do |app|
|
|
16
24
|
options = app.config.active_job
|
|
17
25
|
options.queue_adapter ||= :async
|
|
18
26
|
|
|
19
27
|
ActiveSupport.on_load(:active_job) do
|
|
20
|
-
options.each
|
|
28
|
+
options.each do |k, v|
|
|
29
|
+
k = "#{k}="
|
|
30
|
+
send(k, v) if respond_to? k
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
ActiveSupport.on_load(:action_dispatch_integration_test) do
|
|
35
|
+
include ActiveJob::TestHelper
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
ActiveSupport.on_load(:active_record) do
|
|
39
|
+
self.destroy_association_async_job = ActiveRecord::DestroyAssociationAsyncJob
|
|
21
40
|
end
|
|
22
41
|
end
|
|
23
42
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveJob
|
|
4
|
+
module Serializers
|
|
5
|
+
class DateSerializer < ObjectSerializer # :nodoc:
|
|
6
|
+
def serialize(date)
|
|
7
|
+
super("value" => date.iso8601)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def deserialize(hash)
|
|
11
|
+
Date.iso8601(hash["value"])
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
def klass
|
|
16
|
+
Date
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveJob
|
|
4
|
+
module Serializers
|
|
5
|
+
class DateTimeSerializer < TimeObjectSerializer # :nodoc:
|
|
6
|
+
def deserialize(hash)
|
|
7
|
+
DateTime.iso8601(hash["value"])
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
def klass
|
|
12
|
+
DateTime
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveJob
|
|
4
|
+
module Serializers
|
|
5
|
+
class DurationSerializer < ObjectSerializer # :nodoc:
|
|
6
|
+
def serialize(duration)
|
|
7
|
+
super("value" => duration.value, "parts" => Arguments.serialize(duration.parts))
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def deserialize(hash)
|
|
11
|
+
value = hash["value"]
|
|
12
|
+
parts = Arguments.deserialize(hash["parts"])
|
|
13
|
+
|
|
14
|
+
klass.new(value, parts)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
def klass
|
|
19
|
+
ActiveSupport::Duration
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveJob
|
|
4
|
+
module Serializers
|
|
5
|
+
class ModuleSerializer < ObjectSerializer # :nodoc:
|
|
6
|
+
def serialize(constant)
|
|
7
|
+
super("value" => constant.name)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def deserialize(hash)
|
|
11
|
+
hash["value"].constantize
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
def klass
|
|
16
|
+
Module
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveJob
|
|
4
|
+
module Serializers
|
|
5
|
+
# Base class for serializing and deserializing custom objects.
|
|
6
|
+
#
|
|
7
|
+
# Example:
|
|
8
|
+
#
|
|
9
|
+
# class MoneySerializer < ActiveJob::Serializers::ObjectSerializer
|
|
10
|
+
# def serialize(money)
|
|
11
|
+
# super("amount" => money.amount, "currency" => money.currency)
|
|
12
|
+
# end
|
|
13
|
+
#
|
|
14
|
+
# def deserialize(hash)
|
|
15
|
+
# Money.new(hash["amount"], hash["currency"])
|
|
16
|
+
# end
|
|
17
|
+
#
|
|
18
|
+
# private
|
|
19
|
+
#
|
|
20
|
+
# def klass
|
|
21
|
+
# Money
|
|
22
|
+
# end
|
|
23
|
+
# end
|
|
24
|
+
class ObjectSerializer
|
|
25
|
+
include Singleton
|
|
26
|
+
|
|
27
|
+
class << self
|
|
28
|
+
delegate :serialize?, :serialize, :deserialize, to: :instance
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Determines if an argument should be serialized by a serializer.
|
|
32
|
+
def serialize?(argument)
|
|
33
|
+
argument.is_a?(klass)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Serializes an argument to a JSON primitive type.
|
|
37
|
+
def serialize(hash)
|
|
38
|
+
{ Arguments::OBJECT_SERIALIZER_KEY => self.class.name }.merge!(hash)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Deserializes an argument from a JSON primitive type.
|
|
42
|
+
def deserialize(json)
|
|
43
|
+
raise NotImplementedError
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
# The class of the object that will be serialized.
|
|
48
|
+
def klass # :doc:
|
|
49
|
+
raise NotImplementedError
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveJob
|
|
4
|
+
module Serializers
|
|
5
|
+
class SymbolSerializer < ObjectSerializer # :nodoc:
|
|
6
|
+
def serialize(argument)
|
|
7
|
+
super("value" => argument.to_s)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def deserialize(argument)
|
|
11
|
+
argument["value"].to_sym
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
def klass
|
|
16
|
+
Symbol
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveJob
|
|
4
|
+
module Serializers
|
|
5
|
+
class TimeSerializer < TimeObjectSerializer # :nodoc:
|
|
6
|
+
def deserialize(hash)
|
|
7
|
+
Time.iso8601(hash["value"])
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
def klass
|
|
12
|
+
Time
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|