activejob 5.2.7.1 → 6.1.4.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +109 -58
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +18 -13
  5. data/lib/active_job/arguments.rb +80 -30
  6. data/lib/active_job/base.rb +6 -1
  7. data/lib/active_job/callbacks.rb +46 -3
  8. data/lib/active_job/configured_job.rb +2 -0
  9. data/lib/active_job/core.rb +40 -21
  10. data/lib/active_job/enqueuing.rb +20 -7
  11. data/lib/active_job/exceptions.rb +60 -28
  12. data/lib/active_job/execution.rb +11 -2
  13. data/lib/active_job/gem_version.rb +4 -4
  14. data/lib/active_job/instrumentation.rb +40 -0
  15. data/lib/active_job/log_subscriber.rb +140 -0
  16. data/lib/active_job/logging.rb +3 -101
  17. data/lib/active_job/queue_adapter.rb +5 -0
  18. data/lib/active_job/queue_adapters/async_adapter.rb +1 -1
  19. data/lib/active_job/queue_adapters/backburner_adapter.rb +2 -2
  20. data/lib/active_job/queue_adapters/inline_adapter.rb +1 -1
  21. data/lib/active_job/queue_adapters/que_adapter.rb +2 -2
  22. data/lib/active_job/queue_adapters/sidekiq_adapter.rb +2 -2
  23. data/lib/active_job/queue_adapters/sucker_punch_adapter.rb +1 -1
  24. data/lib/active_job/queue_adapters/test_adapter.rb +32 -14
  25. data/lib/active_job/queue_adapters.rb +13 -11
  26. data/lib/active_job/queue_name.rb +23 -3
  27. data/lib/active_job/railtie.rb +20 -1
  28. data/lib/active_job/serializers/date_serializer.rb +20 -0
  29. data/lib/active_job/serializers/date_time_serializer.rb +16 -0
  30. data/lib/active_job/serializers/duration_serializer.rb +23 -0
  31. data/lib/active_job/serializers/module_serializer.rb +20 -0
  32. data/lib/active_job/serializers/object_serializer.rb +53 -0
  33. data/lib/active_job/serializers/symbol_serializer.rb +20 -0
  34. data/lib/active_job/serializers/time_object_serializer.rb +13 -0
  35. data/lib/active_job/serializers/time_serializer.rb +16 -0
  36. data/lib/active_job/serializers/time_with_zone_serializer.rb +16 -0
  37. data/lib/active_job/serializers.rb +66 -0
  38. data/lib/active_job/test_helper.rb +317 -68
  39. data/lib/active_job/timezones.rb +13 -0
  40. data/lib/active_job/translation.rb +1 -1
  41. data/lib/active_job.rb +2 -1
  42. data/lib/rails/generators/job/job_generator.rb +4 -0
  43. metadata +26 -11
  44. data/lib/active_job/queue_adapters/qu_adapter.rb +0 -46
@@ -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 JobWrapper, [ job.serialize ], queue: job.queue_name
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 JobWrapper, [ job.serialize ], queue: job.queue_name, delay: delay
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 http://guides.rubyonrails.org/active_job_basics.html"
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.to_s,
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.to_s,
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 (eg. 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
  #
@@ -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
- enqueue_or_perform(perform_enqueued_jobs, job, job_data)
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
- enqueue_or_perform(perform_enqueued_at_jobs, job, job_data)
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
- { job: job.class, args: job.serialize.fetch("arguments"), queue: job.queue_name }.merge!(extras)
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 enqueue_or_perform(perform, job, job_data)
47
+ def perform_or_enqueue(perform, job, job_data)
48
48
  if perform
49
49
  performed_jobs << job_data
50
- Base.execute job.serialize
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
- !Array(filter).include?(job.class)
72
+ !filter_as_proc(filter).call(job)
59
73
  elsif reject
60
- Array(reject).include?(job.class)
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 queueing backends:
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}[http://sidekiq.org]
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}[http://api.rubyonrails.org/classes/ActiveJob/QueueAdapters/AsyncAdapter.html]
18
- # * {Active Job Inline}[http://api.rubyonrails.org/classes/ActiveJob/QueueAdapters/InlineAdapter.html]
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 queueing.
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: Does not allow the priority of jobs to be configured.
75
+ # No: The adapter does not allow the priority of jobs to be configured.
77
76
  #
78
- # N/A: The adapter does not support queueing, and therefore sorting them.
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".freeze
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.
@@ -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 { |k, v| send("#{k}=", v) }
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,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJob
4
+ module Serializers
5
+ class TimeObjectSerializer < ObjectSerializer # :nodoc:
6
+ NANO_PRECISION = 9
7
+
8
+ def serialize(time)
9
+ super("value" => time.iso8601(NANO_PRECISION))
10
+ end
11
+ end
12
+ end
13
+ 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
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveJob
4
+ module Serializers
5
+ class TimeWithZoneSerializer < TimeObjectSerializer # :nodoc:
6
+ def deserialize(hash)
7
+ Time.iso8601(hash["value"]).in_time_zone
8
+ end
9
+
10
+ private
11
+ def klass
12
+ ActiveSupport::TimeWithZone
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "set"
4
+
5
+ module ActiveJob
6
+ # The <tt>ActiveJob::Serializers</tt> module is used to store a list of known serializers
7
+ # and to add new ones. It also has helpers to serialize/deserialize objects.
8
+ module Serializers # :nodoc:
9
+ extend ActiveSupport::Autoload
10
+
11
+ autoload :ObjectSerializer
12
+ autoload :TimeObjectSerializer
13
+ autoload :SymbolSerializer
14
+ autoload :DurationSerializer
15
+ autoload :DateTimeSerializer
16
+ autoload :DateSerializer
17
+ autoload :TimeWithZoneSerializer
18
+ autoload :TimeSerializer
19
+ autoload :ModuleSerializer
20
+
21
+ mattr_accessor :_additional_serializers
22
+ self._additional_serializers = Set.new
23
+
24
+ class << self
25
+ # Returns serialized representative of the passed object.
26
+ # Will look up through all known serializers.
27
+ # Raises <tt>ActiveJob::SerializationError</tt> if it can't find a proper serializer.
28
+ def serialize(argument)
29
+ serializer = serializers.detect { |s| s.serialize?(argument) }
30
+ raise SerializationError.new("Unsupported argument type: #{argument.class.name}") unless serializer
31
+ serializer.serialize(argument)
32
+ end
33
+
34
+ # Returns deserialized object.
35
+ # Will look up through all known serializers.
36
+ # If no serializer found will raise <tt>ArgumentError</tt>.
37
+ def deserialize(argument)
38
+ serializer_name = argument[Arguments::OBJECT_SERIALIZER_KEY]
39
+ raise ArgumentError, "Serializer name is not present in the argument: #{argument.inspect}" unless serializer_name
40
+
41
+ serializer = serializer_name.safe_constantize
42
+ raise ArgumentError, "Serializer #{serializer_name} is not known" unless serializer
43
+
44
+ serializer.deserialize(argument)
45
+ end
46
+
47
+ # Returns list of known serializers.
48
+ def serializers
49
+ self._additional_serializers
50
+ end
51
+
52
+ # Adds new serializers to a list of known serializers.
53
+ def add_serializers(*new_serializers)
54
+ self._additional_serializers += new_serializers.flatten
55
+ end
56
+ end
57
+
58
+ add_serializers SymbolSerializer,
59
+ DurationSerializer,
60
+ DateTimeSerializer,
61
+ DateSerializer,
62
+ TimeWithZoneSerializer,
63
+ TimeSerializer,
64
+ ModuleSerializer
65
+ end
66
+ end