activejob 7.1.5.2 → 8.1.2.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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +86 -264
  3. data/README.md +8 -6
  4. data/lib/active_job/arguments.rb +51 -59
  5. data/lib/active_job/base.rb +5 -6
  6. data/lib/active_job/callbacks.rb +0 -3
  7. data/lib/active_job/configured_job.rb +5 -4
  8. data/lib/active_job/continuable.rb +102 -0
  9. data/lib/active_job/continuation/step.rb +83 -0
  10. data/lib/active_job/continuation/test_helper.rb +89 -0
  11. data/lib/active_job/continuation/validation.rb +50 -0
  12. data/lib/active_job/continuation.rb +332 -0
  13. data/lib/active_job/core.rb +25 -22
  14. data/lib/active_job/enqueue_after_transaction_commit.rb +38 -0
  15. data/lib/active_job/enqueuing.rb +46 -12
  16. data/lib/active_job/exceptions.rb +21 -17
  17. data/lib/active_job/execution_state.rb +11 -0
  18. data/lib/active_job/gem_version.rb +3 -3
  19. data/lib/active_job/instrumentation.rb +12 -12
  20. data/lib/active_job/log_subscriber.rb +65 -6
  21. data/lib/active_job/logging.rb +16 -2
  22. data/lib/active_job/queue_adapter.rb +6 -4
  23. data/lib/active_job/queue_adapters/abstract_adapter.rb +25 -0
  24. data/lib/active_job/queue_adapters/async_adapter.rb +7 -3
  25. data/lib/active_job/queue_adapters/backburner_adapter.rb +1 -1
  26. data/lib/active_job/queue_adapters/delayed_job_adapter.rb +1 -1
  27. data/lib/active_job/queue_adapters/inline_adapter.rb +1 -1
  28. data/lib/active_job/queue_adapters/queue_classic_adapter.rb +1 -1
  29. data/lib/active_job/queue_adapters/resque_adapter.rb +1 -1
  30. data/lib/active_job/queue_adapters/sidekiq_adapter.rb +20 -1
  31. data/lib/active_job/queue_adapters/sneakers_adapter.rb +1 -1
  32. data/lib/active_job/queue_adapters/test_adapter.rb +6 -2
  33. data/lib/active_job/queue_adapters.rb +1 -4
  34. data/lib/active_job/railtie.rb +25 -4
  35. data/lib/active_job/serializers/action_controller_parameters_serializer.rb +25 -0
  36. data/lib/active_job/serializers/big_decimal_serializer.rb +3 -4
  37. data/lib/active_job/serializers/date_serializer.rb +3 -4
  38. data/lib/active_job/serializers/date_time_serializer.rb +3 -4
  39. data/lib/active_job/serializers/duration_serializer.rb +5 -6
  40. data/lib/active_job/serializers/module_serializer.rb +3 -4
  41. data/lib/active_job/serializers/object_serializer.rb +13 -14
  42. data/lib/active_job/serializers/range_serializer.rb +9 -9
  43. data/lib/active_job/serializers/symbol_serializer.rb +4 -5
  44. data/lib/active_job/serializers/time_serializer.rb +3 -4
  45. data/lib/active_job/serializers/time_with_zone_serializer.rb +3 -4
  46. data/lib/active_job/serializers.rb +62 -18
  47. data/lib/active_job/structured_event_subscriber.rb +220 -0
  48. data/lib/active_job/test_helper.rb +28 -5
  49. data/lib/active_job.rb +5 -9
  50. metadata +18 -11
  51. data/lib/active_job/queue_adapters/sucker_punch_adapter.rb +0 -49
  52. data/lib/active_job/timezones.rb +0 -13
  53. data/lib/active_job/translation.rb +0 -13
@@ -15,7 +15,7 @@ module ActiveJob
15
15
  # To use Delayed Job, set the queue_adapter config to +:delayed_job+.
16
16
  #
17
17
  # Rails.application.config.active_job.queue_adapter = :delayed_job
18
- class DelayedJobAdapter
18
+ class DelayedJobAdapter < AbstractAdapter
19
19
  def enqueue(job) # :nodoc:
20
20
  delayed_job = Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name, priority: job.priority)
21
21
  job.provider_job_id = delayed_job.id
@@ -10,7 +10,7 @@ module ActiveJob
10
10
  # To use the Inline set the queue_adapter config to +:inline+.
11
11
  #
12
12
  # Rails.application.config.active_job.queue_adapter = :inline
13
- class InlineAdapter
13
+ class InlineAdapter < AbstractAdapter
14
14
  def enqueue(job) # :nodoc:
15
15
  Base.execute(job.serialize)
16
16
  end
@@ -18,7 +18,7 @@ module ActiveJob
18
18
  # To use queue_classic set the queue_adapter config to +:queue_classic+.
19
19
  #
20
20
  # Rails.application.config.active_job.queue_adapter = :queue_classic
21
- class QueueClassicAdapter
21
+ class QueueClassicAdapter < AbstractAdapter
22
22
  def enqueue(job) # :nodoc:
23
23
  qc_job = build_queue(job.queue_name).enqueue("#{JobWrapper.name}.perform", job.serialize)
24
24
  job.provider_job_id = qc_job["id"] if qc_job.is_a?(Hash)
@@ -27,7 +27,7 @@ module ActiveJob
27
27
  # To use Resque set the queue_adapter config to +:resque+.
28
28
  #
29
29
  # Rails.application.config.active_job.queue_adapter = :resque
30
- class ResqueAdapter
30
+ class ResqueAdapter < AbstractAdapter
31
31
  def enqueue(job) # :nodoc:
32
32
  JobWrapper.instance_variable_set(:@queue, job.queue_name)
33
33
  Resque.enqueue_to job.queue_name, JobWrapper, job.serialize
@@ -17,7 +17,26 @@ module ActiveJob
17
17
  # To use Sidekiq set the queue_adapter config to +:sidekiq+.
18
18
  #
19
19
  # Rails.application.config.active_job.queue_adapter = :sidekiq
20
- class SidekiqAdapter
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,
@@ -17,7 +17,7 @@ module ActiveJob
17
17
  # To use Sneakers set the queue_adapter config to +:sneakers+.
18
18
  #
19
19
  # Rails.application.config.active_job.queue_adapter = :sneakers
20
- class SneakersAdapter
20
+ class SneakersAdapter < AbstractAdapter
21
21
  def initialize
22
22
  @monitor = Monitor.new
23
23
  end
@@ -11,8 +11,8 @@ module ActiveJob
11
11
  # To use the test adapter set +queue_adapter+ config to +:test+.
12
12
  #
13
13
  # Rails.application.config.active_job.queue_adapter = :test
14
- class TestAdapter
15
- attr_accessor(:perform_enqueued_jobs, :perform_enqueued_at_jobs, :filter, :reject, :queue, :at)
14
+ class TestAdapter < AbstractAdapter
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
18
  # Provides a store of all the enqueued jobs with the TestAdapter so you can check them.
@@ -35,6 +35,10 @@ module ActiveJob
35
35
  perform_or_enqueue(perform_enqueued_at_jobs && !filtered?(job), job, job_data)
36
36
  end
37
37
 
38
+ def stopping?
39
+ @stopping.is_a?(Proc) ? @stopping.call : @stopping
40
+ end
41
+
38
42
  private
39
43
  def job_to_hash(job, extras = {})
40
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 |
@@ -114,16 +112,15 @@ module ActiveJob
114
112
  module QueueAdapters
115
113
  extend ActiveSupport::Autoload
116
114
 
115
+ autoload :AbstractAdapter
117
116
  autoload :AsyncAdapter
118
117
  autoload :InlineAdapter
119
118
  autoload :BackburnerAdapter
120
119
  autoload :DelayedJobAdapter
121
- autoload :QueAdapter
122
120
  autoload :QueueClassicAdapter
123
121
  autoload :ResqueAdapter
124
122
  autoload :SidekiqAdapter
125
123
  autoload :SneakersAdapter
126
- autoload :SuckerPunchAdapter
127
124
  autoload :TestAdapter
128
125
 
129
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,15 +20,31 @@ 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
26
27
  end
27
28
 
29
+ initializer "active_job.enqueue_after_transaction_commit" do |app|
30
+ ActiveSupport.on_load(:active_job) do
31
+ ActiveSupport.on_load(:active_record) do
32
+ ActiveJob::Base.include EnqueueAfterTransactionCommit
33
+ end
34
+ end
35
+ end
36
+
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
41
+ end
42
+ end
43
+ end
44
+
28
45
  initializer "active_job.set_configs" do |app|
29
46
  options = app.config.active_job
30
- options.queue_adapter ||= :async
47
+ options.queue_adapter ||= (Rails.env.test? ? :test : :async)
31
48
 
32
49
  config.after_initialize do
33
50
  options.each do |k, v|
@@ -42,7 +59,9 @@ module ActiveJob
42
59
  # Configs used in other initializers
43
60
  options = options.except(
44
61
  :log_query_tags_around_perform,
45
- :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
46
65
  )
47
66
 
48
67
  options.each do |k, v|
@@ -79,7 +98,9 @@ module ActiveJob
79
98
  app.config.active_record.query_log_tags |= [:job]
80
99
 
81
100
  ActiveSupport.on_load(:active_record) do
82
- 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
+ )
83
104
  end
84
105
  end
85
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
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "singleton"
4
+
3
5
  module ActiveJob
4
6
  module Serializers
5
7
  # Base class for serializing and deserializing custom objects.
@@ -15,11 +17,9 @@ module ActiveJob
15
17
  # Money.new(hash["amount"], hash["currency"])
16
18
  # end
17
19
  #
18
- # private
19
- #
20
- # def klass
21
- # Money
22
- # end
20
+ # def klass
21
+ # Money
22
+ # end
23
23
  # end
24
24
  class ObjectSerializer
25
25
  include Singleton
@@ -28,6 +28,11 @@ module ActiveJob
28
28
  delegate :serialize?, :serialize, :deserialize, to: :instance
29
29
  end
30
30
 
31
+ def initialize
32
+ super
33
+ @template = { Serializers::OBJECT_SERIALIZER_KEY => self.class.name }.freeze
34
+ end
35
+
31
36
  # Determines if an argument should be serialized by a serializer.
32
37
  def serialize?(argument)
33
38
  argument.is_a?(klass)
@@ -35,19 +40,13 @@ module ActiveJob
35
40
 
36
41
  # Serializes an argument to a JSON primitive type.
37
42
  def serialize(hash)
38
- { Arguments::OBJECT_SERIALIZER_KEY => self.class.name }.merge!(hash)
43
+ @template.merge(hash)
39
44
  end
40
45
 
41
46
  # Deserializes an argument from a JSON primitive type.
42
- def deserialize(json)
43
- raise NotImplementedError
47
+ def deserialize(hash)
48
+ raise NotImplementedError, "#{self.class.name} should implement a public #deserialize(hash) method"
44
49
  end
45
-
46
- private
47
- # The class of the object that will be serialized.
48
- def klass # :doc:
49
- raise NotImplementedError
50
- end
51
50
  end
52
51
  end
53
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
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "set"
4
-
5
3
  module ActiveJob
6
4
  # = Active Job \Serializers
7
5
  #
@@ -21,16 +19,17 @@ module ActiveJob
21
19
  autoload :ModuleSerializer
22
20
  autoload :RangeSerializer
23
21
  autoload :BigDecimalSerializer
22
+ autoload :ActionControllerParametersSerializer
24
23
 
25
- mattr_accessor :_additional_serializers
26
- self._additional_serializers = Set.new
24
+ @serializers = Set.new
25
+ @serializers_index = {}
27
26
 
28
27
  class << self
29
28
  # Returns serialized representative of the passed object.
30
29
  # Will look up through all known serializers.
31
30
  # Raises ActiveJob::SerializationError if it can't find a proper serializer.
32
31
  def serialize(argument)
33
- serializer = serializers.detect { |s| s.serialize?(argument) }
32
+ serializer = @serializers_index[argument.class] || serializers.find { |s| s.serialize?(argument) }
34
33
  raise SerializationError.new("Unsupported argument type: #{argument.class.name}") unless serializer
35
34
  serializer.serialize(argument)
36
35
  end
@@ -39,7 +38,7 @@ module ActiveJob
39
38
  # Will look up through all known serializers.
40
39
  # If no serializer found will raise <tt>ArgumentError</tt>.
41
40
  def deserialize(argument)
42
- serializer_name = argument[Arguments::OBJECT_SERIALIZER_KEY]
41
+ serializer_name = argument[OBJECT_SERIALIZER_KEY]
43
42
  raise ArgumentError, "Serializer name is not present in the argument: #{argument.inspect}" unless serializer_name
44
43
 
45
44
  serializer = serializer_name.safe_constantize
@@ -49,24 +48,69 @@ module ActiveJob
49
48
  end
50
49
 
51
50
  # Returns list of known serializers.
52
- def serializers
53
- self._additional_serializers
51
+ attr_reader :serializers
52
+
53
+ def serializers=(serializers)
54
+ @serializers_index.clear
55
+ @serializers = Set.new
56
+ add_new_serializers(serializers)
54
57
  end
55
58
 
56
59
  # Adds new serializers to a list of known serializers.
57
60
  def add_serializers(*new_serializers)
58
- self._additional_serializers += new_serializers.flatten
61
+ new_serializers = new_serializers.flatten
62
+ add_new_serializers(new_serializers)
59
63
  end
64
+
65
+ private
66
+ def add_new_serializers(new_serializers)
67
+ new_serializers.map! do |s|
68
+ if s.is_a?(Class) && s < ObjectSerializer
69
+ s.instance
70
+ else
71
+ s
72
+ end
73
+ end
74
+
75
+ @serializers += new_serializers
76
+ index_serializers(new_serializers)
77
+ @serializers
78
+ end
79
+
80
+ def index_serializers(new_serializers)
81
+ new_serializers.each do |s|
82
+ if s.respond_to?(:klass)
83
+ @serializers_index[s.klass] = s
84
+ elsif s.respond_to?(:klass, true)
85
+ klass = s.send(:klass)
86
+ ActiveJob.deprecator.warn(<<~MSG.squish)
87
+ #{s.class.name}#klass method should be public.
88
+ This will raise an error in Rails 8.2.
89
+ MSG
90
+ @serializers_index[klass] = s
91
+ else
92
+ ActiveJob.deprecator.warn(
93
+ <<~MSG.squish
94
+ #{s.class.name} should implement a public #klass method.
95
+ This will raise an error in Rails 8.2.
96
+ MSG
97
+ )
98
+ end
99
+ end
100
+ end
60
101
  end
61
102
 
62
- add_serializers SymbolSerializer,
63
- DurationSerializer,
64
- DateTimeSerializer,
65
- DateSerializer,
66
- TimeWithZoneSerializer,
67
- TimeSerializer,
68
- ModuleSerializer,
69
- RangeSerializer,
70
- BigDecimalSerializer
103
+ # :nodoc:
104
+ OBJECT_SERIALIZER_KEY = "_aj_serialized"
105
+
106
+ add_serializers SymbolSerializer.instance,
107
+ DurationSerializer.instance,
108
+ DateTimeSerializer.instance,
109
+ DateSerializer.instance,
110
+ TimeWithZoneSerializer.instance,
111
+ TimeSerializer.instance,
112
+ ModuleSerializer.instance,
113
+ RangeSerializer.instance,
114
+ BigDecimalSerializer.instance
71
115
  end
72
116
  end