activejob 7.2.2.1 → 8.1.2

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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +90 -50
  3. data/README.md +8 -6
  4. data/lib/active_job/arguments.rb +51 -48
  5. data/lib/active_job/base.rb +5 -6
  6. data/lib/active_job/configured_job.rb +5 -4
  7. data/lib/active_job/continuable.rb +102 -0
  8. data/lib/active_job/continuation/step.rb +83 -0
  9. data/lib/active_job/continuation/test_helper.rb +89 -0
  10. data/lib/active_job/continuation/validation.rb +50 -0
  11. data/lib/active_job/continuation.rb +332 -0
  12. data/lib/active_job/core.rb +22 -4
  13. data/lib/active_job/enqueue_after_transaction_commit.rb +20 -10
  14. data/lib/active_job/enqueuing.rb +11 -8
  15. data/lib/active_job/exceptions.rb +16 -6
  16. data/lib/active_job/execution_state.rb +11 -0
  17. data/lib/active_job/gem_version.rb +3 -3
  18. data/lib/active_job/instrumentation.rb +12 -12
  19. data/lib/active_job/log_subscriber.rb +64 -5
  20. data/lib/active_job/queue_adapter.rb +1 -0
  21. data/lib/active_job/queue_adapters/abstract_adapter.rb +5 -7
  22. data/lib/active_job/queue_adapters/async_adapter.rb +6 -2
  23. data/lib/active_job/queue_adapters/delayed_job_adapter.rb +0 -8
  24. data/lib/active_job/queue_adapters/inline_adapter.rb +0 -4
  25. data/lib/active_job/queue_adapters/queue_classic_adapter.rb +0 -8
  26. data/lib/active_job/queue_adapters/sidekiq_adapter.rb +19 -0
  27. data/lib/active_job/queue_adapters/test_adapter.rb +5 -9
  28. data/lib/active_job/queue_adapters.rb +0 -4
  29. data/lib/active_job/railtie.rb +15 -6
  30. data/lib/active_job/serializers/action_controller_parameters_serializer.rb +25 -0
  31. data/lib/active_job/serializers/big_decimal_serializer.rb +3 -4
  32. data/lib/active_job/serializers/date_serializer.rb +3 -4
  33. data/lib/active_job/serializers/date_time_serializer.rb +3 -4
  34. data/lib/active_job/serializers/duration_serializer.rb +5 -6
  35. data/lib/active_job/serializers/module_serializer.rb +3 -4
  36. data/lib/active_job/serializers/object_serializer.rb +11 -14
  37. data/lib/active_job/serializers/range_serializer.rb +9 -9
  38. data/lib/active_job/serializers/symbol_serializer.rb +4 -5
  39. data/lib/active_job/serializers/time_serializer.rb +3 -4
  40. data/lib/active_job/serializers/time_with_zone_serializer.rb +3 -4
  41. data/lib/active_job/serializers.rb +62 -18
  42. data/lib/active_job/structured_event_subscriber.rb +220 -0
  43. data/lib/active_job.rb +3 -12
  44. metadata +17 -15
  45. data/lib/active_job/queue_adapters/sucker_punch_adapter.rb +0 -49
  46. data/lib/active_job/timezones.rb +0 -13
  47. data/lib/active_job/translation.rb +0 -13
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJob
4
+ module ExecutionState # :nodoc:
5
+ def perform_now
6
+ I18n.with_locale(locale) do
7
+ Time.use_zone(timezone) { super }
8
+ end
9
+ end
10
+ end
11
+ end
@@ -7,10 +7,10 @@ module ActiveJob
7
7
  end
8
8
 
9
9
  module VERSION
10
- MAJOR = 7
11
- MINOR = 2
10
+ MAJOR = 8
11
+ MINOR = 1
12
12
  TINY = 2
13
- PRE = "1"
13
+ PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -26,24 +26,24 @@ module ActiveJob
26
26
  instrument(:perform) { super }
27
27
  end
28
28
 
29
+ def instrument(operation, payload = {}, &block) # :nodoc:
30
+ payload[:job] = self
31
+ payload[:adapter] = queue_adapter
32
+
33
+ ActiveSupport::Notifications.instrument("#{operation}.active_job", payload) do |payload|
34
+ value = block.call(payload) if block
35
+ payload[:aborted] = @_halted_callback_hook_called if defined?(@_halted_callback_hook_called)
36
+ @_halted_callback_hook_called = nil
37
+ value
38
+ end
39
+ end
40
+
29
41
  private
30
42
  def _perform_job
31
43
  instrument(:perform_start)
32
44
  super
33
45
  end
34
46
 
35
- def instrument(operation, payload = {}, &block)
36
- payload[:job] = self
37
- payload[:adapter] = queue_adapter
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
43
- value
44
- end
45
- end
46
-
47
47
  def halted_callback_hook(*)
48
48
  super
49
49
  @_halted_callback_hook_called = true
@@ -50,7 +50,7 @@ module ActiveJob
50
50
  info do
51
51
  jobs = event.payload[:jobs]
52
52
  adapter = event.payload[:adapter]
53
- enqueued_count = event.payload[:enqueued_count]
53
+ enqueued_count = event.payload[:enqueued_count].to_i
54
54
 
55
55
  if enqueued_count == jobs.size
56
56
  enqueued_jobs_message(adapter, jobs)
@@ -87,8 +87,9 @@ module ActiveJob
87
87
  job = event.payload[:job]
88
88
  ex = event.payload[:exception_object]
89
89
  if ex
90
+ cleaned_backtrace = backtrace_cleaner.clean(ex.backtrace)
90
91
  error do
91
- "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")
92
+ "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(cleaned_backtrace).join("\n")
92
93
  end
93
94
  elsif event.payload[:aborted]
94
95
  error do
@@ -137,6 +138,64 @@ module ActiveJob
137
138
  end
138
139
  subscribe_log_level :discard, :error
139
140
 
141
+ def interrupt(event)
142
+ job = event.payload[:job]
143
+ info do
144
+ "Interrupted #{job.class} (Job ID: #{job.job_id}) #{event.payload[:description]} (#{event.payload[:reason]})"
145
+ end
146
+ end
147
+ subscribe_log_level :interrupt, :info
148
+
149
+ def resume(event)
150
+ job = event.payload[:job]
151
+ info do
152
+ "Resuming #{job.class} (Job ID: #{job.job_id}) #{event.payload[:description]}"
153
+ end
154
+ end
155
+ subscribe_log_level :resume, :info
156
+
157
+ def step_skipped(event)
158
+ job = event.payload[:job]
159
+ info do
160
+ "Step '#{event.payload[:step].name}' skipped #{job.class}"
161
+ end
162
+ end
163
+ subscribe_log_level :step_skipped, :info
164
+
165
+ def step_started(event)
166
+ job = event.payload[:job]
167
+ step = event.payload[:step]
168
+ info do
169
+ if step.resumed?
170
+ "Step '#{step.name}' resumed from cursor '#{step.cursor}' for #{job.class} (Job ID: #{job.job_id})"
171
+ else
172
+ "Step '#{step.name}' started for #{job.class} (Job ID: #{job.job_id})"
173
+ end
174
+ end
175
+ end
176
+ subscribe_log_level :step_started, :info
177
+
178
+ def step(event)
179
+ job = event.payload[:job]
180
+ step = event.payload[:step]
181
+ ex = event.payload[:exception_object]
182
+
183
+ if event.payload[:interrupted]
184
+ info do
185
+ "Step '#{step.name}' interrupted at cursor '#{step.cursor}' for #{job.class} (Job ID: #{job.job_id}) in #{event.duration.round(2)}ms"
186
+ end
187
+ elsif ex
188
+ error do
189
+ "Error during step '#{step.name}' at cursor '#{step.cursor}' for #{job.class} (Job ID: #{job.job_id}) in #{event.duration.round(2)}ms: #{ex.class} (#{ex.message})"
190
+ end
191
+ else
192
+ info do
193
+ "Step '#{step.name}' completed for #{job.class} (Job ID: #{job.job_id}) in #{event.duration.round(2)}ms"
194
+ end
195
+ end
196
+ end
197
+ subscribe_log_level :step, :error
198
+
140
199
  private
141
200
  def queue_name(event)
142
201
  ActiveJob.adapter_name(event.payload[:adapter]) + "(#{event.payload[:job].queue_name})"
@@ -189,15 +248,15 @@ module ActiveJob
189
248
  end
190
249
 
191
250
  def log_enqueue_source
192
- source = extract_enqueue_source_location(caller)
251
+ source = enqueue_source_location
193
252
 
194
253
  if source
195
254
  logger.info("↳ #{source}")
196
255
  end
197
256
  end
198
257
 
199
- def extract_enqueue_source_location(locations)
200
- backtrace_cleaner.clean(locations.lazy).first
258
+ def enqueue_source_location
259
+ backtrace_cleaner.first_clean_frame
201
260
  end
202
261
 
203
262
  def enqueued_jobs_message(adapter, enqueued_jobs)
@@ -50,6 +50,7 @@ module ActiveJob
50
50
  case name_or_adapter
51
51
  when Symbol, String
52
52
  queue_adapter = ActiveJob::QueueAdapters.lookup(name_or_adapter).new
53
+ queue_adapter.try(:check_adapter)
53
54
  assign_adapter(name_or_adapter.to_s, queue_adapter)
54
55
  else
55
56
  if queue_adapter?(name_or_adapter)
@@ -7,13 +7,7 @@ module ActiveJob
7
7
  # Active Job supports multiple job queue systems. ActiveJob::QueueAdapters::AbstractAdapter
8
8
  # forms the abstraction layer which makes this possible.
9
9
  class AbstractAdapter
10
- # Defines whether enqueuing should happen implicitly to after commit when called
11
- # from inside a transaction. Most adapters should return true, but some adapters
12
- # that use the same database as Active Record and are transaction aware can return
13
- # false to continue enqueuing jobs as part of the transaction.
14
- def enqueue_after_transaction_commit?
15
- true
16
- end
10
+ attr_accessor :stopping
17
11
 
18
12
  def enqueue(job)
19
13
  raise NotImplementedError
@@ -22,6 +16,10 @@ module ActiveJob
22
16
  def enqueue_at(job, timestamp)
23
17
  raise NotImplementedError
24
18
  end
19
+
20
+ def stopping?
21
+ !!@stopping
22
+ end
25
23
  end
26
24
  end
27
25
  end
@@ -74,7 +74,7 @@ module ActiveJob
74
74
  class Scheduler # :nodoc:
75
75
  DEFAULT_EXECUTOR_OPTIONS = {
76
76
  min_threads: 0,
77
- max_threads: Concurrent.processor_count,
77
+ max_threads: ENV.fetch("RAILS_MAX_THREADS", 5).to_i,
78
78
  auto_terminate: true,
79
79
  idletime: 60, # 1 minute
80
80
  max_queue: 0, # unlimited
@@ -86,7 +86,11 @@ module ActiveJob
86
86
  def initialize(**options)
87
87
  self.immediate = false
88
88
  @immediate_executor = Concurrent::ImmediateExecutor.new
89
- @async_executor = Concurrent::ThreadPoolExecutor.new(DEFAULT_EXECUTOR_OPTIONS.merge(options))
89
+ @async_executor = Concurrent::ThreadPoolExecutor.new(
90
+ name: "ActiveJob-async-scheduler",
91
+ **DEFAULT_EXECUTOR_OPTIONS,
92
+ **options
93
+ )
90
94
  end
91
95
 
92
96
  def enqueue(job, queue_name:)
@@ -16,14 +16,6 @@ module ActiveJob
16
16
  #
17
17
  # Rails.application.config.active_job.queue_adapter = :delayed_job
18
18
  class DelayedJobAdapter < AbstractAdapter
19
- def initialize(enqueue_after_transaction_commit: false)
20
- @enqueue_after_transaction_commit = enqueue_after_transaction_commit
21
- end
22
-
23
- def enqueue_after_transaction_commit? # :nodoc:
24
- @enqueue_after_transaction_commit
25
- end
26
-
27
19
  def enqueue(job) # :nodoc:
28
20
  delayed_job = Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name, priority: job.priority)
29
21
  job.provider_job_id = delayed_job.id
@@ -11,10 +11,6 @@ module ActiveJob
11
11
  #
12
12
  # Rails.application.config.active_job.queue_adapter = :inline
13
13
  class InlineAdapter < AbstractAdapter
14
- def enqueue_after_transaction_commit? # :nodoc:
15
- false
16
- end
17
-
18
14
  def enqueue(job) # :nodoc:
19
15
  Base.execute(job.serialize)
20
16
  end
@@ -19,14 +19,6 @@ module ActiveJob
19
19
  #
20
20
  # Rails.application.config.active_job.queue_adapter = :queue_classic
21
21
  class QueueClassicAdapter < AbstractAdapter
22
- def initialize(enqueue_after_transaction_commit: false)
23
- @enqueue_after_transaction_commit = enqueue_after_transaction_commit
24
- end
25
-
26
- def enqueue_after_transaction_commit? # :nodoc:
27
- @enqueue_after_transaction_commit
28
- end
29
-
30
22
  def enqueue(job) # :nodoc:
31
23
  qc_job = build_queue(job.queue_name).enqueue("#{JobWrapper.name}.perform", job.serialize)
32
24
  job.provider_job_id = qc_job["id"] if qc_job.is_a?(Hash)
@@ -18,6 +18,25 @@ module ActiveJob
18
18
  #
19
19
  # Rails.application.config.active_job.queue_adapter = :sidekiq
20
20
  class SidekiqAdapter < AbstractAdapter
21
+ def initialize(*) # :nodoc:
22
+ @stopping = false
23
+
24
+ Sidekiq.configure_server do |config|
25
+ config.on(:quiet) { @stopping = true }
26
+ end
27
+
28
+ Sidekiq.configure_client do |config|
29
+ config.on(:quiet) { @stopping = true }
30
+ end
31
+ end
32
+
33
+ def check_adapter
34
+ ActiveJob.deprecator.warn <<~MSG.squish
35
+ The built-in `sidekiq` adapter is deprecated and will be removed in Rails 8.2.
36
+ Please upgrade `sidekiq` gem to version 7.3.3 or later to use the `sidekiq` gem's adapter.
37
+ MSG
38
+ end
39
+
21
40
  def enqueue(job) # :nodoc:
22
41
  job.provider_job_id = JobWrapper.set(
23
42
  wrapped: job.class,
@@ -12,17 +12,9 @@ module ActiveJob
12
12
  #
13
13
  # Rails.application.config.active_job.queue_adapter = :test
14
14
  class TestAdapter < AbstractAdapter
15
- attr_accessor(:perform_enqueued_jobs, :perform_enqueued_at_jobs, :filter, :reject, :queue, :at, :enqueue_after_transaction_commit)
15
+ attr_accessor(:perform_enqueued_jobs, :perform_enqueued_at_jobs, :filter, :reject, :queue, :at, :stopping)
16
16
  attr_writer(:enqueued_jobs, :performed_jobs)
17
17
 
18
- def initialize(enqueue_after_transaction_commit: true)
19
- @enqueue_after_transaction_commit = enqueue_after_transaction_commit
20
- end
21
-
22
- def enqueue_after_transaction_commit? # :nodoc:
23
- @enqueue_after_transaction_commit
24
- end
25
-
26
18
  # Provides a store of all the enqueued jobs with the TestAdapter so you can check them.
27
19
  def enqueued_jobs
28
20
  @enqueued_jobs ||= []
@@ -43,6 +35,10 @@ module ActiveJob
43
35
  perform_or_enqueue(perform_enqueued_at_jobs && !filtered?(job), job, job_data)
44
36
  end
45
37
 
38
+ def stopping?
39
+ @stopping.is_a?(Proc) ? @stopping.call : @stopping
40
+ end
41
+
46
42
  private
47
43
  def job_to_hash(job, extras = {})
48
44
  job.serialize.tap do |job_data|
@@ -12,7 +12,6 @@ module ActiveJob
12
12
  # * {Resque}[https://github.com/resque/resque]
13
13
  # * {Sidekiq}[https://sidekiq.org]
14
14
  # * {Sneakers}[https://github.com/jondot/sneakers]
15
- # * {Sucker Punch}[https://github.com/brandonhilkert/sucker_punch]
16
15
  # * Please Note: We are not accepting pull requests for new adapters. See the {README}[link:files/activejob/README_md.html] for more details.
17
16
  #
18
17
  # For testing and development Active Job has three built-in adapters:
@@ -32,7 +31,6 @@ module ActiveJob
32
31
  # | Resque | Yes | Yes | Yes (Gem) | Queue | Global | Yes |
33
32
  # | Sidekiq | Yes | Yes | Yes | Queue | No | Job |
34
33
  # | Sneakers | Yes | Yes | No | Queue | Queue | No |
35
- # | Sucker Punch | Yes | Yes | Yes | No | No | No |
36
34
  # | Active Job Async | Yes | Yes | Yes | No | No | No |
37
35
  # | Active Job Inline | No | Yes | N/A | N/A | N/A | N/A |
38
36
  # | Active Job Test | No | Yes | N/A | N/A | N/A | N/A |
@@ -119,12 +117,10 @@ module ActiveJob
119
117
  autoload :InlineAdapter
120
118
  autoload :BackburnerAdapter
121
119
  autoload :DelayedJobAdapter
122
- autoload :QueAdapter
123
120
  autoload :QueueClassicAdapter
124
121
  autoload :ResqueAdapter
125
122
  autoload :SidekiqAdapter
126
123
  autoload :SneakersAdapter
127
- autoload :SuckerPunchAdapter
128
124
  autoload :TestAdapter
129
125
 
130
126
  ADAPTER = "Adapter"
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "rails"
3
4
  require "global_id/railtie"
4
5
  require "active_job"
5
6
 
@@ -19,7 +20,7 @@ module ActiveJob
19
20
  end
20
21
 
21
22
  initializer "active_job.custom_serializers" do |app|
22
- config.after_initialize do
23
+ ActiveSupport.on_load(:active_job_arguments) do
23
24
  custom_serializers = app.config.active_job.custom_serializers
24
25
  ActiveJob::Serializers.add_serializers custom_serializers
25
26
  end
@@ -29,10 +30,14 @@ module ActiveJob
29
30
  ActiveSupport.on_load(:active_job) do
30
31
  ActiveSupport.on_load(:active_record) do
31
32
  ActiveJob::Base.include EnqueueAfterTransactionCommit
33
+ end
34
+ end
35
+ end
32
36
 
33
- if app.config.active_job.key?(:enqueue_after_transaction_commit)
34
- ActiveJob::Base.enqueue_after_transaction_commit = app.config.active_job.delete(:enqueue_after_transaction_commit)
35
- end
37
+ initializer "active_job.action_controller_parameters" do |app|
38
+ ActiveSupport.on_load(:active_job) do
39
+ ActiveSupport.on_load(:action_controller) do
40
+ ActiveJob::Serializers.add_serializers ActiveJob::Serializers::ActionControllerParametersSerializer
36
41
  end
37
42
  end
38
43
  end
@@ -54,7 +59,9 @@ module ActiveJob
54
59
  # Configs used in other initializers
55
60
  options = options.except(
56
61
  :log_query_tags_around_perform,
57
- :custom_serializers
62
+ :custom_serializers,
63
+ # This config can't be applied globally, so we need to remove otherwise it will be applied to `ActiveJob::Base`.
64
+ :enqueue_after_transaction_commit
58
65
  )
59
66
 
60
67
  options.each do |k, v|
@@ -91,7 +98,9 @@ module ActiveJob
91
98
  app.config.active_record.query_log_tags |= [:job]
92
99
 
93
100
  ActiveSupport.on_load(:active_record) do
94
- ActiveRecord::QueryLogs.taggings[:job] = ->(context) { context[:job].class.name if context[:job] }
101
+ ActiveRecord::QueryLogs.taggings = ActiveRecord::QueryLogs.taggings.merge(
102
+ job: ->(context) { context[:job].class.name if context[:job] }
103
+ )
95
104
  end
96
105
  end
97
106
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJob
4
+ module Serializers
5
+ class ActionControllerParametersSerializer < ObjectSerializer
6
+ def serialize(argument)
7
+ Arguments.serialize_argument(argument.to_h.with_indifferent_access)
8
+ end
9
+
10
+ def deserialize(hash)
11
+ raise NotImplementedError # Serialized as a HashWithIndifferentAccess
12
+ end
13
+
14
+ def serialize?(argument)
15
+ argument.respond_to?(:permitted?) && argument.respond_to?(:to_h)
16
+ end
17
+
18
+ def klass
19
+ if defined?(ActionController::Parameters)
20
+ ActionController::Parameters
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -13,10 +13,9 @@ module ActiveJob
13
13
  BigDecimal(hash["value"])
14
14
  end
15
15
 
16
- private
17
- def klass
18
- BigDecimal
19
- end
16
+ def klass
17
+ BigDecimal
18
+ end
20
19
  end
21
20
  end
22
21
  end
@@ -11,10 +11,9 @@ module ActiveJob
11
11
  Date.iso8601(hash["value"])
12
12
  end
13
13
 
14
- private
15
- def klass
16
- Date
17
- end
14
+ def klass
15
+ Date
16
+ end
18
17
  end
19
18
  end
20
19
  end
@@ -7,10 +7,9 @@ module ActiveJob
7
7
  DateTime.iso8601(hash["value"])
8
8
  end
9
9
 
10
- private
11
- def klass
12
- DateTime
13
- end
10
+ def klass
11
+ DateTime
12
+ end
14
13
  end
15
14
  end
16
15
  end
@@ -6,20 +6,19 @@ module ActiveJob
6
6
  def serialize(duration)
7
7
  # Ideally duration.parts would be wrapped in an array before passing to Arguments.serialize,
8
8
  # but we continue passing the bare hash for backwards compatibility:
9
- super("value" => duration.value, "parts" => Arguments.serialize(duration.parts))
9
+ super("value" => duration.value, "parts" => Arguments.serialize(duration.parts.to_a))
10
10
  end
11
11
 
12
12
  def deserialize(hash)
13
13
  value = hash["value"]
14
- parts = Arguments.deserialize(hash["parts"])
14
+ parts = Arguments.deserialize(hash["parts"].to_h)
15
15
  # `parts` is originally a hash, but will have been flattened to an array by Arguments.serialize
16
16
  klass.new(value, parts.to_h)
17
17
  end
18
18
 
19
- private
20
- def klass
21
- ActiveSupport::Duration
22
- end
19
+ def klass
20
+ ActiveSupport::Duration
21
+ end
23
22
  end
24
23
  end
25
24
  end
@@ -12,10 +12,9 @@ module ActiveJob
12
12
  hash["value"].constantize
13
13
  end
14
14
 
15
- private
16
- def klass
17
- Module
18
- end
15
+ def klass
16
+ Module
17
+ end
19
18
  end
20
19
  end
21
20
  end
@@ -17,11 +17,9 @@ module ActiveJob
17
17
  # Money.new(hash["amount"], hash["currency"])
18
18
  # end
19
19
  #
20
- # private
21
- #
22
- # def klass
23
- # Money
24
- # end
20
+ # def klass
21
+ # Money
22
+ # end
25
23
  # end
26
24
  class ObjectSerializer
27
25
  include Singleton
@@ -30,6 +28,11 @@ module ActiveJob
30
28
  delegate :serialize?, :serialize, :deserialize, to: :instance
31
29
  end
32
30
 
31
+ def initialize
32
+ super
33
+ @template = { Serializers::OBJECT_SERIALIZER_KEY => self.class.name }.freeze
34
+ end
35
+
33
36
  # Determines if an argument should be serialized by a serializer.
34
37
  def serialize?(argument)
35
38
  argument.is_a?(klass)
@@ -37,19 +40,13 @@ module ActiveJob
37
40
 
38
41
  # Serializes an argument to a JSON primitive type.
39
42
  def serialize(hash)
40
- { Arguments::OBJECT_SERIALIZER_KEY => self.class.name }.merge!(hash)
43
+ @template.merge(hash)
41
44
  end
42
45
 
43
46
  # Deserializes an argument from a JSON primitive type.
44
- def deserialize(json)
45
- raise NotImplementedError
47
+ def deserialize(hash)
48
+ raise NotImplementedError, "#{self.class.name} should implement a public #deserialize(hash) method"
46
49
  end
47
-
48
- private
49
- # The class of the object that will be serialized.
50
- def klass # :doc:
51
- raise NotImplementedError
52
- end
53
50
  end
54
51
  end
55
52
  end
@@ -3,21 +3,21 @@
3
3
  module ActiveJob
4
4
  module Serializers
5
5
  class RangeSerializer < ObjectSerializer
6
- KEYS = %w[begin end exclude_end].freeze
7
-
8
6
  def serialize(range)
9
- args = Arguments.serialize([range.begin, range.end, range.exclude_end?])
10
- super(KEYS.zip(args).to_h)
7
+ super(
8
+ "begin" => Arguments.serialize_argument(range.begin),
9
+ "end" => Arguments.serialize_argument(range.end),
10
+ "exclude_end" => range.exclude_end?, # Always boolean, no need to serialize
11
+ )
11
12
  end
12
13
 
13
14
  def deserialize(hash)
14
- klass.new(*Arguments.deserialize(hash.values_at(*KEYS)))
15
+ Range.new(*Arguments.deserialize([hash["begin"], hash["end"]]), hash["exclude_end"])
15
16
  end
16
17
 
17
- private
18
- def klass
19
- ::Range
20
- end
18
+ def klass
19
+ ::Range
20
+ end
21
21
  end
22
22
  end
23
23
  end
@@ -4,17 +4,16 @@ module ActiveJob
4
4
  module Serializers
5
5
  class SymbolSerializer < ObjectSerializer # :nodoc:
6
6
  def serialize(argument)
7
- super("value" => argument.to_s)
7
+ super("value" => argument.name)
8
8
  end
9
9
 
10
10
  def deserialize(argument)
11
11
  argument["value"].to_sym
12
12
  end
13
13
 
14
- private
15
- def klass
16
- Symbol
17
- end
14
+ def klass
15
+ Symbol
16
+ end
18
17
  end
19
18
  end
20
19
  end
@@ -7,10 +7,9 @@ module ActiveJob
7
7
  Time.iso8601(hash["value"])
8
8
  end
9
9
 
10
- private
11
- def klass
12
- Time
13
- end
10
+ def klass
11
+ Time
12
+ end
14
13
  end
15
14
  end
16
15
  end
@@ -16,10 +16,9 @@ module ActiveJob
16
16
  Time.iso8601(hash["value"]).in_time_zone(hash["time_zone"] || Time.zone)
17
17
  end
18
18
 
19
- private
20
- def klass
21
- ActiveSupport::TimeWithZone
22
- end
19
+ def klass
20
+ ActiveSupport::TimeWithZone
21
+ end
23
22
  end
24
23
  end
25
24
  end