zizq 0.1.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 +7 -0
- data/LICENSE +21 -0
- data/README.md +94 -0
- data/bin/profile-worker +145 -0
- data/bin/zizq-worker +174 -0
- data/lib/active_job/queue_adapters/zizq_adapter.rb +109 -0
- data/lib/zizq/ack_processor.rb +132 -0
- data/lib/zizq/active_job_config.rb +122 -0
- data/lib/zizq/backoff.rb +50 -0
- data/lib/zizq/bulk_enqueue.rb +87 -0
- data/lib/zizq/client.rb +982 -0
- data/lib/zizq/configuration.rb +164 -0
- data/lib/zizq/enqueue_request.rb +178 -0
- data/lib/zizq/enqueue_with.rb +109 -0
- data/lib/zizq/error.rb +43 -0
- data/lib/zizq/job.rb +188 -0
- data/lib/zizq/job_config.rb +244 -0
- data/lib/zizq/lifecycle.rb +58 -0
- data/lib/zizq/middleware.rb +79 -0
- data/lib/zizq/query.rb +566 -0
- data/lib/zizq/resources/error_enumerator.rb +241 -0
- data/lib/zizq/resources/error_page.rb +19 -0
- data/lib/zizq/resources/error_record.rb +19 -0
- data/lib/zizq/resources/job.rb +124 -0
- data/lib/zizq/resources/job_page.rb +57 -0
- data/lib/zizq/resources/page.rb +77 -0
- data/lib/zizq/resources/resource.rb +45 -0
- data/lib/zizq/resources.rb +16 -0
- data/lib/zizq/version.rb +9 -0
- data/lib/zizq/worker.rb +467 -0
- data/lib/zizq.rb +269 -0
- data/sig/generated/zizq/ack_processor.rbs +73 -0
- data/sig/generated/zizq/active_job_config.rbs +74 -0
- data/sig/generated/zizq/backoff.rbs +34 -0
- data/sig/generated/zizq/bulk_enqueue.rbs +72 -0
- data/sig/generated/zizq/client.rbs +419 -0
- data/sig/generated/zizq/configuration.rbs +95 -0
- data/sig/generated/zizq/enqueue_request.rbs +94 -0
- data/sig/generated/zizq/enqueue_with.rbs +88 -0
- data/sig/generated/zizq/error.rbs +41 -0
- data/sig/generated/zizq/job.rbs +136 -0
- data/sig/generated/zizq/job_config.rbs +150 -0
- data/sig/generated/zizq/lifecycle.rbs +34 -0
- data/sig/generated/zizq/middleware.rbs +50 -0
- data/sig/generated/zizq/query.rbs +327 -0
- data/sig/generated/zizq/resources/error_enumerator.rbs +148 -0
- data/sig/generated/zizq/resources/error_page.rbs +13 -0
- data/sig/generated/zizq/resources/error_record.rbs +20 -0
- data/sig/generated/zizq/resources/job.rbs +89 -0
- data/sig/generated/zizq/resources/job_page.rbs +33 -0
- data/sig/generated/zizq/resources/page.rbs +47 -0
- data/sig/generated/zizq/resources/resource.rbs +26 -0
- data/sig/generated/zizq/version.rbs +5 -0
- data/sig/generated/zizq/worker.rbs +152 -0
- data/sig/generated/zizq.rbs +180 -0
- data/sig/zizq.rbs +111 -0
- metadata +134 -0
data/lib/zizq.rb
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
# Copyright (c) 2026 Chris Corbyn <chris@zizq.io>
|
|
2
|
+
# Licensed under the MIT License. See LICENSE file for details.
|
|
3
|
+
|
|
4
|
+
# rbs_inline: enabled
|
|
5
|
+
# frozen_string_literal: true
|
|
6
|
+
|
|
7
|
+
require_relative "zizq/version"
|
|
8
|
+
require_relative "zizq/error"
|
|
9
|
+
require_relative "zizq/configuration"
|
|
10
|
+
|
|
11
|
+
# Autoloaded when first accessed — avoids loading heavy deps at require time.
|
|
12
|
+
autoload :MessagePack, "msgpack"
|
|
13
|
+
|
|
14
|
+
module Zizq
|
|
15
|
+
autoload :AckProcessor, "zizq/ack_processor"
|
|
16
|
+
autoload :ActiveJobConfig, "zizq/active_job_config"
|
|
17
|
+
autoload :Backoff, "zizq/backoff"
|
|
18
|
+
autoload :BulkEnqueue, "zizq/bulk_enqueue"
|
|
19
|
+
autoload :Client, "zizq/client"
|
|
20
|
+
autoload :EnqueueRequest, "zizq/enqueue_request"
|
|
21
|
+
autoload :EnqueueWith, "zizq/enqueue_with"
|
|
22
|
+
autoload :Job, "zizq/job"
|
|
23
|
+
autoload :JobConfig, "zizq/job_config"
|
|
24
|
+
autoload :Middleware, "zizq/middleware"
|
|
25
|
+
autoload :Lifecycle, "zizq/lifecycle"
|
|
26
|
+
autoload :Query, "zizq/query"
|
|
27
|
+
autoload :Resources, "zizq/resources"
|
|
28
|
+
autoload :Worker, "zizq/worker"
|
|
29
|
+
|
|
30
|
+
# Sentinel indicating a field should not be included in the request.
|
|
31
|
+
# Used as the default for update parameters.
|
|
32
|
+
module UNCHANGED; end
|
|
33
|
+
|
|
34
|
+
# Sentinel indicating a field should be sent as null to reset to server default.
|
|
35
|
+
module RESET; end
|
|
36
|
+
|
|
37
|
+
@client_mutex = Mutex.new
|
|
38
|
+
|
|
39
|
+
class << self
|
|
40
|
+
# Returns the client configuration.
|
|
41
|
+
#
|
|
42
|
+
# The configuration can be updated by calling [`Zizq::configure`].
|
|
43
|
+
#
|
|
44
|
+
# This configuration is for the client only. Worker parameters are
|
|
45
|
+
# configured on a per-run basis for flexibility.
|
|
46
|
+
def configuration #: () -> Configuration
|
|
47
|
+
@configuration ||= Configuration.new
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Yields the global configuration ready for updates, which should be done
|
|
51
|
+
# during application initialization, before any jobs are enqueued or
|
|
52
|
+
# worked.
|
|
53
|
+
#
|
|
54
|
+
# Zizq.configure do |c|
|
|
55
|
+
# c.url = "http://localhost:7890"
|
|
56
|
+
# c.format = :msgpack
|
|
57
|
+
# c.dequeue_middleware.use(MyDequeueMiddleware.new)
|
|
58
|
+
# end
|
|
59
|
+
def configure #: () { (Configuration) -> void } -> void
|
|
60
|
+
yield configuration
|
|
61
|
+
ensure
|
|
62
|
+
@client = nil # shared client is potentially stale
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Returns a shared client instance built from the global configuration.
|
|
66
|
+
#
|
|
67
|
+
# The client is memoized so that persistent HTTP connections are reused
|
|
68
|
+
# across calls, reducing TCP connection overhead.
|
|
69
|
+
def client #: () -> Client
|
|
70
|
+
@client ||= begin
|
|
71
|
+
@client_mutex.synchronize do
|
|
72
|
+
break @client if @client
|
|
73
|
+
|
|
74
|
+
configuration.validate!
|
|
75
|
+
@client = Client.new(
|
|
76
|
+
url: configuration.url,
|
|
77
|
+
format: configuration.format,
|
|
78
|
+
ssl_context: configuration.ssl_context
|
|
79
|
+
)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Resets all global state: configuration and shared client.
|
|
85
|
+
# Intended for use in tests.
|
|
86
|
+
def reset! #: () -> void
|
|
87
|
+
@client&.close
|
|
88
|
+
@client = nil
|
|
89
|
+
@configuration = nil
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Server version string.
|
|
93
|
+
def server_version #: () -> String
|
|
94
|
+
client.server_version
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# List all distinct queue names on the server.
|
|
98
|
+
def queues #: () -> Array[String]
|
|
99
|
+
client.get_queues
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Start a query to retrieve or modify job data.
|
|
103
|
+
#
|
|
104
|
+
# @rbs id: (String | Array[String])?
|
|
105
|
+
# @rbs queue: (String | Array[String])?
|
|
106
|
+
# @rbs type: (String | Array[String])?
|
|
107
|
+
# @rbs status: (String | Array[String])?
|
|
108
|
+
# @rbs jq_filter: String?
|
|
109
|
+
# @rbs order: Zizq::sort_direction?
|
|
110
|
+
# @rbs limit: Integer?
|
|
111
|
+
# @rbs page_size: Integer?
|
|
112
|
+
# @rbs return: Zizq::Query
|
|
113
|
+
def query(...)
|
|
114
|
+
Query.new(...)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Enqueue a job by class with positional and keyword arguments.
|
|
118
|
+
#
|
|
119
|
+
# By default all arguments are serialized as JSON, which means hashes with
|
|
120
|
+
# symbol keys will become hashes with string keys. The serialization
|
|
121
|
+
# behaviour can be changed by implementing `::zizq_serialize` and
|
|
122
|
+
# `::zizq_deserialize` as class methods on the job class.
|
|
123
|
+
#
|
|
124
|
+
# Default job options can be overridden at enqueue-time by providing a
|
|
125
|
+
# block which receives a mutable `Zizq::EnqueueRequest` instance.
|
|
126
|
+
#
|
|
127
|
+
# Zizq.enqueue(SendEmailJob, 42, template: "welcome")
|
|
128
|
+
# Zizq.enqueue(SendEmailJob, 42) { |o| o.queue = "priority" }
|
|
129
|
+
#
|
|
130
|
+
# Job classes may also override `::zizq_enqueue_options` to implement
|
|
131
|
+
# dynamically computed options, such as dynamic prioritisation. This class
|
|
132
|
+
# method accepts the same arguments as the `#perform` method and returns an
|
|
133
|
+
# instance of `Zizq::EnqueueRequest`. Any overrides may call `super` and
|
|
134
|
+
# modify the result.
|
|
135
|
+
#
|
|
136
|
+
# class SendEmailJob
|
|
137
|
+
# include Zizq::Job
|
|
138
|
+
#
|
|
139
|
+
# zizq_priority 1000
|
|
140
|
+
#
|
|
141
|
+
# def self.zizq_enqueue_options(user_id, template:)
|
|
142
|
+
# opts = super
|
|
143
|
+
# opts.priority /= 2 if template == "welcome"
|
|
144
|
+
# opts
|
|
145
|
+
# end
|
|
146
|
+
#
|
|
147
|
+
# def perform(user_id, template:)
|
|
148
|
+
# # ...
|
|
149
|
+
# end
|
|
150
|
+
# end
|
|
151
|
+
#
|
|
152
|
+
# @rbs job_class: Class & Zizq::job_class
|
|
153
|
+
# @rbs args: Array[untyped]
|
|
154
|
+
# @rbs kwargs: Hash[Symbol, untyped]
|
|
155
|
+
# @rbs &block: ?(EnqueueRequest) -> void
|
|
156
|
+
# @rbs return: Resources::Job
|
|
157
|
+
def enqueue(job_class, *args, **kwargs, &block)
|
|
158
|
+
req = build_enqueue_request(job_class, *args, **kwargs, &block)
|
|
159
|
+
req = configuration.enqueue_middleware.call(req)
|
|
160
|
+
client.enqueue(**req.to_enqueue_params)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Enqueue a job by providing raw inputs to the Zizq server.
|
|
164
|
+
#
|
|
165
|
+
# This is for advanced use cases such as enqueueing jobs for consumption in
|
|
166
|
+
# other programming languages.
|
|
167
|
+
#
|
|
168
|
+
# Zizq.enqueue_raw(
|
|
169
|
+
# queue: "emails",
|
|
170
|
+
# type: "send_email",
|
|
171
|
+
# payload: {user_id: 42, template: "welcome"}
|
|
172
|
+
# )
|
|
173
|
+
#
|
|
174
|
+
# If using this method to enqueue a job that is intended for consumption in
|
|
175
|
+
# the Ruby client itself a custom dispatcher implementation is likely
|
|
176
|
+
# required:
|
|
177
|
+
#
|
|
178
|
+
# Zizq.configure do |c|
|
|
179
|
+
# c.dispatcher = MyDispatcher.new
|
|
180
|
+
# end
|
|
181
|
+
#
|
|
182
|
+
# @rbs queue: String
|
|
183
|
+
# @rbs type: String
|
|
184
|
+
# @rbs payload: untyped
|
|
185
|
+
# @rbs priority: Integer?
|
|
186
|
+
# @rbs ready_at: Zizq::to_f?
|
|
187
|
+
# @rbs retry_limit: Integer?
|
|
188
|
+
# @rbs backoff: Zizq::backoff?
|
|
189
|
+
# @rbs retention: Zizq::retention?
|
|
190
|
+
# @rbs unique_key: String?
|
|
191
|
+
# @rbs unique_while: Zizq::unique_scope?
|
|
192
|
+
# @rbs return: Resources::Job
|
|
193
|
+
def enqueue_raw(queue:, type:, payload:, **opts)
|
|
194
|
+
req = EnqueueRequest.new(queue:, type:, payload:, **opts)
|
|
195
|
+
req = configuration.enqueue_middleware.call(req)
|
|
196
|
+
client.enqueue(**req.to_enqueue_params)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
# Enqueue multiple jobs atomically in a single bulk request.
|
|
200
|
+
#
|
|
201
|
+
# This can significantly imprive throughput when many jobs need to be
|
|
202
|
+
# enqueued collectively. There is no upper limit on the number of jobs in
|
|
203
|
+
# the request though generally it is probably wise to keep this to less
|
|
204
|
+
# than 1000 jobs unless you have strong atomicity requuirements for a
|
|
205
|
+
# larger number of jobs..
|
|
206
|
+
#
|
|
207
|
+
# Yields a builder object whose `#enqueue` method accepts the same
|
|
208
|
+
# arguments as `Zizq.enqueue`. All collected jobs are sent as a
|
|
209
|
+
# single `POST /jobs/bulk` request and an array of jobs is returned in the
|
|
210
|
+
# same order as the inputs.
|
|
211
|
+
#
|
|
212
|
+
# Zizq.enqueue_bulk do |b|
|
|
213
|
+
# b.enqueue(ProcessPaymentJob, 7)
|
|
214
|
+
# b.enqueue(SendEmailJob, 42, template: "welcome")
|
|
215
|
+
# b.enqueue(SendEmailJob, 42) { |o| o.queue = "priority" }
|
|
216
|
+
# end
|
|
217
|
+
#
|
|
218
|
+
# Build a scoped enqueue helper that applies the given option overrides
|
|
219
|
+
# to every enqueue routed through it. Equivalent to using the block
|
|
220
|
+
# form of `Zizq.enqueue`, but composable and reusable.
|
|
221
|
+
#
|
|
222
|
+
# Zizq.enqueue_with(ready_at: Time.now + 3600).enqueue(MyJob, 42)
|
|
223
|
+
# Zizq.enqueue_with(priority: 0).enqueue_bulk { |b| ... }
|
|
224
|
+
#
|
|
225
|
+
# See `Zizq::EnqueueWith` for details.
|
|
226
|
+
#
|
|
227
|
+
# @rbs overrides: Hash[Symbol, untyped]
|
|
228
|
+
# @rbs return: EnqueueWith
|
|
229
|
+
def enqueue_with(**overrides)
|
|
230
|
+
EnqueueWith.new(self, overrides)
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# @rbs &block: (BulkEnqueue) -> void
|
|
234
|
+
# @rbs return: Array[Resources::Job]
|
|
235
|
+
def enqueue_bulk(&block)
|
|
236
|
+
builder = BulkEnqueue.new
|
|
237
|
+
yield builder
|
|
238
|
+
return [] if builder.requests.empty?
|
|
239
|
+
|
|
240
|
+
jobs = builder.requests.map do |req|
|
|
241
|
+
configuration.enqueue_middleware.call(req).to_enqueue_params
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
client.enqueue_bulk(jobs:)
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
# @api private
|
|
248
|
+
# Build an EnqueueRequest for a single job class enqueue.
|
|
249
|
+
#
|
|
250
|
+
# @rbs job_class: Class & Zizq::job_class
|
|
251
|
+
# @rbs args: Array[untyped]
|
|
252
|
+
# @rbs kwargs: Hash[Symbol, untyped]
|
|
253
|
+
# @rbs &block: ?(EnqueueRequest) -> void
|
|
254
|
+
# @rbs return: EnqueueRequest
|
|
255
|
+
def build_enqueue_request(job_class, *args, **kwargs, &block)
|
|
256
|
+
unless job_class.is_a?(Class) && job_class < Zizq::Job
|
|
257
|
+
raise ArgumentError, "#{job_class.inspect} must include Zizq::Job"
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
zizq_job_class = job_class #: Zizq::job_class
|
|
261
|
+
req = zizq_job_class.zizq_enqueue_request(*args, **kwargs)
|
|
262
|
+
yield req if block_given?
|
|
263
|
+
req
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# Make sure everything is cleaned up before we exit.
|
|
269
|
+
Kernel.at_exit { Zizq.reset! }
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Generated from lib/zizq/ack_processor.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Zizq
|
|
4
|
+
# Dedicated background thread that processes ack/nack HTTP requests on
|
|
5
|
+
# behalf of worker threads, decoupling job processing from network I/O.
|
|
6
|
+
#
|
|
7
|
+
# Workers push Ack/Nack items to a thread-safe queue. The processor runs
|
|
8
|
+
# an async event loop that spawns an independent fiber per ack/nack
|
|
9
|
+
# request, enabling true concurrent I/O over a single HTTP/2 connection.
|
|
10
|
+
# Each fiber handles its own retries with exponential backoff.
|
|
11
|
+
class AckProcessor
|
|
12
|
+
# Immutable value object representing a successful job completion.
|
|
13
|
+
class Ack < Data
|
|
14
|
+
attr_reader job_id(): untyped
|
|
15
|
+
|
|
16
|
+
def self.new: (untyped job_id) -> instance
|
|
17
|
+
| (job_id: untyped) -> instance
|
|
18
|
+
|
|
19
|
+
def self.members: () -> [ :job_id ]
|
|
20
|
+
|
|
21
|
+
def members: () -> [ :job_id ]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Immutable value object representing a job failure.
|
|
25
|
+
class Nack < Data
|
|
26
|
+
attr_reader job_id(): untyped
|
|
27
|
+
|
|
28
|
+
attr_reader message(): untyped
|
|
29
|
+
|
|
30
|
+
attr_reader error_type(): untyped
|
|
31
|
+
|
|
32
|
+
attr_reader backtrace(): untyped
|
|
33
|
+
|
|
34
|
+
def self.new: (untyped job_id, untyped message, untyped error_type, untyped backtrace) -> instance
|
|
35
|
+
| (job_id: untyped, message: untyped, error_type: untyped, backtrace: untyped) -> instance
|
|
36
|
+
|
|
37
|
+
def self.members: () -> [ :job_id, :message, :error_type, :backtrace ]
|
|
38
|
+
|
|
39
|
+
def members: () -> [ :job_id, :message, :error_type, :backtrace ]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @rbs client: Client
|
|
43
|
+
# @rbs capacity: Integer
|
|
44
|
+
# @rbs logger: Logger
|
|
45
|
+
# @rbs backoff: Backoff
|
|
46
|
+
# @rbs return: void
|
|
47
|
+
def initialize: (client: Client, capacity: Integer, logger: Logger, backoff: Backoff) -> void
|
|
48
|
+
|
|
49
|
+
# Push an Ack or Nack to the processing queue.
|
|
50
|
+
# Blocks if the queue is at capacity (backpressure).
|
|
51
|
+
#
|
|
52
|
+
# @rbs item: Ack | Nack
|
|
53
|
+
# @rbs return: void
|
|
54
|
+
def push: (Ack | Nack item) -> void
|
|
55
|
+
|
|
56
|
+
# Start the background processor thread.
|
|
57
|
+
def start: () -> untyped
|
|
58
|
+
|
|
59
|
+
# Close the queue and wait for the processor to drain. Waits indefinitely —
|
|
60
|
+
# callers who want a deadline should wrap the call in `Timeout::timeout`.
|
|
61
|
+
#
|
|
62
|
+
# @rbs return: void
|
|
63
|
+
def stop: () -> void
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
def run: () -> untyped
|
|
68
|
+
|
|
69
|
+
def process_ack_batch: (untyped acks) -> untyped
|
|
70
|
+
|
|
71
|
+
def process_nack: (untyped nack) -> untyped
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Generated from lib/zizq/active_job_config.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Zizq
|
|
4
|
+
# Zizq configuration DSL for ActiveJob classes.
|
|
5
|
+
#
|
|
6
|
+
# Extend this module in an ActiveJob subclass to gain access to Zizq
|
|
7
|
+
# features like unique jobs, backoff, and retention:
|
|
8
|
+
#
|
|
9
|
+
# class SendEmailJob < ApplicationJob
|
|
10
|
+
# extend Zizq::ActiveJobConfig
|
|
11
|
+
#
|
|
12
|
+
# zizq_unique true, scope: :active
|
|
13
|
+
# zizq_backoff exponent: 4.0, base: 15, jitter: 30
|
|
14
|
+
#
|
|
15
|
+
# def perform(user_id, template:)
|
|
16
|
+
# # ...
|
|
17
|
+
# end
|
|
18
|
+
# end
|
|
19
|
+
#
|
|
20
|
+
# Serialization uses ActiveJob's own format so that GlobalID, Time, and
|
|
21
|
+
# other ActiveJob-supported types are handled correctly. The Zizq worker
|
|
22
|
+
# must use the ActiveJob dispatcher:
|
|
23
|
+
#
|
|
24
|
+
# Zizq.configure do |c|
|
|
25
|
+
# c.dispatcher = ActiveJob::QueueAdapters::ZizqAdapter::Dispatcher
|
|
26
|
+
# end
|
|
27
|
+
module ActiveJobConfig
|
|
28
|
+
include JobConfig
|
|
29
|
+
|
|
30
|
+
# ActiveJob::Base.new — invisible to steep without this.
|
|
31
|
+
def new: (*untyped, **untyped) -> untyped
|
|
32
|
+
|
|
33
|
+
# Serialize arguments using ActiveJob's serialization format.
|
|
34
|
+
#
|
|
35
|
+
# Creates a temporary ActiveJob instance to produce the canonical
|
|
36
|
+
# serialized form, including `_aj_ruby2_keywords` markers for kwargs.
|
|
37
|
+
# This ensures unique key generation uses the same format as the
|
|
38
|
+
# enqueued payload.
|
|
39
|
+
#
|
|
40
|
+
# This is needed so that unique job keys can be correctly generated.
|
|
41
|
+
def zizq_serialize: (*untyped args, **untyped kwargs) -> untyped
|
|
42
|
+
|
|
43
|
+
# Deserialization is handled by ActiveJob::Base.execute on the worker
|
|
44
|
+
# side. This method is not used in the ActiveJob dispatch path.
|
|
45
|
+
def zizq_deserialize: (untyped _payload) -> untyped
|
|
46
|
+
|
|
47
|
+
# Generate a jq expression that exactly matches payloads with the given
|
|
48
|
+
# arguments.
|
|
49
|
+
#
|
|
50
|
+
# This is used for filtering in Zizq::Query.
|
|
51
|
+
#
|
|
52
|
+
# Generates an expression of the form:
|
|
53
|
+
#
|
|
54
|
+
# .arguments == ["a","b",{"example":true,"_aj_ruby2_keywords":["example"]}]
|
|
55
|
+
def zizq_payload_filter: (*untyped args, **untyped kwargs) -> untyped
|
|
56
|
+
|
|
57
|
+
# Generate a jq expression that matches jobs whose positional args
|
|
58
|
+
# start with the given values and whose kwargs contain the given
|
|
59
|
+
# key/value pairs.
|
|
60
|
+
#
|
|
61
|
+
# This is used for filtering in Zizq::Query.
|
|
62
|
+
#
|
|
63
|
+
# Generates expressions of the form:
|
|
64
|
+
#
|
|
65
|
+
# (.arguments[0:2] == ["a","b"])
|
|
66
|
+
#
|
|
67
|
+
# or
|
|
68
|
+
#
|
|
69
|
+
# (.arguments[0:2] == ["a","b"]) and
|
|
70
|
+
# (.arguments[-1] | has("_aj_ruby2_keywords")) and
|
|
71
|
+
# (.arguments[-1] | contains({"example":true}))
|
|
72
|
+
def zizq_payload_subset_filter: (*untyped args, **untyped kwargs) -> untyped
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Generated from lib/zizq/backoff.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Zizq
|
|
4
|
+
# Encapsulates exponential backoff state for retry loops.
|
|
5
|
+
#
|
|
6
|
+
# Each call to `wait` sleeps for the current duration and then advances
|
|
7
|
+
# to the next interval. Call `reset` to return to the initial wait time
|
|
8
|
+
# after a successful operation.
|
|
9
|
+
class Backoff
|
|
10
|
+
attr_reader min_wait: Float
|
|
11
|
+
|
|
12
|
+
attr_reader max_wait: Float
|
|
13
|
+
|
|
14
|
+
attr_reader multiplier: Float
|
|
15
|
+
|
|
16
|
+
# @rbs min_wait: (Float | Integer)
|
|
17
|
+
# @rbs max_wait: (Float | Integer)
|
|
18
|
+
# @rbs multiplier: (Float | Integer)
|
|
19
|
+
# @rbs return: void
|
|
20
|
+
def initialize: (min_wait: Float | Integer, max_wait: Float | Integer, multiplier: Float | Integer) -> void
|
|
21
|
+
|
|
22
|
+
# Returns the current backoff duration without advancing.
|
|
23
|
+
def duration: () -> untyped
|
|
24
|
+
|
|
25
|
+
# Sleeps for the current backoff duration, then advances to the next.
|
|
26
|
+
def wait: () -> untyped
|
|
27
|
+
|
|
28
|
+
# Resets the backoff to the initial min_wait.
|
|
29
|
+
def reset: () -> untyped
|
|
30
|
+
|
|
31
|
+
# Returns a new Backoff with the same configuration but reset state.
|
|
32
|
+
def fresh: () -> untyped
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Generated from lib/zizq/bulk_enqueue.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Zizq
|
|
4
|
+
# Builder for collecting multiple job params to be sent as a single bulk
|
|
5
|
+
# request via `Zizq.enqueue_bulk`.
|
|
6
|
+
#
|
|
7
|
+
# Zizq.enqueue_bulk do |b|
|
|
8
|
+
# b.enqueue(MyApp::FooJob, 42)
|
|
9
|
+
# b.enqueue(MyApp::OtherJob, 42, x: 7)
|
|
10
|
+
# end
|
|
11
|
+
class BulkEnqueue
|
|
12
|
+
attr_reader requests: Array[EnqueueRequest]
|
|
13
|
+
|
|
14
|
+
def initialize: () -> untyped
|
|
15
|
+
|
|
16
|
+
# Collect a job class enqueue. Accepts the same arguments as
|
|
17
|
+
# `Zizq.enqueue`.
|
|
18
|
+
#
|
|
19
|
+
# @rbs job_class: Class & Zizq::job_class
|
|
20
|
+
# @rbs args: Array[untyped]
|
|
21
|
+
# @rbs kwargs: Hash[Symbol, untyped]
|
|
22
|
+
# @rbs &block: ?(EnqueueRequest) -> void
|
|
23
|
+
# @rbs return: void
|
|
24
|
+
def enqueue: (Class & Zizq::job_class job_class, *untyped args, **untyped kwargs) ?{ (EnqueueRequest) -> void } -> void
|
|
25
|
+
|
|
26
|
+
# Collect a raw enqueue. Accepts the same arguments as
|
|
27
|
+
# `Zizq.enqueue_raw`.
|
|
28
|
+
#
|
|
29
|
+
# @rbs queue: String
|
|
30
|
+
# @rbs type: String
|
|
31
|
+
# @rbs payload: untyped
|
|
32
|
+
# @rbs priority: Integer?
|
|
33
|
+
# @rbs ready_at: Zizq::to_f?
|
|
34
|
+
# @rbs retry_limit: Integer?
|
|
35
|
+
# @rbs backoff: Zizq::backoff?
|
|
36
|
+
# @rbs retention: Zizq::retention?
|
|
37
|
+
# @rbs unique_key: String?
|
|
38
|
+
# @rbs unique_while: Zizq::unique_scope?
|
|
39
|
+
# @rbs return: void
|
|
40
|
+
def enqueue_raw: (queue: String, type: String, payload: untyped, **untyped opts) -> void
|
|
41
|
+
|
|
42
|
+
# Build a scoped enqueue helper that applies the given overrides to a
|
|
43
|
+
# single enqueue inside this bulk block. Sugar for the block form:
|
|
44
|
+
#
|
|
45
|
+
# b.enqueue_with(ready_at: Time.now + 3600).enqueue(OtherJob, 42)
|
|
46
|
+
#
|
|
47
|
+
# is equivalent to:
|
|
48
|
+
#
|
|
49
|
+
# b.enqueue(OtherJob, 42) { |req| req.ready_at = Time.now + 3600 }
|
|
50
|
+
#
|
|
51
|
+
# @rbs overrides: Hash[Symbol, untyped]
|
|
52
|
+
# @rbs return: EnqueueWith
|
|
53
|
+
def enqueue_with: (**untyped overrides) -> EnqueueWith
|
|
54
|
+
|
|
55
|
+
# Nested bulk is a no-op — we're already inside a bulk block, so we
|
|
56
|
+
# just yield this same builder. This exists to satisfy the
|
|
57
|
+
# `_EnqueueTarget` interface, which lets `EnqueueWith#enqueue_bulk`
|
|
58
|
+
# work uniformly against both the top-level `Zizq` module and a
|
|
59
|
+
# `BulkEnqueue` instance without branching on target type.
|
|
60
|
+
#
|
|
61
|
+
# Zizq.enqueue_bulk do |b|
|
|
62
|
+
# b.enqueue_with(priority: 0).enqueue_bulk do |b2|
|
|
63
|
+
# b2.enqueue(MyJob, 1)
|
|
64
|
+
# b2.enqueue(MyJob, 2)
|
|
65
|
+
# end
|
|
66
|
+
# end
|
|
67
|
+
#
|
|
68
|
+
# @rbs &block: (BulkEnqueue) -> void
|
|
69
|
+
# @rbs return: self
|
|
70
|
+
def enqueue_bulk: () { (BulkEnqueue) -> void } -> self
|
|
71
|
+
end
|
|
72
|
+
end
|