activejob 7.1.0.beta1 → 7.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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: []