job-iteration 1.17.0 → 1.18.0
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 +6 -0
- data/lib/job-iteration/iteration.rb +37 -4
- data/lib/job-iteration/version.rb +1 -1
- data/lib/tapioca/dsl/compilers/job_iteration.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4eeecd22600aa17ab6d0cee8d7ce0b5df6cd7bc984facb2a2b16025d7432881f
|
|
4
|
+
data.tar.gz: b08981a5c35feba0d9077dffd45147ea16838c87c2fc2c3de2c4798b90c3ce26
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 57e13085c92355e548c35a96aa8506ab084444dbc8c83857dc1b7e234dc91783cb517613be43d90a9a03ee93f668cecc890a6bb4cfac1dcc835431004f565062
|
|
7
|
+
data.tar.gz: 338fef9982f317132a3f46681c015d9790d98a688e773ad34519a1821acf35e44ea6c4fda2f8b2b7b0e863a533d97aecde2426f478d8329a1129a59e2ad9b8eb
|
data/CHANGELOG.md
CHANGED
|
@@ -16,6 +16,12 @@ nil
|
|
|
16
16
|
|
|
17
17
|
nil
|
|
18
18
|
|
|
19
|
+
## v1.18.0 (Nov 6, 2026)
|
|
20
|
+
|
|
21
|
+
### Features
|
|
22
|
+
|
|
23
|
+
- [760](https://github.com/Shopify/job-iteration/pull/760) - Add the `serialize_cursor` and `deserialize_cursor` hooks, which a job overrides to decide how its cursor is stored in the job payload and rebuilt when it resumes; for example through `ActiveJob::Arguments`, so a `Time` or a custom id class survives the trip through JSON. The defaults keep the cursor as it is.
|
|
24
|
+
|
|
19
25
|
## v1.17.0 (Oct 27, 2026)
|
|
20
26
|
|
|
21
27
|
### Features
|
|
@@ -94,7 +94,7 @@ module JobIteration
|
|
|
94
94
|
|
|
95
95
|
def serialize # @private
|
|
96
96
|
super.merge(
|
|
97
|
-
"cursor_position" => cursor_position,
|
|
97
|
+
"cursor_position" => serialize_cursor(cursor_position),
|
|
98
98
|
"times_interrupted" => times_interrupted,
|
|
99
99
|
"total_time" => total_time,
|
|
100
100
|
)
|
|
@@ -102,11 +102,42 @@ module JobIteration
|
|
|
102
102
|
|
|
103
103
|
def deserialize(job_data) # @private
|
|
104
104
|
super
|
|
105
|
-
self.cursor_position = job_data["cursor_position"]
|
|
105
|
+
self.cursor_position = deserialize_cursor(job_data["cursor_position"])
|
|
106
106
|
self.times_interrupted = Integer(job_data["times_interrupted"] || 0)
|
|
107
107
|
self.total_time = Float(job_data["total_time"] || 0.0)
|
|
108
108
|
end
|
|
109
109
|
|
|
110
|
+
# Converts the cursor into the form stored in the job payload when the job is interrupted. The queue
|
|
111
|
+
# backend serializes that payload, typically as JSON, so by default a cursor has to be made of values
|
|
112
|
+
# JSON round-trips as the same objects: Strings, Integers, Floats, Arrays, Hashes, true, false, or nil.
|
|
113
|
+
#
|
|
114
|
+
# Override this method together with #deserialize_cursor to persist cursors of other types. Active Job's
|
|
115
|
+
# argument serialization is a natural choice: it already handles Time, Date, BigDecimal, Symbol and any
|
|
116
|
+
# class with an ActiveJob::Serializers::ObjectSerializer, and leaves JSON-native values untouched.
|
|
117
|
+
#
|
|
118
|
+
# def serialize_cursor(cursor)
|
|
119
|
+
# ActiveJob::Arguments.serialize([cursor]).first
|
|
120
|
+
# end
|
|
121
|
+
#
|
|
122
|
+
# def deserialize_cursor(cursor)
|
|
123
|
+
# ActiveJob::Arguments.deserialize([cursor]).first
|
|
124
|
+
# end
|
|
125
|
+
#
|
|
126
|
+
# @param cursor [Object] the cursor the enumerator yielded last
|
|
127
|
+
# @return [Object] what to store in the job payload
|
|
128
|
+
def serialize_cursor(cursor)
|
|
129
|
+
cursor
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Rebuilds the cursor from the form #serialize_cursor stored in the job payload, before it is passed to
|
|
133
|
+
# #build_enumerator as +cursor:+. The default returns it unchanged.
|
|
134
|
+
#
|
|
135
|
+
# @param cursor [Object] the stored cursor, as the queue backend deserialized it
|
|
136
|
+
# @return [Object] the cursor to resume from
|
|
137
|
+
def deserialize_cursor(cursor)
|
|
138
|
+
cursor
|
|
139
|
+
end
|
|
140
|
+
|
|
110
141
|
def perform(...) # @private
|
|
111
142
|
interruptible_perform(...)
|
|
112
143
|
|
|
@@ -184,7 +215,7 @@ module JobIteration
|
|
|
184
215
|
|
|
185
216
|
enumerator.each do |object_from_enumerator, cursor_from_enumerator|
|
|
186
217
|
# Deferred until 2.0.0
|
|
187
|
-
# assert_valid_cursor!(cursor_from_enumerator)
|
|
218
|
+
# assert_valid_cursor!(serialize_cursor(cursor_from_enumerator))
|
|
188
219
|
|
|
189
220
|
tags = instrumentation_tags.merge(cursor_position: cursor_from_enumerator)
|
|
190
221
|
ActiveSupport::Notifications.instrument("each_iteration.iteration", tags) do
|
|
@@ -312,12 +343,14 @@ module JobIteration
|
|
|
312
343
|
|
|
313
344
|
# The adapter must be able to serialize and deserialize the cursor back into an equivalent object.
|
|
314
345
|
# https://github.com/mperham/sidekiq/wiki/Best-Practices#1-make-your-job-parameters-small-and-simple
|
|
346
|
+
# Validated on the result of #serialize_cursor, which is what reaches the adapter.
|
|
315
347
|
def assert_valid_cursor!(cursor)
|
|
316
348
|
return if serializable?(cursor)
|
|
317
349
|
|
|
318
350
|
raise CursorError.new(
|
|
319
351
|
"Cursor must be composed of objects capable of built-in (de)serialization: " \
|
|
320
|
-
"Strings, Integers, Floats, Arrays, Hashes, true, false, or nil."
|
|
352
|
+
"Strings, Integers, Floats, Arrays, Hashes, true, false, or nil. " \
|
|
353
|
+
"Override #serialize_cursor and #deserialize_cursor to persist other types.",
|
|
321
354
|
cursor: cursor,
|
|
322
355
|
)
|
|
323
356
|
end
|
|
@@ -23,7 +23,7 @@ module Tapioca
|
|
|
23
23
|
|
|
24
24
|
sig { override.void }
|
|
25
25
|
def decorate
|
|
26
|
-
return unless constant.
|
|
26
|
+
return unless constant.method_defined?(:build_enumerator, false)
|
|
27
27
|
|
|
28
28
|
root.create_path(constant) do |job|
|
|
29
29
|
method = constant.instance_method(:build_enumerator)
|