activejob 7.1.0.beta1 → 7.1.0.rc1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c483058510bace1163414149c1aff4177dd5dc026414417a99f240128686ccc6
4
- data.tar.gz: 27f14766eafe75eb955ebae328ef1c154c3bd3aa42251403e6ced8a61f8dc3d1
3
+ metadata.gz: 6afc607e83451a80e5538b8289eb78a3d4256a82648d2fc364c00b35d86652a1
4
+ data.tar.gz: 66372474efc76dc1bcb4e4bc7e32bc6ccfbf62242bd394bfa0b6982a65a48133
5
5
  SHA512:
6
- metadata.gz: eeb8e50e581068b1e9862917d02d99bc8988fc254475e4a70a4a7e231ccb61340dfa276be6d39d0f6ebd4f347a00019d3c3703c946549bb4788dcdd83b46ccc9
7
- data.tar.gz: 23cb3701834db4e4b6ba5adbd77966a50bd0debf8aed7a75d9a83f04355895aad870baca894d6e32183757b9a4a7f62c79748a638f99928be4c497d633302cb5
6
+ metadata.gz: d3ec6a49ca490b307c258df58fa5d6885d7be0ecd3d7db615096a06696ea718e129002198603cd46be21a3c2c7e43146e22e0f3350da69c3a828945a3785cff8
7
+ data.tar.gz: 1d051b0f106d489def667bf37f5801a452269742c25029fd392eb826a02830762730bae3fb556f8a175b79f91b57bb43e49c6d1f69d74ed4d40edea03abe2c1f
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ ## Rails 7.1.0.rc1 (September 27, 2023) ##
2
+
3
+ * Set `scheduled_at` attribute as a Time object instead of epoch seconds, and serialize and deserialize the value
4
+ when enqueued. Assigning a numeric/epoch value to scheduled_at= is deprecated; use a Time object instead.
5
+
6
+ Deserializes `enqueued_at` as a Time instead of ISO8601 String.
7
+
8
+ *Ben Sheldon*
9
+
10
+ * Clarify the backoff strategy for the recommended `:wait` option when retrying jobs
11
+
12
+ `wait: :exponentially_longer` is waiting polynomially longer, so it is now recommended to use `wait: :polynomially_longer` to keep the same behavior.
13
+
14
+ *Victor Mours*
15
+
16
+
1
17
  ## Rails 7.1.0.beta1 (September 13, 2023) ##
2
18
 
3
19
  * Fix Active Job log message to correctly report a job failed to enqueue
@@ -12,8 +12,10 @@ module ActiveJob
12
12
  attr_accessor :arguments
13
13
  attr_writer :serialized_arguments
14
14
 
15
- # Timestamp when the job should be performed
16
- attr_accessor :scheduled_at
15
+ # Time when the job should be performed
16
+ attr_reader :scheduled_at
17
+
18
+ attr_reader :_scheduled_at_time # :nodoc:
17
19
 
18
20
  # Job Identifier
19
21
  attr_accessor :job_id
@@ -94,6 +96,8 @@ module ActiveJob
94
96
  @arguments = arguments
95
97
  @job_id = SecureRandom.uuid
96
98
  @queue_name = self.class.queue_name
99
+ @scheduled_at = nil
100
+ @_scheduled_at_time = nil
97
101
  @priority = self.class.priority
98
102
  @executions = 0
99
103
  @exception_executions = {}
@@ -115,7 +119,8 @@ module ActiveJob
115
119
  "exception_executions" => exception_executions,
116
120
  "locale" => I18n.locale.to_s,
117
121
  "timezone" => timezone,
118
- "enqueued_at" => Time.now.utc.iso8601(9)
122
+ "enqueued_at" => Time.now.utc.iso8601(9),
123
+ "scheduled_at" => _scheduled_at_time ? _scheduled_at_time.utc.iso8601(9) : nil,
119
124
  }
120
125
  end
121
126
 
@@ -155,19 +160,32 @@ module ActiveJob
155
160
  self.exception_executions = job_data["exception_executions"]
156
161
  self.locale = job_data["locale"] || I18n.locale.to_s
157
162
  self.timezone = job_data["timezone"] || Time.zone&.name
158
- self.enqueued_at = job_data["enqueued_at"]
163
+ self.enqueued_at = Time.iso8601(job_data["enqueued_at"]) if job_data["enqueued_at"]
164
+ self.scheduled_at = Time.iso8601(job_data["scheduled_at"]) if job_data["scheduled_at"]
159
165
  end
160
166
 
161
167
  # Configures the job with the given options.
162
168
  def set(options = {}) # :nodoc:
163
- self.scheduled_at = options[:wait].seconds.from_now.to_f if options[:wait]
164
- self.scheduled_at = options[:wait_until].to_f if options[:wait_until]
169
+ self.scheduled_at = options[:wait].seconds.from_now if options[:wait]
170
+ self.scheduled_at = options[:wait_until] if options[:wait_until]
165
171
  self.queue_name = self.class.queue_name_from_part(options[:queue]) if options[:queue]
166
172
  self.priority = options[:priority].to_i if options[:priority]
167
173
 
168
174
  self
169
175
  end
170
176
 
177
+ def scheduled_at=(value)
178
+ @_scheduled_at_time = if value&.is_a?(Numeric)
179
+ ActiveJob.deprecator.warn(<<~MSG.squish)
180
+ Assigning a numeric/epoch value to scheduled_at is deprecated. Use a Time object instead.
181
+ MSG
182
+ Time.at(value)
183
+ else
184
+ value
185
+ end
186
+ @scheduled_at = value
187
+ end
188
+
171
189
  private
172
190
  def serialize_arguments_if_needed(arguments)
173
191
  if arguments_serialized?
@@ -23,7 +23,7 @@ module ActiveJob
23
23
  adapter_jobs.each do |job|
24
24
  job.successfully_enqueued = false
25
25
  if job.scheduled_at
26
- queue_adapter.enqueue_at(job, job.scheduled_at)
26
+ queue_adapter.enqueue_at(job, job._scheduled_at_time.to_f)
27
27
  else
28
28
  queue_adapter.enqueue(job)
29
29
  end
@@ -92,7 +92,7 @@ module ActiveJob
92
92
 
93
93
  run_callbacks :enqueue do
94
94
  if scheduled_at
95
- queue_adapter.enqueue_at self, scheduled_at
95
+ queue_adapter.enqueue_at self, _scheduled_at_time.to_f
96
96
  else
97
97
  queue_adapter.enqueue self
98
98
  end
@@ -24,7 +24,7 @@ module ActiveJob
24
24
  # ==== Options
25
25
  # * <tt>:wait</tt> - Re-enqueues the job with a delay specified either in seconds (default: 3 seconds),
26
26
  # as a computing proc that takes the number of executions so far as an argument, or as a symbol reference of
27
- # <tt>:exponentially_longer</tt>, which applies the wait algorithm of <tt>((executions**4) + (Kernel.rand * (executions**4) * jitter)) + 2</tt>
27
+ # <tt>:polynomially_longer</tt>, which applies the wait algorithm of <tt>((executions**4) + (Kernel.rand * (executions**4) * jitter)) + 2</tt>
28
28
  # (first wait ~3s, then ~18s, then ~83s, etc)
29
29
  # * <tt>:attempts</tt> - Re-enqueues the job the specified number of times (default: 5 attempts) or a symbol reference of <tt>:unlimited</tt>
30
30
  # to retry the job until it succeeds
@@ -40,11 +40,11 @@ module ActiveJob
40
40
  # retry_on CustomInfrastructureException, wait: 5.minutes, attempts: :unlimited
41
41
  #
42
42
  # retry_on ActiveRecord::Deadlocked, wait: 5.seconds, attempts: 3
43
- # retry_on Net::OpenTimeout, Timeout::Error, wait: :exponentially_longer, attempts: 10 # retries at most 10 times for Net::OpenTimeout and Timeout::Error combined
43
+ # retry_on Net::OpenTimeout, Timeout::Error, wait: :polynomially_longer, attempts: 10 # retries at most 10 times for Net::OpenTimeout and Timeout::Error combined
44
44
  # # To retry at most 10 times for each individual exception:
45
- # # retry_on Net::OpenTimeout, wait: :exponentially_longer, attempts: 10
45
+ # # retry_on Net::OpenTimeout, wait: :polynomially_longer, attempts: 10
46
46
  # # retry_on Net::ReadTimeout, wait: 5.seconds, jitter: 0.30, attempts: 10
47
- # # retry_on Timeout::Error, wait: :exponentially_longer, attempts: 10
47
+ # # retry_on Timeout::Error, wait: :polynomially_longer, attempts: 10
48
48
  #
49
49
  # retry_on(YetAnotherCustomAppException) do |job, error|
50
50
  # ExceptionNotifier.caught(error)
@@ -57,6 +57,12 @@ module ActiveJob
57
57
  # end
58
58
  # end
59
59
  def retry_on(*exceptions, wait: 3.seconds, attempts: 5, queue: nil, priority: nil, jitter: JITTER_DEFAULT)
60
+ if wait == :exponentially_longer
61
+ ActiveJob.deprecator.warn(<<~MSG.squish)
62
+ `wait: :exponentially_longer` will actually wait polynomially longer and is therefore deprecated.
63
+ Prefer `wait: :polynomially_longer` to avoid confusion and keep the same behavior.
64
+ MSG
65
+ end
60
66
  rescue_from(*exceptions) do |error|
61
67
  executions = executions_for(exceptions)
62
68
  if attempts == :unlimited || executions < attempts
@@ -156,7 +162,8 @@ module ActiveJob
156
162
  jitter = jitter == JITTER_DEFAULT ? self.class.retry_jitter : (jitter || 0.0)
157
163
 
158
164
  case seconds_or_duration_or_algorithm
159
- when :exponentially_longer
165
+ when :exponentially_longer, :polynomially_longer
166
+ # This delay uses a polynomial backoff strategy, which was previously misnamed as exponential
160
167
  delay = executions**4
161
168
  delay_jitter = determine_jitter_for_delay(delay, jitter)
162
169
  delay + delay_jitter + 2
@@ -10,7 +10,7 @@ module ActiveJob
10
10
  MAJOR = 7
11
11
  MINOR = 1
12
12
  TINY = 0
13
- PRE = "beta1"
13
+ PRE = "rc1"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -76,7 +76,7 @@ module ActiveJob
76
76
  def perform_start(event)
77
77
  info do
78
78
  job = event.payload[:job]
79
- "Performing #{job.class.name} (Job ID: #{job.job_id}) from #{queue_name(event)} enqueued at #{job.enqueued_at}" + args_info(job)
79
+ "Performing #{job.class.name} (Job ID: #{job.job_id}) from #{queue_name(event)} enqueued at #{job.enqueued_at.utc.iso8601(9)}" + args_info(job)
80
80
  end
81
81
  end
82
82
  subscribe_log_level :perform_start, :info
@@ -54,7 +54,7 @@ module ActiveJob
54
54
  "wrapped" => job_class,
55
55
  "queue" => queue,
56
56
  "args" => scheduled_jobs.map { |job| [job.serialize] },
57
- "at" => scheduled_jobs.map { |job| job.scheduled_at }
57
+ "at" => scheduled_jobs.map { |job| job.scheduled_at&.to_f }
58
58
  )
59
59
  enqueued_count += jids.compact.size
60
60
  end
@@ -59,7 +59,7 @@ module ActiveJob
59
59
  end
60
60
 
61
61
  def filtered_time?(job)
62
- job.scheduled_at > at.to_f if at && job.scheduled_at
62
+ job.scheduled_at > at if at && job.scheduled_at
63
63
  end
64
64
 
65
65
  def filtered_queue?(job)
@@ -730,7 +730,7 @@ module ActiveJob
730
730
 
731
731
  def instantiate_job(payload, skip_deserialize_arguments: false)
732
732
  job = payload[:job].deserialize(payload)
733
- job.scheduled_at = payload[:at].to_f if payload.key?(:at)
733
+ job.scheduled_at = payload[:at] if payload.key?(:at)
734
734
  job.send(:deserialize_arguments_if_needed) unless skip_deserialize_arguments
735
735
  job
736
736
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activejob
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.1.0.beta1
4
+ version: 7.1.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-13 00:00:00.000000000 Z
11
+ date: 2023-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 7.1.0.beta1
19
+ version: 7.1.0.rc1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 7.1.0.beta1
26
+ version: 7.1.0.rc1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: globalid
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -102,10 +102,10 @@ licenses:
102
102
  - MIT
103
103
  metadata:
104
104
  bug_tracker_uri: https://github.com/rails/rails/issues
105
- changelog_uri: https://github.com/rails/rails/blob/v7.1.0.beta1/activejob/CHANGELOG.md
106
- documentation_uri: https://api.rubyonrails.org/v7.1.0.beta1/
105
+ changelog_uri: https://github.com/rails/rails/blob/v7.1.0.rc1/activejob/CHANGELOG.md
106
+ documentation_uri: https://api.rubyonrails.org/v7.1.0.rc1/
107
107
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
108
- source_code_uri: https://github.com/rails/rails/tree/v7.1.0.beta1/activejob
108
+ source_code_uri: https://github.com/rails/rails/tree/v7.1.0.rc1/activejob
109
109
  rubygems_mfa_required: 'true'
110
110
  post_install_message:
111
111
  rdoc_options: []