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 +4 -4
- data/CHANGELOG.md +16 -0
- data/lib/active_job/core.rb +24 -6
- data/lib/active_job/enqueuing.rb +2 -2
- data/lib/active_job/exceptions.rb +12 -5
- data/lib/active_job/gem_version.rb +1 -1
- data/lib/active_job/log_subscriber.rb +1 -1
- data/lib/active_job/queue_adapters/sidekiq_adapter.rb +1 -1
- data/lib/active_job/queue_adapters/test_adapter.rb +1 -1
- data/lib/active_job/test_helper.rb +1 -1
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6afc607e83451a80e5538b8289eb78a3d4256a82648d2fc364c00b35d86652a1
|
4
|
+
data.tar.gz: 66372474efc76dc1bcb4e4bc7e32bc6ccfbf62242bd394bfa0b6982a65a48133
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/lib/active_job/core.rb
CHANGED
@@ -12,8 +12,10 @@ module ActiveJob
|
|
12
12
|
attr_accessor :arguments
|
13
13
|
attr_writer :serialized_arguments
|
14
14
|
|
15
|
-
#
|
16
|
-
|
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
|
164
|
-
self.scheduled_at = 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?
|
data/lib/active_job/enqueuing.rb
CHANGED
@@ -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.
|
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,
|
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>:
|
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: :
|
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: :
|
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: :
|
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
|
@@ -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
|
@@ -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]
|
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.
|
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-
|
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.
|
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.
|
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.
|
106
|
-
documentation_uri: https://api.rubyonrails.org/v7.1.0.
|
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.
|
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: []
|