zizq 0.5.0 → 0.6.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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -3
  3. data/lib/active_job/queue_adapters/zizq_adapter.rb +42 -20
  4. data/lib/zizq/ack_processor.rb +17 -11
  5. data/lib/zizq/active_job_config.rb +30 -10
  6. data/lib/zizq/backoff.rb +5 -1
  7. data/lib/zizq/bulk_enqueue.rb +7 -1
  8. data/lib/zizq/client.rb +288 -185
  9. data/lib/zizq/configuration.rb +15 -14
  10. data/lib/zizq/crontab.rb +35 -33
  11. data/lib/zizq/crontab_builder.rb +1 -7
  12. data/lib/zizq/crontab_entry.rb +36 -35
  13. data/lib/zizq/crontab_entry_builder.rb +15 -18
  14. data/lib/zizq/enqueue_request.rb +51 -38
  15. data/lib/zizq/enqueue_with.rb +1 -3
  16. data/lib/zizq/error.rb +12 -6
  17. data/lib/zizq/job.rb +31 -13
  18. data/lib/zizq/job_config.rb +217 -13
  19. data/lib/zizq/lifecycle.rb +10 -2
  20. data/lib/zizq/middleware.rb +7 -6
  21. data/lib/zizq/query.rb +85 -67
  22. data/lib/zizq/resources/cron_entry.rb +7 -7
  23. data/lib/zizq/resources/cron_group.rb +5 -5
  24. data/lib/zizq/resources/error_enumerator.rb +11 -9
  25. data/lib/zizq/resources/error_page.rb +2 -1
  26. data/lib/zizq/resources/error_record.rb +5 -5
  27. data/lib/zizq/resources/job.rb +41 -24
  28. data/lib/zizq/resources/job_page.rb +19 -8
  29. data/lib/zizq/resources/job_template.rb +16 -8
  30. data/lib/zizq/resources/page.rb +2 -1
  31. data/lib/zizq/resources/resource.rb +5 -4
  32. data/lib/zizq/resources.rb +9 -9
  33. data/lib/zizq/router.rb +3 -2
  34. data/lib/zizq/test/client.rb +79 -58
  35. data/lib/zizq/test.rb +8 -8
  36. data/lib/zizq/tls_configuration.rb +7 -6
  37. data/lib/zizq/version.rb +1 -1
  38. data/lib/zizq/worker.rb +68 -50
  39. data/lib/zizq/worker_configuration.rb +11 -10
  40. data/lib/zizq.rb +48 -41
  41. data/sig/generated/zizq/active_job_config.rbs +16 -5
  42. data/sig/generated/zizq/bulk_enqueue.rbs +1 -0
  43. data/sig/generated/zizq/client.rbs +2 -1
  44. data/sig/generated/zizq/crontab_entry_builder.rbs +1 -0
  45. data/sig/generated/zizq/enqueue_request.rbs +7 -2
  46. data/sig/generated/zizq/job.rbs +6 -0
  47. data/sig/generated/zizq/job_config.rbs +98 -0
  48. data/sig/generated/zizq/resources/job.rbs +2 -0
  49. data/sig/generated/zizq/resources/job_template.rbs +5 -2
  50. data/sig/generated/zizq.rbs +1 -0
  51. data/sig/zizq.rbs +12 -1
  52. metadata +2 -2
@@ -112,8 +112,8 @@ module Zizq
112
112
  @tls = TlsConfiguration.new(**value)
113
113
  else
114
114
  raise ArgumentError,
115
- "Zizq.configure: tls= expects a Hash, Zizq::TlsConfiguration, or nil " \
116
- "(got #{value.class})"
115
+ "Zizq.configure: tls= expects a Hash, Zizq::TlsConfiguration, or nil " \
116
+ "(got #{value.class})"
117
117
  end
118
118
  end
119
119
 
@@ -143,8 +143,8 @@ module Zizq
143
143
  @worker = WorkerConfiguration.new(**value)
144
144
  else
145
145
  raise ArgumentError,
146
- "Zizq.configure: worker= expects a Hash, Zizq::WorkerConfiguration, or nil " \
147
- "(got #{value.class})"
146
+ "Zizq.configure: worker= expects a Hash, Zizq::WorkerConfiguration, or nil " \
147
+ "(got #{value.class})"
148
148
  end
149
149
  end
150
150
 
@@ -175,15 +175,18 @@ module Zizq
175
175
  raise ArgumentError, "Zizq.configure: url is required" if url.empty?
176
176
 
177
177
  unless %i[msgpack json].include?(format)
178
- raise ArgumentError, "Zizq.configure: format must be :msgpack or :json, got #{format.inspect}"
178
+ raise ArgumentError,
179
+ "Zizq.configure: format must be :msgpack or :json, got #{format.inspect}"
179
180
  end
180
181
 
181
182
  unless read_timeout.is_a?(Numeric) && read_timeout > 0
182
- raise ArgumentError, "Zizq.configure: read_timeout must be a positive number, got #{read_timeout.inspect}"
183
+ raise ArgumentError,
184
+ "Zizq.configure: read_timeout must be a positive number, got #{read_timeout.inspect}"
183
185
  end
184
186
 
185
187
  unless stream_idle_timeout.is_a?(Numeric) && stream_idle_timeout > 0
186
- raise ArgumentError, "Zizq.configure: stream_idle_timeout must be a positive number, got #{stream_idle_timeout.inspect}"
188
+ raise ArgumentError,
189
+ "Zizq.configure: stream_idle_timeout must be a positive number, got #{stream_idle_timeout.inspect}"
187
190
  end
188
191
 
189
192
  tls = @tls
@@ -255,11 +258,13 @@ module Zizq
255
258
 
256
259
  def validate_tls!(tls) #: (TlsConfiguration) -> void
257
260
  if tls.client_cert && !tls.client_key
258
- raise ArgumentError, "Zizq.configure: tls.client_key is required when tls.client_cert is set"
261
+ raise ArgumentError,
262
+ "Zizq.configure: tls.client_key is required when tls.client_cert is set"
259
263
  end
260
264
 
261
265
  if tls.client_key && !tls.client_cert
262
- raise ArgumentError, "Zizq.configure: tls.client_cert is required when tls.client_key is set"
266
+ raise ArgumentError,
267
+ "Zizq.configure: tls.client_cert is required when tls.client_key is set"
263
268
  end
264
269
  end
265
270
 
@@ -276,11 +281,7 @@ module Zizq
276
281
  # If the value looks like PEM data, return it as-is; otherwise treat
277
282
  # it as a file path and read the contents.
278
283
  def resolve_pem(value) #: (String) -> String
279
- if value.include?("-----BEGIN ")
280
- value
281
- else
282
- File.read(value)
283
- end
284
+ value.include?("-----BEGIN ") ? value : File.read(value)
284
285
  end
285
286
  end
286
287
  end
data/lib/zizq/crontab.rb CHANGED
@@ -142,8 +142,8 @@ module Zizq
142
142
  Zizq.client.replace_cron_group(
143
143
  name,
144
144
  paused:,
145
- entries: entries.values.map(&:to_params),
146
- ),
145
+ entries: entries.values.map(&:to_params)
146
+ )
147
147
  )
148
148
 
149
149
  @building = false
@@ -161,9 +161,10 @@ module Zizq
161
161
  def entry(name)
162
162
  materialize
163
163
  entries.fetch(name) do
164
- entry = materialize_entry_with(
165
- Zizq.client.get_cron_group_entry(self.name, name),
166
- )
164
+ entry =
165
+ materialize_entry_with(
166
+ Zizq.client.get_cron_group_entry(self.name, name)
167
+ )
167
168
  entries[name] = entry
168
169
  end
169
170
  end
@@ -196,16 +197,17 @@ module Zizq
196
197
  # @rbs return: Zizq::CrontabEntryBuilder
197
198
  def define_entry(name, expression, timezone: nil, paused: nil)
198
199
  CrontabEntryBuilder.new(self, name, expression, timezone:, paused:) do |e|
199
- entry = materialize_entry_with(
200
- Zizq.client.replace_cron_group_entry(
201
- self.name,
202
- name,
203
- expression: e.expression,
204
- job: e.job.to_enqueue_params,
205
- timezone: e.timezone,
206
- paused: e.paused,
207
- ),
208
- )
200
+ entry =
201
+ materialize_entry_with(
202
+ Zizq.client.replace_cron_group_entry(
203
+ self.name,
204
+ name,
205
+ expression: e.expression,
206
+ job: e.job.to_enqueue_params,
207
+ timezone: e.timezone,
208
+ paused: e.paused
209
+ )
210
+ )
209
211
 
210
212
  materialize # in case this was the first entry operation
211
213
 
@@ -222,12 +224,11 @@ module Zizq
222
224
  @paused_at = result.paused_at
223
225
  @resumed_at = result.resumed_at
224
226
 
225
- @entries = result.entries.map do |entry|
226
- [
227
- entry.name,
228
- materialize_entry_with(entry),
229
- ]
230
- end.to_h
227
+ @entries =
228
+ result
229
+ .entries
230
+ .map { |entry| [entry.name, materialize_entry_with(entry)] }
231
+ .to_h
231
232
 
232
233
  @materialized = true
233
234
 
@@ -241,22 +242,23 @@ module Zizq
241
242
  self,
242
243
  result.name,
243
244
  result.expression,
244
- job: EnqueueRequest.new(
245
- type: result.job.type,
246
- queue: result.job.queue,
247
- priority: result.job.priority,
248
- payload: result.job.payload,
249
- retry_limit: result.job.retry_limit,
250
- backoff: result.job.backoff,
251
- retention: result.job.retention,
252
- unique_key: result.job.unique_key,
253
- unique_while: result.job.unique_while,
254
- ),
245
+ job:
246
+ EnqueueRequest.new(
247
+ type: result.job.type,
248
+ queue: result.job.queue,
249
+ priority: result.job.priority,
250
+ payload: result.job.payload,
251
+ retry_limit: result.job.retry_limit,
252
+ backoff: result.job.backoff,
253
+ retention: result.job.retention,
254
+ unique_key: result.job.unique_key,
255
+ unique_while: result.job.unique_while
256
+ ),
255
257
  paused: result.paused?,
256
258
  paused_at: result.paused_at,
257
259
  resumed_at: result.resumed_at,
258
260
  last_enqueue_at: result.last_enqueue_at,
259
- next_enqueue_at: result.next_enqueue_at,
261
+ next_enqueue_at: result.next_enqueue_at
260
262
  )
261
263
  end
262
264
  end
@@ -40,13 +40,7 @@ module Zizq
40
40
  # @rbs paused: bool?
41
41
  # @rbs return: Zizq::CrontabEntryBuilder
42
42
  def define_entry(name, expression, timezone: self.timezone, paused: nil)
43
- CrontabEntryBuilder.new(
44
- target,
45
- name,
46
- expression,
47
- timezone:,
48
- paused:,
49
- )
43
+ CrontabEntryBuilder.new(target, name, expression, timezone:, paused:)
50
44
  end
51
45
  end
52
46
  end
@@ -62,16 +62,18 @@ module Zizq
62
62
  # @rbs resumed_at: Float?
63
63
  # @rbs last_enqueue_at: Float?
64
64
  # @rbs next_enqueue_at: Float?
65
- def initialize(crontab,
66
- name,
67
- expression,
68
- job:,
69
- timezone: nil,
70
- paused: nil,
71
- paused_at: nil,
72
- resumed_at: nil,
73
- last_enqueue_at: nil,
74
- next_enqueue_at: nil)
65
+ def initialize(
66
+ crontab,
67
+ name,
68
+ expression,
69
+ job:,
70
+ timezone: nil,
71
+ paused: nil,
72
+ paused_at: nil,
73
+ resumed_at: nil,
74
+ last_enqueue_at: nil,
75
+ next_enqueue_at: nil
76
+ )
75
77
  @crontab = crontab
76
78
  @name = name
77
79
  @expression = expression
@@ -93,7 +95,13 @@ module Zizq
93
95
  # @rbs paused: bool?
94
96
  # @rbs return: Zizq::CrontabEntryBuilder
95
97
  def redefine(expression, timezone: nil, paused: nil)
96
- CrontabEntryBuilder.new(crontab, name, expression, timezone:, paused:) do |e|
98
+ CrontabEntryBuilder.new(
99
+ crontab,
100
+ name,
101
+ expression,
102
+ timezone:,
103
+ paused:
104
+ ) do |e|
97
105
  materialize_with(
98
106
  Zizq.client.replace_cron_group_entry(
99
107
  crontab.name,
@@ -101,8 +109,8 @@ module Zizq
101
109
  expression: e.expression,
102
110
  job: e.job.to_enqueue_params,
103
111
  timezone: e.timezone,
104
- paused: e.paused,
105
- ),
112
+ paused: e.paused
113
+ )
106
114
  )
107
115
  end
108
116
  end
@@ -118,11 +126,7 @@ module Zizq
118
126
  # This is independent of the paused state of the Crontab itself.
119
127
  def pause! #: () -> void
120
128
  materialize_with(
121
- Zizq.client.update_cron_group_entry(
122
- crontab.name,
123
- name,
124
- paused: true,
125
- ),
129
+ Zizq.client.update_cron_group_entry(crontab.name, name, paused: true)
126
130
  )
127
131
  end
128
132
 
@@ -132,11 +136,7 @@ module Zizq
132
136
  # jobs until the Crontab is resumed.
133
137
  def resume! #: () -> void
134
138
  materialize_with(
135
- Zizq.client.update_cron_group_entry(
136
- crontab.name,
137
- name,
138
- paused: false,
139
- ),
139
+ Zizq.client.update_cron_group_entry(crontab.name, name, paused: false)
140
140
  )
141
141
  end
142
142
 
@@ -148,7 +148,7 @@ module Zizq
148
148
  expression:,
149
149
  timezone:,
150
150
  job: job.to_enqueue_params,
151
- paused:,
151
+ paused:
152
152
  }.compact #: Zizq::cron_entry_params
153
153
  end
154
154
 
@@ -164,17 +164,18 @@ module Zizq
164
164
  @resumed_at = result.resumed_at
165
165
  @last_enqueue_at = result.last_enqueue_at
166
166
  @next_enqueue_at = result.next_enqueue_at
167
- @job = EnqueueRequest.new(
168
- type: result.job.type,
169
- queue: result.job.queue,
170
- priority: result.job.priority,
171
- payload: result.job.payload,
172
- retry_limit: result.job.retry_limit,
173
- backoff: result.job.backoff,
174
- retention: result.job.retention,
175
- unique_key: result.job.unique_key,
176
- unique_while: result.job.unique_while,
177
- )
167
+ @job =
168
+ EnqueueRequest.new(
169
+ type: result.job.type,
170
+ queue: result.job.queue,
171
+ priority: result.job.priority,
172
+ payload: result.job.payload,
173
+ retry_limit: result.job.retry_limit,
174
+ backoff: result.job.backoff,
175
+ retention: result.job.retention,
176
+ unique_key: result.job.unique_key,
177
+ unique_while: result.job.unique_while
178
+ )
178
179
 
179
180
  self
180
181
  end
@@ -46,12 +46,7 @@ module Zizq
46
46
  # @rbs timezone: String?
47
47
  # @rbs paused: bool?
48
48
  # @rbs ?&block: (Zizq::CrontabEntry) -> Zizq::CrontabEntry
49
- def initialize(target,
50
- name,
51
- expression,
52
- timezone: nil,
53
- paused: nil,
54
- &block)
49
+ def initialize(target, name, expression, timezone: nil, paused: nil, &block)
55
50
  @target = target
56
51
  @name = name
57
52
  @expression = expression
@@ -86,6 +81,7 @@ module Zizq
86
81
  # @rbs retention: Zizq::retention?
87
82
  # @rbs unique_key: String?
88
83
  # @rbs unique_while: Zizq::unique_scope?
84
+ # @rbs batch: Zizq::batch?
89
85
  # @rbs return: void
90
86
  def enqueue_raw(queue:, type:, payload:, **opts)
91
87
  push_entry(EnqueueRequest.new(queue:, type:, payload:, **opts))
@@ -96,7 +92,7 @@ module Zizq
96
92
  # @rbs &block: (BulkEnqueue) -> void
97
93
  # @rbs return: self
98
94
  def enqueue_bulk(&block)
99
- raise NotImplementedError, 'bulk enqueues are not supported via cron'
95
+ raise NotImplementedError, "bulk enqueues are not supported via cron"
100
96
  end
101
97
 
102
98
  # Provide common fields to be used when enqueueing a job.
@@ -113,19 +109,20 @@ module Zizq
113
109
  # @rbs return: untyped
114
110
  def push_entry(req)
115
111
  if req.ready_at || req.delay
116
- raise ArgumentError, 'delayed job are not permitted via cron'
112
+ raise ArgumentError, "delayed job are not permitted via cron"
117
113
  end
118
114
 
119
- entry = callback.call(
120
- CrontabEntry.new(
121
- target,
122
- name,
123
- expression,
124
- job: req,
125
- timezone:,
126
- paused:,
127
- ),
128
- )
115
+ entry =
116
+ callback.call(
117
+ CrontabEntry.new(
118
+ target,
119
+ name,
120
+ expression,
121
+ job: req,
122
+ timezone:,
123
+ paused:
124
+ )
125
+ )
129
126
 
130
127
  target.entries[entry.name] = entry
131
128
  end
@@ -48,6 +48,9 @@ module Zizq
48
48
  # Uniqueness scope.
49
49
  attr_accessor :unique_while #: Zizq::unique_scope?
50
50
 
51
+ # Batch configuration for folded jobs.
52
+ attr_accessor :batch #: Zizq::batch?
53
+
51
54
  # @rbs type: String
52
55
  # @rbs queue: String
53
56
  # @rbs payload: untyped
@@ -59,18 +62,22 @@ module Zizq
59
62
  # @rbs retention: Zizq::retention?
60
63
  # @rbs unique_key: String?
61
64
  # @rbs unique_while: Zizq::unique_scope?
65
+ # @rbs batch: Zizq::batch?
62
66
  # @rbs return: void
63
- def initialize(type:,
64
- queue:,
65
- payload:,
66
- priority: nil,
67
- delay: nil,
68
- ready_at: nil,
69
- retry_limit: nil,
70
- backoff: nil,
71
- retention: nil,
72
- unique_key: nil,
73
- unique_while: nil)
67
+ def initialize(
68
+ type:,
69
+ queue:,
70
+ payload:,
71
+ priority: nil,
72
+ delay: nil,
73
+ ready_at: nil,
74
+ retry_limit: nil,
75
+ backoff: nil,
76
+ retention: nil,
77
+ unique_key: nil,
78
+ unique_while: nil,
79
+ batch: nil
80
+ )
74
81
  update(
75
82
  type:,
76
83
  queue:,
@@ -83,6 +90,7 @@ module Zizq
83
90
  retention:,
84
91
  unique_key:,
85
92
  unique_while:,
93
+ batch:
86
94
  )
87
95
  end
88
96
 
@@ -111,29 +119,34 @@ module Zizq
111
119
  # @rbs retention: Zizq::retention?
112
120
  # @rbs unique_key: String?
113
121
  # @rbs unique_while: Zizq::unique_scope?
122
+ # @rbs batch: Zizq::batch?
114
123
  # @rbs return: self
115
- def update(type: @type,
116
- queue: @queue,
117
- payload: @payload,
118
- priority: @priority,
119
- delay: @delay,
120
- ready_at: @ready_at,
121
- retry_limit: @retry_limit,
122
- backoff: @backoff,
123
- retention: @retention,
124
- unique_key: @unique_key,
125
- unique_while: @unique_while)
126
- @type = type
127
- @queue = queue
128
- @payload = payload
129
- @priority = priority
130
- @delay = delay
131
- @ready_at = ready_at
132
- @retry_limit = retry_limit
133
- @backoff = backoff
134
- @retention = retention
135
- @unique_key = unique_key
124
+ def update(
125
+ type: @type,
126
+ queue: @queue,
127
+ payload: @payload,
128
+ priority: @priority,
129
+ delay: @delay,
130
+ ready_at: @ready_at,
131
+ retry_limit: @retry_limit,
132
+ backoff: @backoff,
133
+ retention: @retention,
134
+ unique_key: @unique_key,
135
+ unique_while: @unique_while,
136
+ batch: @batch
137
+ )
138
+ @type = type
139
+ @queue = queue
140
+ @payload = payload
141
+ @priority = priority
142
+ @delay = delay
143
+ @ready_at = ready_at
144
+ @retry_limit = retry_limit
145
+ @backoff = backoff
146
+ @retention = retention
147
+ @unique_key = unique_key
136
148
  @unique_while = unique_while
149
+ @batch = batch
137
150
  self
138
151
  end
139
152
 
@@ -145,11 +158,7 @@ module Zizq
145
158
  params = { queue:, type:, payload: } #: Hash[Symbol, untyped]
146
159
  params[:priority] = priority if priority
147
160
 
148
- effective_ready_at = if delay
149
- Time.now.to_f + delay.to_f
150
- else
151
- ready_at
152
- end
161
+ effective_ready_at = (delay ? Time.now.to_f + delay.to_f : ready_at)
153
162
  params[:ready_at] = effective_ready_at if effective_ready_at
154
163
 
155
164
  params[:retry_limit] = retry_limit if retry_limit
@@ -164,7 +173,9 @@ module Zizq
164
173
 
165
174
  if retention
166
175
  ret = {} #: Hash[Symbol, Integer]
167
- ret[:completed_ms] = (retention[:completed].to_f * 1000).to_i if retention[:completed]
176
+ ret[:completed_ms] = (
177
+ retention[:completed].to_f * 1000
178
+ ).to_i if retention[:completed]
168
179
  ret[:dead_ms] = (retention[:dead].to_f * 1000).to_i if retention[:dead]
169
180
  params[:retention] = ret
170
181
  end
@@ -172,6 +183,8 @@ module Zizq
172
183
  params[:unique_key] = unique_key if unique_key
173
184
  params[:unique_while] = unique_while.to_s if unique_while
174
185
 
186
+ params[:batch] = batch if batch
187
+
175
188
  params
176
189
  end
177
190
  end
@@ -101,9 +101,7 @@ module Zizq
101
101
  # @rbs &block: (EnqueueWith) -> void
102
102
  # @rbs return: untyped
103
103
  def enqueue_bulk(&block)
104
- @target.enqueue_bulk do |b|
105
- block.call(self.class.new(b, @overrides))
106
- end
104
+ @target.enqueue_bulk { |b| block.call(self.class.new(b, @overrides)) }
107
105
  end
108
106
  end
109
107
  end
data/lib/zizq/error.rb CHANGED
@@ -6,10 +6,12 @@
6
6
 
7
7
  module Zizq
8
8
  # Base error class for all Zizq errors.
9
- class Error < StandardError; end
9
+ class Error < StandardError
10
+ end
10
11
 
11
12
  # Network-level failure (connection refused, DNS, timeout etc).
12
- class ConnectionError < Error; end
13
+ class ConnectionError < Error
14
+ end
13
15
 
14
16
  # HTTP error — the server returned a non-success status code.
15
17
  # Carries the status code and parsed body.
@@ -30,14 +32,18 @@ module Zizq
30
32
  end
31
33
 
32
34
  # 4xx client error.
33
- class ClientError < ResponseError; end
35
+ class ClientError < ResponseError
36
+ end
34
37
 
35
38
  # 404 specifically — job not found, etc.
36
- class NotFoundError < ClientError; end
39
+ class NotFoundError < ClientError
40
+ end
37
41
 
38
42
  # 5xx server error.
39
- class ServerError < ResponseError; end
43
+ class ServerError < ResponseError
44
+ end
40
45
 
41
46
  # Streaming take-jobs connection interrupted.
42
- class StreamError < Error; end
47
+ class StreamError < Error
48
+ end
43
49
  end
data/lib/zizq/job.rb CHANGED
@@ -47,10 +47,9 @@ module Zizq
47
47
  job_class = Object.const_get(job.type)
48
48
 
49
49
  unless (
50
- job_class.is_a?(Class) &&
51
- job_class.include?(Zizq::Job) &&
52
- job_class.is_a?(Zizq::JobConfig)
53
- )
50
+ job_class.is_a?(Class) && job_class.include?(Zizq::Job) &&
51
+ job_class.is_a?(Zizq::JobConfig)
52
+ )
54
53
  raise "#{job.type} does not include Zizq::Job"
55
54
  end
56
55
 
@@ -58,9 +57,10 @@ module Zizq
58
57
  instance = zizq_job_class.new
59
58
  instance.set_zizq_job(job)
60
59
 
61
- args, kwargs = zizq_job_class.zizq_deserialize(
62
- job.payload || { "args" => [], "kwargs" => {} }
63
- )
60
+ args, kwargs =
61
+ zizq_job_class.zizq_deserialize(
62
+ job.payload || { "args" => [], "kwargs" => {} }
63
+ )
64
64
 
65
65
  instance.perform(*args, **kwargs)
66
66
  end
@@ -106,7 +106,7 @@ module Zizq
106
106
  # Any failure to deserialize the arguments will cause the job to fail and
107
107
  # backoff according to the backoff policy.
108
108
  def zizq_deserialize(payload) #: (Hash[String, untyped]) -> [Array[untyped], Hash[Symbol, untyped]]
109
- args = payload.fetch("args")
109
+ args = payload.fetch("args")
110
110
  kwargs = payload.fetch("kwargs").transform_keys(&:to_sym)
111
111
  [args, kwargs]
112
112
  end
@@ -143,6 +143,23 @@ module Zizq
143
143
  "(.kwargs | contains(#{JSON.generate(serialized_kwargs)}))"
144
144
  ].join(" and ")
145
145
  end
146
+
147
+ # Static jq expressions for the batched-job configuration on this
148
+ # class. Targets `.args[N]` for a positional batch arg or
149
+ # `.kwargs.NAME` for a keyword batch arg, matching the payload
150
+ # shape produced by the default `zizq_serialize`.
151
+ def zizq_batch_expressions #: () -> Zizq::batch_expressions?
152
+ return nil unless zizq_batched
153
+
154
+ target =
155
+ if (idx = zizq_batch_arg)
156
+ ".args[#{idx}]"
157
+ else
158
+ ".kwargs.#{zizq_batch_kwarg}"
159
+ end
160
+
161
+ build_batch_expressions(target)
162
+ end
146
163
  end
147
164
 
148
165
  # This is your job's main entrypoint when it is run by the worker.
@@ -154,7 +171,8 @@ module Zizq
154
171
  # easier to evolve over time in a backwards compatible way with any already
155
172
  # enqueued jobs.
156
173
  def perform(*args, **kwargs) #: (*untyped, **untyped) -> void
157
- raise NotImplementedError, "#{self.class.name}#perform must be implemented"
174
+ raise NotImplementedError,
175
+ "#{self.class.name}#perform must be implemented"
158
176
  end
159
177
 
160
178
  # --- Metadata helpers ---
@@ -164,17 +182,17 @@ module Zizq
164
182
  # metadata.
165
183
 
166
184
  # The unique job ID assigned by the server.
167
- def zizq_id = @zizq_job&.id #: () -> String?
185
+ def zizq_id = @zizq_job&.id #: () -> String?
168
186
 
169
187
  # How many times this job has previously been attempted (0 on the first
170
188
  # run, 1 on the second, etc...).
171
- def zizq_attempts = @zizq_job&.attempts #: () -> Integer?
189
+ def zizq_attempts = @zizq_job&.attempts #: () -> Integer?
172
190
 
173
191
  # The queue this job was dequeued from.
174
- def zizq_queue = @zizq_job&.queue #: () -> String?
192
+ def zizq_queue = @zizq_job&.queue #: () -> String?
175
193
 
176
194
  # The priority this job was enqueued with.
177
- def zizq_priority = @zizq_job&.priority #: () -> Integer?
195
+ def zizq_priority = @zizq_job&.priority #: () -> Integer?
178
196
 
179
197
  # Time at which this job was dequeued (fractional seconds since the Unix
180
198
  # epoch). This can be converted to `Time` by using `Time.at(dequeued_at)`