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
data/lib/zizq/client.rb CHANGED
@@ -62,24 +62,23 @@ module Zizq
62
62
  # @rbs read_timeout: Numeric
63
63
  # @rbs stream_idle_timeout: Numeric
64
64
  # @rbs return: void
65
- def initialize(url:,
66
- format: :msgpack,
67
- ssl_context: nil,
68
- read_timeout: 30,
69
- stream_idle_timeout: 30)
65
+ def initialize(
66
+ url:,
67
+ format: :msgpack,
68
+ ssl_context: nil,
69
+ read_timeout: 30,
70
+ stream_idle_timeout: 30
71
+ )
70
72
  @url = url.chomp("/")
71
73
  @format = format
72
74
 
73
75
  endpoint_options = {
74
76
  protocol: Async::HTTP::Protocol::HTTP2,
75
- timeout: read_timeout,
77
+ timeout: read_timeout
76
78
  } #: Hash[Symbol, untyped]
77
79
  endpoint_options[:ssl_context] = ssl_context if ssl_context
78
80
 
79
- @endpoint = Async::HTTP::Endpoint.parse(
80
- @url,
81
- **endpoint_options,
82
- )
81
+ @endpoint = Async::HTTP::Endpoint.parse(@url, **endpoint_options)
83
82
 
84
83
  # Streaming take uses a dedicated HTTP/1.1 endpoint. The take
85
84
  # connection is long-lived and carries only one request, so HTTP/2's
@@ -93,14 +92,13 @@ module Zizq
93
92
  # timeout so server heartbeats (~3s) keep it alive while only
94
93
  # genuinely dead connections (no data for the full window)
95
94
  # trigger a reconnect.
96
- stream_endpoint_options = endpoint_options.merge(
97
- protocol: Async::HTTP::Protocol::HTTP11,
98
- timeout: stream_idle_timeout,
99
- )
100
- @stream_endpoint = Async::HTTP::Endpoint.parse(
101
- @url,
102
- **stream_endpoint_options,
103
- )
95
+ stream_endpoint_options =
96
+ endpoint_options.merge(
97
+ protocol: Async::HTTP::Protocol::HTTP11,
98
+ timeout: stream_idle_timeout
99
+ )
100
+ @stream_endpoint =
101
+ Async::HTTP::Endpoint.parse(@url, **stream_endpoint_options)
104
102
 
105
103
  @mutex = Mutex.new
106
104
 
@@ -166,17 +164,21 @@ module Zizq
166
164
  # @rbs retention: Zizq::retention?
167
165
  # @rbs unique_key: String?
168
166
  # @rbs unique_while: Zizq::unique_scope?
167
+ # @rbs batch: Zizq::batch?
169
168
  # @rbs return: Resources::Job
170
- def enqueue(queue:,
171
- type:,
172
- payload:,
173
- priority: nil,
174
- ready_at: nil,
175
- retry_limit: nil,
176
- backoff: nil,
177
- retention: nil,
178
- unique_key: nil,
179
- unique_while: nil)
169
+ def enqueue(
170
+ queue:,
171
+ type:,
172
+ payload:,
173
+ priority: nil,
174
+ ready_at: nil,
175
+ retry_limit: nil,
176
+ backoff: nil,
177
+ retention: nil,
178
+ unique_key: nil,
179
+ unique_while: nil,
180
+ batch: nil
181
+ )
180
182
  body = { queue:, type:, payload: } #: Hash[Symbol, untyped]
181
183
  body[:priority] = priority if priority
182
184
  # ready_at is fractional seconds in Ruby; the server expects ms.
@@ -186,6 +188,7 @@ module Zizq
186
188
  body[:retention] = retention if retention
187
189
  body[:unique_key] = unique_key if unique_key
188
190
  body[:unique_while] = unique_while.to_s if unique_while
191
+ body[:batch] = batch if batch
189
192
 
190
193
  response = post("/jobs", body)
191
194
  data = handle_response!(response, expected: [200, 201])
@@ -204,18 +207,26 @@ module Zizq
204
207
  # @rbs return: Array[Resources::Job]
205
208
  def enqueue_bulk(jobs:)
206
209
  body = {
207
- jobs: jobs.map do |job|
208
- wire = { type: job[:type], queue: job[:queue], payload: job[:payload] } #: Hash[Symbol, untyped]
209
- wire[:priority] = job[:priority] if job[:priority]
210
- # ready_at is fractional seconds in Ruby; the server expects ms.
211
- wire[:ready_at] = (job[:ready_at].to_f * 1000).to_i if job[:ready_at]
212
- wire[:retry_limit] = job[:retry_limit] if job[:retry_limit]
213
- wire[:backoff] = job[:backoff] if job[:backoff]
214
- wire[:retention] = job[:retention] if job[:retention]
215
- wire[:unique_key] = job[:unique_key] if job[:unique_key]
216
- wire[:unique_while] = job[:unique_while].to_s if job[:unique_while]
217
- wire
218
- end
210
+ jobs:
211
+ jobs.map do |job|
212
+ wire = {
213
+ type: job[:type],
214
+ queue: job[:queue],
215
+ payload: job[:payload]
216
+ } #: Hash[Symbol, untyped]
217
+ wire[:priority] = job[:priority] if job[:priority]
218
+ # ready_at is fractional seconds in Ruby; the server expects ms.
219
+ wire[:ready_at] = (job[:ready_at].to_f * 1000).to_i if job[
220
+ :ready_at
221
+ ]
222
+ wire[:retry_limit] = job[:retry_limit] if job[:retry_limit]
223
+ wire[:backoff] = job[:backoff] if job[:backoff]
224
+ wire[:retention] = job[:retention] if job[:retention]
225
+ wire[:unique_key] = job[:unique_key] if job[:unique_key]
226
+ wire[:unique_while] = job[:unique_while].to_s if job[:unique_while]
227
+ wire[:batch] = job[:batch] if job[:batch]
228
+ wire
229
+ end
219
230
  }
220
231
 
221
232
  response = post("/jobs/bulk", body)
@@ -253,17 +264,19 @@ module Zizq
253
264
  # @rbs order: Zizq::sort_direction?
254
265
  # @rbs limit: Integer?
255
266
  # @rbs return: Resources::JobPage
256
- def list_jobs(id: nil,
257
- status: nil,
258
- queue: nil,
259
- type: nil,
260
- filter: nil,
261
- priority: nil,
262
- ready_at: nil,
263
- attempts: nil,
264
- from: nil,
265
- order: nil,
266
- limit: nil)
267
+ def list_jobs(
268
+ id: nil,
269
+ status: nil,
270
+ queue: nil,
271
+ type: nil,
272
+ filter: nil,
273
+ priority: nil,
274
+ ready_at: nil,
275
+ attempts: nil,
276
+ from: nil,
277
+ order: nil,
278
+ limit: nil
279
+ )
267
280
  options = {
268
281
  id:,
269
282
  status:,
@@ -275,7 +288,7 @@ module Zizq
275
288
  attempts: encode_range(attempts),
276
289
  from:,
277
290
  order:,
278
- limit:,
291
+ limit:
279
292
  }.compact #: Hash[Symbol, untyped]
280
293
 
281
294
  multi_keys = %i[id status queue type]
@@ -283,7 +296,9 @@ module Zizq
283
296
 
284
297
  # An empty filter ([] or "") matches nothing — short-circuit.
285
298
  multi_keys.each do |key|
286
- return Resources::JobPage.new(self, { "jobs" => [], "pages" => {} }) if params[key] == ""
299
+ if params[key] == ""
300
+ return Resources::JobPage.new(self, { "jobs" => [], "pages" => {} })
301
+ end
287
302
  end
288
303
 
289
304
  response = get("/jobs", params:)
@@ -305,14 +320,16 @@ module Zizq
305
320
  # @rbs ready_at: (Zizq::to_f | Range[Zizq::to_f?])?
306
321
  # @rbs attempts: (Integer | Range[Integer?])?
307
322
  # @rbs return: Integer
308
- def count_jobs(id: nil,
309
- status: nil,
310
- queue: nil,
311
- type: nil,
312
- filter: nil,
313
- priority: nil,
314
- ready_at: nil,
315
- attempts: nil)
323
+ def count_jobs(
324
+ id: nil,
325
+ status: nil,
326
+ queue: nil,
327
+ type: nil,
328
+ filter: nil,
329
+ priority: nil,
330
+ ready_at: nil,
331
+ attempts: nil
332
+ )
316
333
  options = {
317
334
  id:,
318
335
  status:,
@@ -321,16 +338,14 @@ module Zizq
321
338
  filter:,
322
339
  priority: encode_range(priority),
323
340
  ready_at: encode_range(ready_at) { |v| (v.to_f * 1000).to_i },
324
- attempts: encode_range(attempts),
341
+ attempts: encode_range(attempts)
325
342
  }.compact #: Hash[Symbol, untyped]
326
343
 
327
344
  multi_keys = %i[id status queue type]
328
345
  params = build_where_params(options, multi_keys:)
329
346
 
330
347
  # An empty filter ([] or "") matches nothing — short-circuit.
331
- multi_keys.each do |key|
332
- return 0 if params[key] == ""
333
- end
348
+ multi_keys.each { |key| return 0 if params[key] == "" }
334
349
 
335
350
  response = get("/jobs/count", params:)
336
351
  data = handle_response!(response, expected: 200)
@@ -363,9 +378,7 @@ module Zizq
363
378
  params = build_where_params(filter_params, multi_keys:)
364
379
 
365
380
  # An empty multi-value filter matches nothing — short-circuit.
366
- multi_keys.each do |key|
367
- return 0 if params[key] == ""
368
- end
381
+ multi_keys.each { |key| return 0 if params[key] == "" }
369
382
 
370
383
  response = delete("/jobs", params:)
371
384
  data = handle_response!(response, expected: 200)
@@ -408,21 +421,24 @@ module Zizq
408
421
  # @rbs backoff: (Zizq::backoff | singleton(Zizq::RESET) | singleton(Zizq::UNCHANGED))?
409
422
  # @rbs retention: (Zizq::retention | singleton(Zizq::RESET) | singleton(Zizq::UNCHANGED))?
410
423
  # @rbs return: Resources::Job
411
- def update_job(id,
412
- queue: UNCHANGED,
413
- priority: UNCHANGED,
414
- ready_at: UNCHANGED,
415
- retry_limit: UNCHANGED,
416
- backoff: UNCHANGED,
417
- retention: UNCHANGED)
418
- body = build_set_body(
419
- queue:,
420
- priority:,
421
- ready_at:,
422
- retry_limit:,
423
- backoff:,
424
- retention:
425
- )
424
+ def update_job(
425
+ id,
426
+ queue: UNCHANGED,
427
+ priority: UNCHANGED,
428
+ ready_at: UNCHANGED,
429
+ retry_limit: UNCHANGED,
430
+ backoff: UNCHANGED,
431
+ retention: UNCHANGED
432
+ )
433
+ body =
434
+ build_set_body(
435
+ queue:,
436
+ priority:,
437
+ ready_at:,
438
+ retry_limit:,
439
+ backoff:,
440
+ retention:
441
+ )
426
442
  response = patch("/jobs/#{enc(id)}", body)
427
443
  data = handle_response!(response, expected: 200)
428
444
  Resources::Job.new(self, data)
@@ -448,9 +464,7 @@ module Zizq
448
464
  params = build_where_params(filter_params, multi_keys:)
449
465
 
450
466
  # An empty multi-value filter matches nothing — short-circuit.
451
- multi_keys.each do |key|
452
- return 0 if params[key] == ""
453
- end
467
+ multi_keys.each { |key| return 0 if params[key] == "" }
454
468
 
455
469
  body = validate_and_build_set(**apply)
456
470
  response = patch("/jobs", body, params:)
@@ -602,7 +616,14 @@ module Zizq
602
616
  # @rbs timezone: String?
603
617
  # @rbs paused: bool?
604
618
  # @rbs return: Resources::CronEntry
605
- def add_cron_group_entry(group, name:, expression:, job:, timezone: nil, paused: nil)
619
+ def add_cron_group_entry(
620
+ group,
621
+ name:,
622
+ expression:,
623
+ job:,
624
+ timezone: nil,
625
+ paused: nil
626
+ )
606
627
  body = build_cron_entry(name:, expression:, job:, timezone:, paused:)
607
628
  response = post("/crons/#{enc(group)}/entries", body)
608
629
  data = handle_response!(response, expected: 201)
@@ -620,8 +641,16 @@ module Zizq
620
641
  # @rbs timezone: String?
621
642
  # @rbs paused: bool?
622
643
  # @rbs return: Resources::CronEntry
623
- def replace_cron_group_entry(group, entry, expression:, job:, timezone: nil, paused: nil)
624
- body = build_cron_entry(name: entry, expression:, job:, timezone:, paused:)
644
+ def replace_cron_group_entry(
645
+ group,
646
+ entry,
647
+ expression:,
648
+ job:,
649
+ timezone: nil,
650
+ paused: nil
651
+ )
652
+ body =
653
+ build_cron_entry(name: entry, expression:, job:, timezone:, paused:)
625
654
  response = put("/crons/#{enc(group)}/entries/#{enc(entry)}", body)
626
655
  data = handle_response!(response, expected: 200)
627
656
  Resources::CronEntry.new(self, data)
@@ -634,7 +663,8 @@ module Zizq
634
663
  # @rbs paused: bool
635
664
  # @rbs return: Resources::CronEntry
636
665
  def update_cron_group_entry(group, entry, paused:)
637
- response = patch("/crons/#{enc(group)}/entries/#{enc(entry)}", { paused: })
666
+ response =
667
+ patch("/crons/#{enc(group)}/entries/#{enc(entry)}", { paused: })
638
668
  data = handle_response!(response, expected: 200)
639
669
  Resources::CronEntry.new(self, data)
640
670
  end
@@ -723,7 +753,14 @@ module Zizq
723
753
  # @rbs retry_at: Float?
724
754
  # @rbs kill: bool
725
755
  # @rbs return: Resources::Job
726
- def report_failure(id, message:, error_type: nil, backtrace: nil, retry_at: nil, kill: false)
756
+ def report_failure(
757
+ id,
758
+ message:,
759
+ error_type: nil,
760
+ backtrace: nil,
761
+ retry_at: nil,
762
+ kill: false
763
+ )
727
764
  body = { message: } #: Hash[Symbol, untyped]
728
765
  body[:error_type] = error_type if error_type
729
766
  body[:backtrace] = backtrace if backtrace
@@ -772,7 +809,14 @@ module Zizq
772
809
  # @rbs worker_id: String?
773
810
  # @rbs &block: (Resources::Job) -> void
774
811
  # @rbs return: void
775
- def take_jobs(prefetch: 1, queues: [], worker_id: nil, on_connect: nil, on_response: nil, &block)
812
+ def take_jobs(
813
+ prefetch: 1,
814
+ queues: [],
815
+ worker_id: nil,
816
+ on_connect: nil,
817
+ on_response: nil,
818
+ &block
819
+ )
776
820
  raise ArgumentError, "take_jobs requires a block" unless block
777
821
 
778
822
  params = { prefetch: } #: Hash[Symbol, untyped]
@@ -786,7 +830,10 @@ module Zizq
786
830
  response = stream_http.get(path, headers)
787
831
 
788
832
  begin
789
- raise StreamError, "take jobs stream returned HTTP #{response.status}" unless response.status == 200
833
+ unless response.status == 200
834
+ raise StreamError,
835
+ "take jobs stream returned HTTP #{response.status}"
836
+ end
790
837
  on_connect&.call
791
838
  on_response&.call(response)
792
839
 
@@ -800,11 +847,17 @@ module Zizq
800
847
  body = response.body || []
801
848
 
802
849
  case @format
803
- when :json then self.class.parse_ndjson(body, &wrapper)
804
- when :msgpack then self.class.parse_msgpack_stream(body, &wrapper)
850
+ when :json
851
+ self.class.parse_ndjson(body, &wrapper)
852
+ when :msgpack
853
+ self.class.parse_msgpack_stream(body, &wrapper)
805
854
  end
806
855
  ensure
807
- response.close rescue nil
856
+ begin
857
+ response.close
858
+ rescue StandardError
859
+ nil
860
+ end
808
861
  end
809
862
  end
810
863
  rescue SocketError,
@@ -887,7 +940,10 @@ module Zizq
887
940
  # so that resource objects like Page can follow links without resorting
888
941
  # to `.send`.
889
942
  def get_path(path) #: (String) -> Hash[String, untyped]
890
- response = request { |http| consume_response(http.get(path, {"accept" => @content_type})) }
943
+ response =
944
+ request do |http|
945
+ consume_response(http.get(path, { "accept" => @content_type }))
946
+ end
891
947
  handle_response!(response, expected: 200)
892
948
  end
893
949
 
@@ -900,9 +956,7 @@ module Zizq
900
956
 
901
957
  # Build a relative path with optional query parameters.
902
958
  def build_path(path, params: {}) #: (String, ?params: Hash[Symbol, untyped]) -> String
903
- unless params.empty?
904
- path = "#{path}?#{URI.encode_www_form(params)}"
905
- end
959
+ path = "#{path}?#{URI.encode_www_form(params)}" unless params.empty?
906
960
  path
907
961
  end
908
962
 
@@ -914,13 +968,19 @@ module Zizq
914
968
  # @rbs timezone: String?
915
969
  # @rbs paused: bool?
916
970
  # @rbs return: Hash[Symbol, untyped]
917
- def build_cron_entry(name: nil, expression: nil, job: nil, timezone: nil, paused: nil)
971
+ def build_cron_entry(
972
+ name: nil,
973
+ expression: nil,
974
+ job: nil,
975
+ timezone: nil,
976
+ paused: nil
977
+ )
918
978
  {
919
979
  name:,
920
980
  expression:,
921
981
  timezone:,
922
982
  paused:,
923
- job: build_cron_job(**job),
983
+ job: build_cron_job(**job)
924
984
  }.compact
925
985
  end
926
986
 
@@ -938,15 +998,17 @@ module Zizq
938
998
  # @rbs unique_key: String?
939
999
  # @rbs unique_while: Zizq::unique_scope?
940
1000
  # @rbs return: Hash[Symbol, untyped]
941
- def build_cron_job(type: nil,
942
- queue: nil,
943
- payload: nil,
944
- priority: nil,
945
- retry_limit: nil,
946
- backoff: nil,
947
- retention: nil,
948
- unique_key: nil,
949
- unique_while: nil)
1001
+ def build_cron_job(
1002
+ type: nil,
1003
+ queue: nil,
1004
+ payload: nil,
1005
+ priority: nil,
1006
+ retry_limit: nil,
1007
+ backoff: nil,
1008
+ retention: nil,
1009
+ unique_key: nil,
1010
+ unique_while: nil
1011
+ )
950
1012
  job = { type:, queue:, payload: } #: Hash[Symbol, untyped]
951
1013
  job[:priority] = priority if priority
952
1014
  job[:retry_limit] = retry_limit if retry_limit
@@ -970,14 +1032,16 @@ module Zizq
970
1032
  # @rbs ready_at: (Zizq::to_f | Range[Zizq::to_f?])?
971
1033
  # @rbs attempts: (Integer | Range[Integer?])?
972
1034
  # @rbs return: Hash[Symbol, untyped]
973
- def validate_where(id: nil,
974
- status: nil,
975
- queue: nil,
976
- type: nil,
977
- filter: nil,
978
- priority: nil,
979
- ready_at: nil,
980
- attempts: nil)
1035
+ def validate_where(
1036
+ id: nil,
1037
+ status: nil,
1038
+ queue: nil,
1039
+ type: nil,
1040
+ filter: nil,
1041
+ priority: nil,
1042
+ ready_at: nil,
1043
+ attempts: nil
1044
+ )
981
1045
  {
982
1046
  id:,
983
1047
  status:,
@@ -986,7 +1050,7 @@ module Zizq
986
1050
  filter:,
987
1051
  priority: encode_range(priority),
988
1052
  ready_at: encode_range(ready_at) { |v| (v.to_f * 1000).to_i },
989
- attempts: encode_range(attempts),
1053
+ attempts: encode_range(attempts)
990
1054
  }.compact
991
1055
  end
992
1056
 
@@ -1016,7 +1080,7 @@ module Zizq
1016
1080
  when Range
1017
1081
  if value.exclude_end?
1018
1082
  raise ArgumentError,
1019
- "exclusive ranges are not supported by the server; use an inclusive range (a..b) instead"
1083
+ "exclusive ranges are not supported by the server; use an inclusive range (a..b) instead"
1020
1084
  end
1021
1085
  "#{value.begin&.then(&block)}..#{value.end&.then(&block)}"
1022
1086
  else
@@ -1034,13 +1098,22 @@ module Zizq
1034
1098
  # @rbs backoff: (Zizq::backoff | singleton(Zizq::RESET) | singleton(Zizq::UNCHANGED))?
1035
1099
  # @rbs retention: (Zizq::retention | singleton(Zizq::RESET) | singleton(Zizq::UNCHANGED))?
1036
1100
  # @rbs return: Hash[Symbol, untyped]
1037
- def validate_and_build_set(queue: UNCHANGED,
1038
- priority: UNCHANGED,
1039
- ready_at: UNCHANGED,
1040
- retry_limit: UNCHANGED,
1041
- backoff: UNCHANGED,
1042
- retention: UNCHANGED)
1043
- build_set_body(queue:, priority:, ready_at:, retry_limit:, backoff:, retention:)
1101
+ def validate_and_build_set(
1102
+ queue: UNCHANGED,
1103
+ priority: UNCHANGED,
1104
+ ready_at: UNCHANGED,
1105
+ retry_limit: UNCHANGED,
1106
+ backoff: UNCHANGED,
1107
+ retention: UNCHANGED
1108
+ )
1109
+ build_set_body(
1110
+ queue:,
1111
+ priority:,
1112
+ ready_at:,
1113
+ retry_limit:,
1114
+ backoff:,
1115
+ retention:
1116
+ )
1044
1117
  end
1045
1118
 
1046
1119
  # Build the JSON body hash for a PATCH request from set parameters.
@@ -1051,26 +1124,40 @@ module Zizq
1051
1124
  # - Other values are converted to their wire format.
1052
1125
  #
1053
1126
  # @rbs return: Hash[Symbol, untyped]
1054
- def build_set_body(queue: UNCHANGED,
1055
- priority: UNCHANGED,
1056
- ready_at: UNCHANGED,
1057
- retry_limit: UNCHANGED,
1058
- backoff: UNCHANGED,
1059
- retention: UNCHANGED)
1127
+ def build_set_body(
1128
+ queue: UNCHANGED,
1129
+ priority: UNCHANGED,
1130
+ ready_at: UNCHANGED,
1131
+ retry_limit: UNCHANGED,
1132
+ backoff: UNCHANGED,
1133
+ retention: UNCHANGED
1134
+ )
1060
1135
  body = {} #: Hash[Symbol, untyped]
1061
1136
 
1062
1137
  unless queue.equal?(UNCHANGED)
1063
- raise ArgumentError, "queue cannot be nil; use Zizq::RESET to clear or Zizq::UNCHANGED to leave as-is" if queue.nil?
1138
+ if queue.nil?
1139
+ raise ArgumentError,
1140
+ "queue cannot be nil; use Zizq::RESET to clear or Zizq::UNCHANGED to leave as-is"
1141
+ end
1064
1142
  body[:queue] = queue
1065
1143
  end
1066
1144
 
1067
1145
  unless priority.equal?(UNCHANGED)
1068
- raise ArgumentError, "priority cannot be nil; use Zizq::RESET to clear or Zizq::UNCHANGED to leave as-is" if priority.nil?
1146
+ if priority.nil?
1147
+ raise ArgumentError,
1148
+ "priority cannot be nil; use Zizq::RESET to clear or Zizq::UNCHANGED to leave as-is"
1149
+ end
1069
1150
  body[:priority] = priority
1070
1151
  end
1071
1152
 
1072
1153
  unless ready_at.equal?(UNCHANGED)
1073
- body[:ready_at] = ready_at.equal?(RESET) ? nil : (ready_at.to_f * 1000).to_i
1154
+ body[:ready_at] = (
1155
+ if ready_at.equal?(RESET)
1156
+ nil
1157
+ else
1158
+ (ready_at.to_f * 1000).to_i
1159
+ end
1160
+ )
1074
1161
  end
1075
1162
 
1076
1163
  unless retry_limit.equal?(UNCHANGED)
@@ -1094,8 +1181,12 @@ module Zizq
1094
1181
  nil
1095
1182
  else
1096
1183
  ret = {} #: Hash[Symbol, Integer]
1097
- ret[:completed_ms] = (retention[:completed].to_f * 1000).to_i if retention[:completed]
1098
- ret[:dead_ms] = (retention[:dead].to_f * 1000).to_i if retention[:dead]
1184
+ ret[:completed_ms] = (
1185
+ retention[:completed].to_f * 1000
1186
+ ).to_i if retention[:completed]
1187
+ ret[:dead_ms] = (retention[:dead].to_f * 1000).to_i if retention[
1188
+ :dead
1189
+ ]
1099
1190
  ret
1100
1191
  end
1101
1192
  end
@@ -1118,22 +1209,32 @@ module Zizq
1118
1209
 
1119
1210
  def encode_body(body) #: (Hash[Symbol, untyped]) -> String
1120
1211
  case @format
1121
- when :msgpack then MessagePack.pack(body)
1122
- when :json then JSON.generate(body)
1123
- else raise ArgumentError, "Unknown format: #{@format}"
1212
+ when :msgpack
1213
+ MessagePack.pack(body)
1214
+ when :json
1215
+ JSON.generate(body)
1216
+ else
1217
+ raise ArgumentError, "Unknown format: #{@format}"
1124
1218
  end
1125
1219
  end
1126
1220
 
1127
1221
  def decode_body(data, content_type: nil) #: (String, ?content_type: String?) -> Hash[String, untyped]
1128
- format = case content_type
1129
- when /msgpack/ then :msgpack
1130
- when /json/ then :json
1131
- else @format
1132
- end
1222
+ format =
1223
+ case content_type
1224
+ when /msgpack/
1225
+ :msgpack
1226
+ when /json/
1227
+ :json
1228
+ else
1229
+ @format
1230
+ end
1133
1231
  case format
1134
- when :msgpack then MessagePack.unpack(data)
1135
- when :json then JSON.parse(data)
1136
- else raise ArgumentError, "Unknown format: #{format}"
1232
+ when :msgpack
1233
+ MessagePack.unpack(data)
1234
+ when :json
1235
+ JSON.parse(data)
1236
+ else
1237
+ raise ArgumentError, "Unknown format: #{format}"
1137
1238
  end
1138
1239
  end
1139
1240
 
@@ -1153,7 +1254,11 @@ module Zizq
1153
1254
  # Read the response body and close it, returning a RawResponse that is
1154
1255
  # safe to use outside the reactor.
1155
1256
  def consume_response(response) #: (untyped) -> RawResponse
1156
- RawResponse.new(status: response.status, body: response.read, content_type: response.headers["content-type"])
1257
+ RawResponse.new(
1258
+ status: response.status,
1259
+ body: response.read,
1260
+ content_type: response.headers["content-type"]
1261
+ )
1157
1262
  ensure
1158
1263
  response.close
1159
1264
  end
@@ -1239,24 +1344,22 @@ module Zizq
1239
1344
  end
1240
1345
 
1241
1346
  def thread_local_http(key, endpoint) #: (Symbol, Async::HTTP::Endpoint) -> Async::HTTP::Client
1242
- Thread.current.thread_variable_get(key) || begin
1243
- client = Async::HTTP::Client.new(endpoint)
1244
- @mutex.synchronize do
1245
- @http_clients.reject! { |ref| !ref.weakref_alive? }
1246
- @http_clients << WeakRef.new(client)
1347
+ Thread.current.thread_variable_get(key) ||
1348
+ begin
1349
+ client = Async::HTTP::Client.new(endpoint)
1350
+ @mutex.synchronize do
1351
+ @http_clients.reject! { |ref| !ref.weakref_alive? }
1352
+ @http_clients << WeakRef.new(client)
1353
+ end
1354
+ Thread.current.thread_variable_set(key, client)
1355
+ client
1247
1356
  end
1248
- Thread.current.thread_variable_set(key, client)
1249
- client
1250
- end
1251
1357
  end
1252
1358
 
1253
1359
  def get(path, params: {}) #: (String, ?params: Hash[Symbol, untyped]) -> RawResponse
1254
1360
  request do |http|
1255
1361
  consume_response(
1256
- http.get(
1257
- build_path(path, params:),
1258
- {"accept" => @content_type}
1259
- )
1362
+ http.get(build_path(path, params:), { "accept" => @content_type })
1260
1363
  )
1261
1364
  end
1262
1365
  end
@@ -1266,7 +1369,7 @@ module Zizq
1266
1369
  consume_response(
1267
1370
  http.post(
1268
1371
  build_path(path),
1269
- {"content-type" => @content_type, "accept" => @content_type},
1372
+ { "content-type" => @content_type, "accept" => @content_type },
1270
1373
  Protocol::HTTP::Body::Buffered.wrap(encode_body(body))
1271
1374
  )
1272
1375
  )
@@ -1276,10 +1379,7 @@ module Zizq
1276
1379
  def raw_post(path) #: (String) -> RawResponse
1277
1380
  request do |http|
1278
1381
  consume_response(
1279
- http.post(
1280
- build_path(path),
1281
- {"accept" => @content_type}
1282
- )
1382
+ http.post(build_path(path), { "accept" => @content_type })
1283
1383
  )
1284
1384
  end
1285
1385
  end
@@ -1289,7 +1389,7 @@ module Zizq
1289
1389
  consume_response(
1290
1390
  http.put(
1291
1391
  build_path(path),
1292
- {"content-type" => @content_type, "accept" => @content_type},
1392
+ { "content-type" => @content_type, "accept" => @content_type },
1293
1393
  Protocol::HTTP::Body::Buffered.wrap(encode_body(body))
1294
1394
  )
1295
1395
  )
@@ -1299,10 +1399,7 @@ module Zizq
1299
1399
  def delete(path, params: {}) #: (String, ?params: Hash[Symbol, untyped]) -> RawResponse
1300
1400
  request do |http|
1301
1401
  consume_response(
1302
- http.delete(
1303
- build_path(path, params:),
1304
- {"accept" => @content_type}
1305
- )
1402
+ http.delete(build_path(path, params:), { "accept" => @content_type })
1306
1403
  )
1307
1404
  end
1308
1405
  end
@@ -1312,7 +1409,7 @@ module Zizq
1312
1409
  consume_response(
1313
1410
  http.patch(
1314
1411
  build_path(path, params:),
1315
- {"content-type" => @content_type, "accept" => @content_type},
1412
+ { "content-type" => @content_type, "accept" => @content_type },
1316
1413
  Protocol::HTTP::Body::Buffered.wrap(encode_body(body))
1317
1414
  )
1318
1415
  )
@@ -1330,18 +1427,24 @@ module Zizq
1330
1427
  return nil if status == 204
1331
1428
  decode_body(response.body, content_type: ct)
1332
1429
  else
1333
- body = begin
1334
- decode_body(response.body, content_type: ct)
1335
- rescue
1336
- nil
1337
- end
1430
+ body =
1431
+ begin
1432
+ decode_body(response.body, content_type: ct)
1433
+ rescue StandardError
1434
+ nil
1435
+ end
1338
1436
  message = body&.fetch("error", nil) || "HTTP #{status}"
1339
- error_class = case status
1340
- when 404 then NotFoundError
1341
- when 400..499 then ClientError
1342
- when 500..599 then ServerError
1343
- else ResponseError
1344
- end
1437
+ error_class =
1438
+ case status
1439
+ when 404
1440
+ NotFoundError
1441
+ when 400..499
1442
+ ClientError
1443
+ when 500..599
1444
+ ServerError
1445
+ else
1446
+ ResponseError
1447
+ end
1345
1448
  raise error_class.new(message, status: status, body: body)
1346
1449
  end
1347
1450
  end