zizq 0.3.1 → 0.3.2
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/README.md +34 -20
- data/bin/zizq-worker +108 -32
- data/lib/zizq/configuration.rb +76 -22
- data/lib/zizq/tls_configuration.rb +27 -0
- data/lib/zizq/version.rb +1 -1
- data/lib/zizq/worker.rb +39 -39
- data/lib/zizq/worker_configuration.rb +48 -0
- data/lib/zizq.rb +2 -0
- data/sig/generated/zizq/configuration.rbs +37 -15
- data/sig/generated/zizq/tls_configuration.rbs +27 -0
- data/sig/generated/zizq/worker.rbs +16 -16
- data/sig/generated/zizq/worker_configuration.rbs +52 -0
- data/sig/zizq.rbs +2 -1
- metadata +6 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5f0af940d511a8e1aa6d89df8ca13e98733430827d5f3202bcf7434a94ee02da
|
|
4
|
+
data.tar.gz: 9341d2815e344b3e4b8ca402185e3de01bd488cb5a3159f18e132d3c65cc18ca
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a3e04dffd06a36db8ca940105675428390867bd8dee62b2bcf0ef7cbeef03fe080b35bf93061e9ec00b6834be0940e1d69d7bd837178718a0bd288b6895464c3
|
|
7
|
+
data.tar.gz: 9d5a7d77ca3e143dbcc8c5bb72a58eb1c60092335d206579646dac8df3cbf178a9627a0d8e7a68e394d2b07c32a60a82c915ab049175624760a314042d12f9b7
|
data/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Zizq — Official Ruby Client
|
|
2
2
|
|
|
3
|
+
This is the official Zizq client library for Ruby.
|
|
4
|
+
|
|
3
5
|
Zizq is a simple, zero dependency, single binary job queue system that is both
|
|
4
6
|
fast and durable. It is designed to work in any stack through a simple HTTP
|
|
5
7
|
API.
|
|
6
8
|
|
|
7
|
-
This is the official Zizq client library for Ruby.
|
|
8
|
-
|
|
9
9
|
[](https://github.com/zizq-labs/zizq-ruby/actions/workflows/ci.yml)
|
|
10
10
|
[](https://rubygems.org/gems/zizq)
|
|
11
11
|
|
|
@@ -32,13 +32,13 @@ This is the official Zizq client library for Ruby.
|
|
|
32
32
|
Add it to your application's `Gemfile`:
|
|
33
33
|
|
|
34
34
|
```ruby
|
|
35
|
-
gem 'zizq', '~> 0.3.
|
|
35
|
+
gem 'zizq', '~> 0.3.2'
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
Or install it manually:
|
|
39
39
|
|
|
40
40
|
```shell
|
|
41
|
-
$ gem install zizq -v 0.3.
|
|
41
|
+
$ gem install zizq -v 0.3.2
|
|
42
42
|
```
|
|
43
43
|
|
|
44
44
|
Ruby **3.2.8 or newer** is required. Client and server share version
|
|
@@ -55,12 +55,19 @@ require 'zizq'
|
|
|
55
55
|
|
|
56
56
|
Zizq.configure do |c|
|
|
57
57
|
c.url = 'https://zizq.your.network:7890'
|
|
58
|
-
c.tls = { ca: '/path/to/server-ca-cert.pem' }
|
|
59
58
|
c.logger = Logger.new('log/zizq.log')
|
|
59
|
+
|
|
60
|
+
c.tls.ca = '/path/to/server-ca-cert.pem'
|
|
61
|
+
|
|
62
|
+
# Optional worker defaults — applied to every Zizq::Worker
|
|
63
|
+
# instance and to runs of the `zizq-worker` executable. Explicit
|
|
64
|
+
# kwargs or CLI flags override these.
|
|
65
|
+
c.worker.queues = ['emails', 'payments']
|
|
66
|
+
c.worker.fiber_count = 25
|
|
60
67
|
end
|
|
61
68
|
```
|
|
62
69
|
|
|
63
|
-
For mutual TLS,
|
|
70
|
+
For mutual TLS, also set `c.tls.client_cert` and `c.tls.client_key`.
|
|
64
71
|
|
|
65
72
|
> [!CAUTION]
|
|
66
73
|
> If your server is exposed directly to the internet, it should require
|
|
@@ -149,20 +156,29 @@ end
|
|
|
149
156
|
### Running a worker
|
|
150
157
|
|
|
151
158
|
Jobs are processed by a worker, typically in a separate process. The simplest
|
|
152
|
-
way is the `zizq-worker` executable bundled with the gem
|
|
153
|
-
|
|
159
|
+
way is the `zizq-worker` executable bundled with the gem. **Rails apps need
|
|
160
|
+
no arguments** — `zizq-worker` auto-detects `config/environment.rb` when run
|
|
161
|
+
from the app's root:
|
|
154
162
|
|
|
155
163
|
```shell
|
|
156
|
-
$ bundle exec zizq-worker
|
|
157
|
-
I, [...] INFO -- : Zizq worker starting:
|
|
164
|
+
$ bundle exec zizq-worker
|
|
165
|
+
I, [...] INFO -- : Zizq worker starting: 1 threads, 25 fibers, prefetch=50
|
|
158
166
|
I, [...] INFO -- : Connected. Listening for jobs.
|
|
159
167
|
```
|
|
160
168
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
169
|
+
For Sinatra or other apps, pass the entrypoint explicitly:
|
|
170
|
+
|
|
171
|
+
```shell
|
|
172
|
+
$ bundle exec zizq-worker app.rb
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Worker defaults (`queues`, `thread_count`, `fiber_count`, `prefetch`) come
|
|
176
|
+
from your `Zizq.configure { |c| c.worker.* }` block. CLI flags
|
|
177
|
+
(`--threads`, `--fibers`, `--queue`, `--all-queues`, etc.) override the
|
|
178
|
+
configured defaults when needed. Leave `--fibers 1` if your application
|
|
179
|
+
isn't fiber-safe — no `Async` context is loaded in that case. `INT` /
|
|
180
|
+
`TERM` trigger a graceful shutdown (drains in-flight jobs up to
|
|
181
|
+
`--shutdown-deadline`, default 30s).
|
|
166
182
|
|
|
167
183
|
For more control — for example running the worker in-process alongside a
|
|
168
184
|
Rack app — construct `Zizq::Worker` directly:
|
|
@@ -170,11 +186,9 @@ Rack app — construct `Zizq::Worker` directly:
|
|
|
170
186
|
```ruby
|
|
171
187
|
require 'zizq'
|
|
172
188
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
queues: ['emails', 'payments'],
|
|
177
|
-
)
|
|
189
|
+
# Picks up queues, fiber_count, etc. from Zizq.configure { |c| c.worker.* };
|
|
190
|
+
# any kwarg here overrides those defaults.
|
|
191
|
+
worker = Zizq::Worker.new(queues: ['emails', 'payments'])
|
|
178
192
|
|
|
179
193
|
Signal.trap('INT') { worker.stop }
|
|
180
194
|
worker.run # blocks until the worker stops
|
data/bin/zizq-worker
CHANGED
|
@@ -11,58 +11,96 @@ require "zizq"
|
|
|
11
11
|
# Default deadline for a graceful `stop` before escalating to `kill`.
|
|
12
12
|
DEFAULT_SHUTDOWN_DEADLINE = 30.0
|
|
13
13
|
|
|
14
|
-
# --- Defaults from env vars,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
# --- Defaults from env vars (nil = "not set, defer to Zizq.configure then Worker default") ---
|
|
15
|
+
#
|
|
16
|
+
# Note: env-var-unset values stay as nil rather than being seeded
|
|
17
|
+
# with the Worker's `DEFAULT_*` constants. This lets `Zizq.configure
|
|
18
|
+
# { |c| c.worker.<field> = ... }` win when neither the env nor the
|
|
19
|
+
# CLI explicitly set the value.
|
|
20
|
+
|
|
21
|
+
thread_count = ENV.key?("ZIZQ_THREADS") ? Integer(ENV["ZIZQ_THREADS"]) : nil
|
|
22
|
+
fiber_count = ENV.key?("ZIZQ_FIBERS") ? Integer(ENV["ZIZQ_FIBERS"]) : nil
|
|
18
23
|
prefetch = ENV.key?("ZIZQ_PREFETCH") ? Integer(ENV["ZIZQ_PREFETCH"]) : nil
|
|
19
24
|
shutdown_deadline = Float(ENV.fetch("ZIZQ_SHUTDOWN_DEADLINE", DEFAULT_SHUTDOWN_DEADLINE))
|
|
20
|
-
retry_min_wait =
|
|
21
|
-
retry_max_wait =
|
|
22
|
-
retry_multiplier =
|
|
23
|
-
|
|
24
|
-
queues
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
retry_min_wait = ENV.key?("ZIZQ_RETRY_MIN_WAIT") ? Float(ENV["ZIZQ_RETRY_MIN_WAIT"]) : nil
|
|
26
|
+
retry_max_wait = ENV.key?("ZIZQ_RETRY_MAX_WAIT") ? Float(ENV["ZIZQ_RETRY_MAX_WAIT"]) : nil
|
|
27
|
+
retry_multiplier = ENV.key?("ZIZQ_RETRY_MULTIPLIER") ? Float(ENV["ZIZQ_RETRY_MULTIPLIER"]) : nil
|
|
28
|
+
|
|
29
|
+
# Queue state: explicit list vs. all-queues vs. unset (defer to config).
|
|
30
|
+
# `queues_set_by_user` toggles to true once any CLI/env queue flag is seen.
|
|
31
|
+
queues = []
|
|
32
|
+
queues_set_by_user = false
|
|
33
|
+
all_queues = false
|
|
34
|
+
|
|
35
|
+
if ENV.key?("ZIZQ_QUEUES")
|
|
36
|
+
parsed = ENV["ZIZQ_QUEUES"].split(",").map(&:strip).reject(&:empty?)
|
|
37
|
+
queues = parsed
|
|
38
|
+
queues_set_by_user = true
|
|
28
39
|
end
|
|
29
40
|
|
|
30
41
|
# --- CLI flag parsing (overrides env var defaults) ---
|
|
31
42
|
|
|
32
43
|
parser = OptionParser.new do |opts|
|
|
33
|
-
opts.banner = "Usage: zizq-worker [OPTIONS]
|
|
44
|
+
opts.banner = "Usage: zizq-worker [OPTIONS] [ENTRYPOINT]"
|
|
34
45
|
|
|
35
46
|
opts.separator ""
|
|
36
|
-
opts.separator "Start a Zizq worker process.
|
|
37
|
-
opts.separator "
|
|
47
|
+
opts.separator "Start a Zizq worker process."
|
|
48
|
+
opts.separator ""
|
|
49
|
+
opts.separator "The ENTRYPOINT is a Ruby file that loads your application before the"
|
|
50
|
+
opts.separator "worker starts (so Zizq.configure runs and your job classes are loaded)."
|
|
51
|
+
opts.separator "Resolved in this order:"
|
|
52
|
+
opts.separator ""
|
|
53
|
+
opts.separator " 1. The ENTRYPOINT positional argument, if given."
|
|
54
|
+
opts.separator " 2. The ZIZQ_ENTRYPOINT environment variable, if set."
|
|
55
|
+
opts.separator " 3. config/environment.rb in the current directory, if it exists."
|
|
56
|
+
opts.separator " (This is the canonical Rails boot file, so Rails apps run with"
|
|
57
|
+
opts.separator " no entrypoint argument at all.)"
|
|
58
|
+
opts.separator ""
|
|
59
|
+
opts.separator "Configuration:"
|
|
60
|
+
opts.separator ""
|
|
61
|
+
opts.separator " Client config (url, format, TLS, logger) and worker defaults"
|
|
62
|
+
opts.separator " (queues, thread/fiber count, prefetch, etc.) belong in your"
|
|
63
|
+
opts.separator " Zizq.configure block inside the entrypoint, e.g.:"
|
|
38
64
|
opts.separator ""
|
|
39
|
-
opts.separator "
|
|
40
|
-
opts.separator "
|
|
65
|
+
opts.separator " Zizq.configure do |c|"
|
|
66
|
+
opts.separator " c.url = \"https://...\""
|
|
67
|
+
opts.separator " c.worker.queues = [\"emails\", \"webhooks\"]"
|
|
68
|
+
opts.separator " c.worker.fiber_count = 25"
|
|
69
|
+
opts.separator " end"
|
|
70
|
+
opts.separator ""
|
|
71
|
+
opts.separator " CLI flags and env vars below override whatever is configured there."
|
|
41
72
|
opts.separator ""
|
|
42
73
|
opts.separator "Options:"
|
|
43
74
|
|
|
44
|
-
opts.on("-t", "--threads N", Integer, "Number of worker threads (default: #{Zizq::Worker::DEFAULT_THREADS}, env: ZIZQ_THREADS)") do |n|
|
|
75
|
+
opts.on("-t", "--threads N", Integer, "Number of worker threads (fallback default: #{Zizq::Worker::DEFAULT_THREADS}, env: ZIZQ_THREADS)") do |n|
|
|
45
76
|
thread_count = n
|
|
46
77
|
end
|
|
47
78
|
|
|
48
|
-
opts.on("-f", "--fibers N", Integer, "Number of fibers per thread (default: #{Zizq::Worker::DEFAULT_FIBERS}, env: ZIZQ_FIBERS)") do |n|
|
|
79
|
+
opts.on("-f", "--fibers N", Integer, "Number of fibers per thread (fallback default: #{Zizq::Worker::DEFAULT_FIBERS}, env: ZIZQ_FIBERS)") do |n|
|
|
49
80
|
fiber_count = n
|
|
50
81
|
end
|
|
51
82
|
|
|
52
|
-
opts.on("-p", "--prefetch N", Integer, "Prefetch count (default: 2*threads*fibers, env: ZIZQ_PREFETCH)") do |n|
|
|
83
|
+
opts.on("-p", "--prefetch N", Integer, "Prefetch count (fallback default: 2*threads*fibers, env: ZIZQ_PREFETCH)") do |n|
|
|
53
84
|
prefetch = n
|
|
54
85
|
end
|
|
55
86
|
|
|
56
87
|
queues_from_cli = false
|
|
57
88
|
opts.on("-q", "--queue QUEUE", "Queue to process (repeatable or comma-separated, env: ZIZQ_QUEUES)") do |q|
|
|
58
|
-
# First
|
|
89
|
+
# First CLI `-q` replaces the env var default; subsequent ones
|
|
90
|
+
# accumulate. `queues_from_cli` distinguishes that from
|
|
91
|
+
# `queues_set_by_user` (which also tracks env-var input).
|
|
59
92
|
unless queues_from_cli
|
|
60
93
|
queues = []
|
|
61
94
|
queues_from_cli = true
|
|
62
95
|
end
|
|
96
|
+
queues_set_by_user = true
|
|
63
97
|
queues.concat(q.split(",").map(&:strip).reject(&:empty?))
|
|
64
98
|
end
|
|
65
99
|
|
|
100
|
+
opts.on("--all-queues", "Override any configured queues to process all queues (mutually exclusive with -q)") do
|
|
101
|
+
all_queues = true
|
|
102
|
+
end
|
|
103
|
+
|
|
66
104
|
opts.on("--shutdown-deadline N", Float, "Graceful shutdown deadline in seconds before escalating to kill (default: #{DEFAULT_SHUTDOWN_DEADLINE}, env: ZIZQ_SHUTDOWN_DEADLINE)") do |n|
|
|
67
105
|
shutdown_deadline = n
|
|
68
106
|
end
|
|
@@ -100,22 +138,38 @@ end
|
|
|
100
138
|
|
|
101
139
|
# --- Validate options ---
|
|
102
140
|
|
|
103
|
-
if thread_count < 1
|
|
141
|
+
if thread_count && thread_count < 1
|
|
104
142
|
warn "Error: --threads must be at least 1 (got #{thread_count})"
|
|
105
143
|
exit 1
|
|
106
144
|
end
|
|
107
145
|
|
|
108
|
-
if fiber_count < 1
|
|
146
|
+
if fiber_count && fiber_count < 1
|
|
109
147
|
warn "Error: --fibers must be at least 1 (got #{fiber_count})"
|
|
110
148
|
exit 1
|
|
111
149
|
end
|
|
112
150
|
|
|
113
|
-
|
|
151
|
+
if all_queues && queues_set_by_user
|
|
152
|
+
warn "Error: --all-queues and --queue (or ZIZQ_QUEUES) are mutually exclusive."
|
|
153
|
+
exit 1
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# --- Resolve and load entrypoint ---
|
|
157
|
+
#
|
|
158
|
+
# Precedence:
|
|
159
|
+
# 1. CLI argument: `zizq-worker path/to/entrypoint.rb`
|
|
160
|
+
# 2. ZIZQ_ENTRYPOINT env var
|
|
161
|
+
# 3. Auto-detect: `config/environment.rb` (Rails apps)
|
|
114
162
|
|
|
115
|
-
entrypoint = ARGV[0]
|
|
163
|
+
entrypoint = ARGV[0] || ENV["ZIZQ_ENTRYPOINT"] || (
|
|
164
|
+
File.file?("config/environment.rb") ? "config/environment.rb" : nil
|
|
165
|
+
)
|
|
116
166
|
|
|
117
167
|
if entrypoint.nil?
|
|
118
|
-
warn "Error:
|
|
168
|
+
warn "Error: no entrypoint found."
|
|
169
|
+
warn ""
|
|
170
|
+
warn "Specify one as a CLI argument or via the ZIZQ_ENTRYPOINT env var."
|
|
171
|
+
warn "Rails apps are detected automatically via the presence of"
|
|
172
|
+
warn "config/environment.rb in the current directory."
|
|
119
173
|
warn ""
|
|
120
174
|
warn parser.help
|
|
121
175
|
exit 1
|
|
@@ -128,17 +182,33 @@ end
|
|
|
128
182
|
|
|
129
183
|
require File.expand_path(entrypoint)
|
|
130
184
|
|
|
131
|
-
# ---
|
|
185
|
+
# --- Resolve queues ---
|
|
186
|
+
#
|
|
187
|
+
# --all-queues -> [] (explicit "all queues" override)
|
|
188
|
+
# -q / ZIZQ_QUEUES set -> the parsed list
|
|
189
|
+
# neither -> nil (defer to Zizq.configure → Worker default)
|
|
190
|
+
|
|
191
|
+
queues_value =
|
|
192
|
+
if all_queues
|
|
193
|
+
[]
|
|
194
|
+
elsif queues_set_by_user
|
|
195
|
+
queues
|
|
196
|
+
end
|
|
132
197
|
|
|
133
|
-
worker
|
|
198
|
+
# --- Start the worker ---
|
|
199
|
+
#
|
|
200
|
+
# `.compact` drops any unset kwarg so `Zizq::Worker#initialize`'s
|
|
201
|
+
# fallback chain (kwarg -> Zizq.configuration.worker -> DEFAULT_*)
|
|
202
|
+
# applies for whichever values weren't given on the CLI / via env.
|
|
203
|
+
worker = Zizq::Worker.new(**{
|
|
134
204
|
thread_count:,
|
|
135
205
|
fiber_count:,
|
|
136
206
|
prefetch:,
|
|
137
|
-
queues
|
|
207
|
+
queues: queues_value,
|
|
138
208
|
retry_min_wait:,
|
|
139
209
|
retry_max_wait:,
|
|
140
210
|
retry_multiplier:,
|
|
141
|
-
)
|
|
211
|
+
}.compact)
|
|
142
212
|
|
|
143
213
|
# `Zizq::Worker#stop` is patient (waits forever for in-flight jobs and
|
|
144
214
|
# acks to drain). We enforce the shutdown deadline at the CLI level: the
|
|
@@ -154,7 +224,10 @@ stopping = false
|
|
|
154
224
|
%w[INT TERM].each do |signal|
|
|
155
225
|
Signal.trap(signal) do
|
|
156
226
|
if stopping
|
|
157
|
-
exit(
|
|
227
|
+
# Second signal: hard exit. `exit!` (not `exit`) so SystemExit
|
|
228
|
+
# terminates the process from any thread context, including
|
|
229
|
+
# the signal trap.
|
|
230
|
+
exit!(1)
|
|
158
231
|
else
|
|
159
232
|
worker.stop
|
|
160
233
|
stopping = true
|
|
@@ -164,7 +237,10 @@ stopping = false
|
|
|
164
237
|
worker.logger.warn do
|
|
165
238
|
"Worker did not stop within #{shutdown_deadline}s, killing..."
|
|
166
239
|
end
|
|
167
|
-
exit
|
|
240
|
+
# `exit!` rather than `exit`: this runs in a watchdog thread,
|
|
241
|
+
# and `exit` would only raise SystemExit in *this* thread,
|
|
242
|
+
# leaving main (joining the hung worker thread) untouched.
|
|
243
|
+
exit!(1)
|
|
168
244
|
end
|
|
169
245
|
end
|
|
170
246
|
end
|
data/lib/zizq/configuration.rb
CHANGED
|
@@ -29,19 +29,6 @@ module Zizq
|
|
|
29
29
|
# Logger instance to which to write log messages.
|
|
30
30
|
attr_accessor :logger #: Logger
|
|
31
31
|
|
|
32
|
-
# TLS options for connecting to the server over HTTPS.
|
|
33
|
-
#
|
|
34
|
-
# All values may be PEM-encoded strings or file paths.
|
|
35
|
-
#
|
|
36
|
-
# {
|
|
37
|
-
# ca: "path/to/ca-cert.pem", # CA certificate for server verification
|
|
38
|
-
# client_cert: "path/to/client-cert.pem", # Client certificate for mTLS
|
|
39
|
-
# client_key: "path/to/client-key.pem", # Client private key for mTLS
|
|
40
|
-
# }
|
|
41
|
-
#
|
|
42
|
-
# Note: Mutual TLS support requires a Zizq Pro license on the server.
|
|
43
|
-
attr_accessor :tls #: Zizq::tls_options?
|
|
44
|
-
|
|
45
32
|
# Per-operation socket I/O timeout (seconds) for regular API calls
|
|
46
33
|
# (enqueue, queries, mutations). Each socket read/write is bounded
|
|
47
34
|
# by this value. A request whose handshake or any single read exceeds
|
|
@@ -76,12 +63,79 @@ module Zizq
|
|
|
76
63
|
@format = :msgpack
|
|
77
64
|
@logger = Logger.new($stdout, level: Logger::INFO)
|
|
78
65
|
@tls = nil
|
|
66
|
+
@worker = nil
|
|
79
67
|
@read_timeout = 30
|
|
80
68
|
@stream_idle_timeout = 30
|
|
81
69
|
@enqueue_middleware = Middleware::Chain.new(Identity.new)
|
|
82
70
|
@dequeue_middleware = Middleware::Chain.new(Zizq::Job)
|
|
83
71
|
end
|
|
84
72
|
|
|
73
|
+
# TLS settings for connecting to the server over HTTPS.
|
|
74
|
+
#
|
|
75
|
+
# Configure via the `c.tls` accessors inside a `Zizq.configure`
|
|
76
|
+
# block:
|
|
77
|
+
#
|
|
78
|
+
# Zizq.configure do |c|
|
|
79
|
+
# c.tls.ca = "/path/to/server-ca-cert.pem"
|
|
80
|
+
# c.tls.client_cert = "/path/to/client-cert.pem"
|
|
81
|
+
# c.tls.client_key = "/path/to/client-key.pem"
|
|
82
|
+
# end
|
|
83
|
+
#
|
|
84
|
+
# All values may be PEM-encoded strings or file paths. Set
|
|
85
|
+
# `c.tls = nil` to explicitly disable TLS.
|
|
86
|
+
#
|
|
87
|
+
# Note: Mutual TLS support requires a Zizq Pro license on the
|
|
88
|
+
# server.
|
|
89
|
+
def tls #: () -> TlsConfiguration
|
|
90
|
+
@tls ||= TlsConfiguration.new
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def tls=(value) #: ((Hash[Symbol, String?] | TlsConfiguration)?) -> void
|
|
94
|
+
case value
|
|
95
|
+
when nil
|
|
96
|
+
@tls = nil
|
|
97
|
+
when TlsConfiguration
|
|
98
|
+
@tls = value
|
|
99
|
+
when Hash
|
|
100
|
+
@tls = TlsConfiguration.new(**value)
|
|
101
|
+
else
|
|
102
|
+
raise ArgumentError,
|
|
103
|
+
"Zizq.configure: tls= expects a Hash, Zizq::TlsConfiguration, or nil " \
|
|
104
|
+
"(got #{value.class})"
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Defaults for `Zizq::Worker` instances. Apps populate this in
|
|
109
|
+
# their `Zizq.configure` block:
|
|
110
|
+
#
|
|
111
|
+
# Zizq.configure do |c|
|
|
112
|
+
# c.worker.queues = ["emails"]
|
|
113
|
+
# c.worker.fiber_count = 25
|
|
114
|
+
# end
|
|
115
|
+
#
|
|
116
|
+
# Anything left unset here falls through to the Worker's
|
|
117
|
+
# hardcoded defaults; anything explicitly passed to `Worker.new`
|
|
118
|
+
# (or set via `zizq-worker` CLI flags / env vars) overrides
|
|
119
|
+
# whatever is configured here.
|
|
120
|
+
def worker #: () -> WorkerConfiguration
|
|
121
|
+
@worker ||= WorkerConfiguration.new
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def worker=(value) #: ((Hash[Symbol, untyped] | WorkerConfiguration)?) -> void
|
|
125
|
+
case value
|
|
126
|
+
when nil
|
|
127
|
+
@worker = nil
|
|
128
|
+
when WorkerConfiguration
|
|
129
|
+
@worker = value
|
|
130
|
+
when Hash
|
|
131
|
+
@worker = WorkerConfiguration.new(**value)
|
|
132
|
+
else
|
|
133
|
+
raise ArgumentError,
|
|
134
|
+
"Zizq.configure: worker= expects a Hash, Zizq::WorkerConfiguration, or nil " \
|
|
135
|
+
"(got #{value.class})"
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
85
139
|
# The job dispatcher.
|
|
86
140
|
# This is the terminal of the dequeue middleware chain.
|
|
87
141
|
# Defaults to `Zizq::Job` which finds and executes jobs written by mixing
|
|
@@ -130,21 +184,22 @@ module Zizq
|
|
|
130
184
|
def ssl_context #: () -> OpenSSL::SSL::SSLContext?
|
|
131
185
|
tls = @tls
|
|
132
186
|
return nil unless tls
|
|
187
|
+
return nil if tls.to_h.values.all?(&:nil?)
|
|
133
188
|
|
|
134
189
|
ctx = OpenSSL::SSL::SSLContext.new
|
|
135
190
|
|
|
136
|
-
if (ca = tls
|
|
191
|
+
if (ca = tls.ca)
|
|
137
192
|
store = OpenSSL::X509::Store.new
|
|
138
193
|
store.add_cert(load_cert(ca))
|
|
139
194
|
ctx.cert_store = store
|
|
140
195
|
ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
|
141
196
|
end
|
|
142
197
|
|
|
143
|
-
if (client_cert = tls
|
|
198
|
+
if (client_cert = tls.client_cert)
|
|
144
199
|
ctx.cert = load_cert(client_cert)
|
|
145
200
|
end
|
|
146
201
|
|
|
147
|
-
if (client_key = tls
|
|
202
|
+
if (client_key = tls.client_key)
|
|
148
203
|
ctx.key = load_key(client_key)
|
|
149
204
|
end
|
|
150
205
|
|
|
@@ -161,14 +216,13 @@ module Zizq
|
|
|
161
216
|
|
|
162
217
|
private
|
|
163
218
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
raise ArgumentError, "Zizq.configure: tls[:client_key] is required when tls[:client_cert] is set"
|
|
219
|
+
def validate_tls!(tls) #: (TlsConfiguration) -> void
|
|
220
|
+
if tls.client_cert && !tls.client_key
|
|
221
|
+
raise ArgumentError, "Zizq.configure: tls.client_key is required when tls.client_cert is set"
|
|
168
222
|
end
|
|
169
223
|
|
|
170
|
-
if tls
|
|
171
|
-
raise ArgumentError, "Zizq.configure: tls
|
|
224
|
+
if tls.client_key && !tls.client_cert
|
|
225
|
+
raise ArgumentError, "Zizq.configure: tls.client_cert is required when tls.client_key is set"
|
|
172
226
|
end
|
|
173
227
|
end
|
|
174
228
|
|
|
@@ -0,0 +1,27 @@
|
|
|
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
|
+
module Zizq
|
|
8
|
+
# TLS settings for connecting to the Zizq server over HTTPS.
|
|
9
|
+
#
|
|
10
|
+
# Set inside a `Zizq.configure` block via the `c.tls` accessors:
|
|
11
|
+
#
|
|
12
|
+
# Zizq.configure do |c|
|
|
13
|
+
# c.tls.ca = "/path/to/ca-cert.pem"
|
|
14
|
+
# c.tls.client_cert = "/path/to/client-cert.pem"
|
|
15
|
+
# c.tls.client_key = "/path/to/client-key.pem"
|
|
16
|
+
# end
|
|
17
|
+
#
|
|
18
|
+
# All values may be PEM-encoded strings or file paths.
|
|
19
|
+
#
|
|
20
|
+
# Note: Mutual TLS support requires a Zizq Pro license on the server.
|
|
21
|
+
TlsConfiguration = Struct.new(
|
|
22
|
+
:ca, #: String?
|
|
23
|
+
:client_cert, #: String?
|
|
24
|
+
:client_key, #: String?
|
|
25
|
+
keyword_init: true
|
|
26
|
+
)
|
|
27
|
+
end
|
data/lib/zizq/version.rb
CHANGED
data/lib/zizq/worker.rb
CHANGED
|
@@ -15,7 +15,7 @@ module Zizq
|
|
|
15
15
|
#
|
|
16
16
|
# Total concurrency is calculated as `thread_count * fiber_count`.
|
|
17
17
|
class Worker
|
|
18
|
-
DEFAULT_THREADS =
|
|
18
|
+
DEFAULT_THREADS = 1 #: Integer
|
|
19
19
|
DEFAULT_FIBERS = 1 #: Integer
|
|
20
20
|
DEFAULT_RETRY_MIN_WAIT = 1
|
|
21
21
|
DEFAULT_RETRY_MAX_WAIT = 30
|
|
@@ -50,11 +50,6 @@ module Zizq
|
|
|
50
50
|
# pipeline full while ack round-trips are in flight.
|
|
51
51
|
attr_reader :prefetch #: Integer
|
|
52
52
|
|
|
53
|
-
# Proc to derive a worker ID string for each thread and fiber.
|
|
54
|
-
#
|
|
55
|
-
# When not present, the Zizq server assigns a random worker ID.
|
|
56
|
-
attr_reader :worker_id_proc #: (^(Integer, Integer) -> String?)?
|
|
57
|
-
|
|
58
53
|
# An instance of a Logger to be used for worker logging.
|
|
59
54
|
attr_reader :logger #: Logger
|
|
60
55
|
|
|
@@ -66,45 +61,55 @@ module Zizq
|
|
|
66
61
|
# their own `Zizq::Middleware::Chain` if middleware needs to be applied.
|
|
67
62
|
attr_reader :dispatcher #: ^(Resources::Job) -> void
|
|
68
63
|
|
|
69
|
-
#
|
|
70
|
-
#
|
|
71
|
-
#
|
|
64
|
+
# All keyword arguments default to `nil` and follow a three-level
|
|
65
|
+
# fallback chain:
|
|
66
|
+
#
|
|
67
|
+
# 1. Explicit kwarg passed to `Worker.new`.
|
|
68
|
+
# 2. `Zizq.configuration.worker.<field>` set in the app's
|
|
69
|
+
# `Zizq.configure` block.
|
|
70
|
+
# 3. The Worker's hardcoded `DEFAULT_*` constants.
|
|
71
|
+
#
|
|
72
|
+
# @rbs queues: Array[String]?
|
|
73
|
+
# @rbs thread_count: Integer?
|
|
74
|
+
# @rbs fiber_count: Integer?
|
|
72
75
|
# @rbs prefetch: Integer?
|
|
73
|
-
# @rbs retry_min_wait: (Float | Integer)
|
|
74
|
-
# @rbs retry_max_wait: (Float | Integer)
|
|
75
|
-
# @rbs retry_multiplier: (Float | Integer)
|
|
76
|
-
# @rbs worker_id: (^(Integer, Integer) -> String?)?
|
|
76
|
+
# @rbs retry_min_wait: (Float | Integer)?
|
|
77
|
+
# @rbs retry_max_wait: (Float | Integer)?
|
|
78
|
+
# @rbs retry_multiplier: (Float | Integer)?
|
|
77
79
|
# @rbs logger: Logger?
|
|
78
80
|
# @rbs dispatcher: (^(Resources::Job) -> void)?
|
|
79
81
|
# @rbs return: void
|
|
80
82
|
def initialize(
|
|
81
|
-
queues:
|
|
82
|
-
thread_count:
|
|
83
|
-
fiber_count:
|
|
83
|
+
queues: nil,
|
|
84
|
+
thread_count: nil,
|
|
85
|
+
fiber_count: nil,
|
|
84
86
|
prefetch: nil,
|
|
85
|
-
retry_min_wait:
|
|
86
|
-
retry_max_wait:
|
|
87
|
-
retry_multiplier:
|
|
88
|
-
worker_id: nil,
|
|
87
|
+
retry_min_wait: nil,
|
|
88
|
+
retry_max_wait: nil,
|
|
89
|
+
retry_multiplier: nil,
|
|
89
90
|
logger: nil,
|
|
90
91
|
dispatcher: nil
|
|
91
92
|
)
|
|
92
|
-
raise ArgumentError, "thread_count must be at least 1 (got #{thread_count})" if thread_count < 1
|
|
93
|
-
raise ArgumentError, "fiber_count must be at least 1 (got #{fiber_count})" if fiber_count < 1
|
|
94
|
-
|
|
95
93
|
Zizq.configuration.validate!
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
@
|
|
99
|
-
@
|
|
100
|
-
@
|
|
101
|
-
@
|
|
102
|
-
@
|
|
103
|
-
@
|
|
104
|
-
@
|
|
94
|
+
config = Zizq.configuration.worker
|
|
95
|
+
|
|
96
|
+
@queues = queues || config.queues || []
|
|
97
|
+
@thread_count = thread_count || config.thread_count || DEFAULT_THREADS
|
|
98
|
+
@fiber_count = fiber_count || config.fiber_count || DEFAULT_FIBERS
|
|
99
|
+
@prefetch = prefetch || config.prefetch || @thread_count * @fiber_count * 2
|
|
100
|
+
@retry_min_wait = retry_min_wait || config.retry_min_wait || DEFAULT_RETRY_MIN_WAIT
|
|
101
|
+
@retry_max_wait = retry_max_wait || config.retry_max_wait || DEFAULT_RETRY_MAX_WAIT
|
|
102
|
+
@retry_multiplier = retry_multiplier || config.retry_multiplier || DEFAULT_RETRY_MULTIPLIER
|
|
105
103
|
@logger = logger || Zizq.configuration.logger
|
|
106
104
|
@dispatcher = dispatcher || Zizq.configuration.dequeue_middleware
|
|
107
105
|
|
|
106
|
+
if @thread_count < 1
|
|
107
|
+
raise ArgumentError, "thread_count must be at least 1 (got #{@thread_count})"
|
|
108
|
+
end
|
|
109
|
+
if @fiber_count < 1
|
|
110
|
+
raise ArgumentError, "fiber_count must be at least 1 (got #{@fiber_count})"
|
|
111
|
+
end
|
|
112
|
+
|
|
108
113
|
reset_runtime_state
|
|
109
114
|
end
|
|
110
115
|
|
|
@@ -360,14 +365,12 @@ module Zizq
|
|
|
360
365
|
format("Worker %d:%d started", thread_idx, fiber_idx)
|
|
361
366
|
end
|
|
362
367
|
|
|
363
|
-
wid = resolve_worker_id(thread_idx, fiber_idx)
|
|
364
|
-
|
|
365
368
|
loop do
|
|
366
369
|
# pop returns nil when queue is closed and empty
|
|
367
370
|
job = @dispatch_queue.pop
|
|
368
371
|
break if job.nil?
|
|
369
372
|
|
|
370
|
-
dispatch(job
|
|
373
|
+
dispatch(job)
|
|
371
374
|
end
|
|
372
375
|
|
|
373
376
|
logger.info do
|
|
@@ -392,7 +395,7 @@ module Zizq
|
|
|
392
395
|
#
|
|
393
396
|
# Delegates to the configured dispatcher (default: `Zizq::Job.dispatch`)
|
|
394
397
|
# and reports success or failure.
|
|
395
|
-
def dispatch(job
|
|
398
|
+
def dispatch(job) #: (Resources::Job) -> void
|
|
396
399
|
job_id, job_type = job.id, job.type
|
|
397
400
|
|
|
398
401
|
begin
|
|
@@ -460,8 +463,5 @@ module Zizq
|
|
|
460
463
|
))
|
|
461
464
|
end
|
|
462
465
|
|
|
463
|
-
def resolve_worker_id(thread_idx, fiber_idx) #: (Integer, Integer) -> String?
|
|
464
|
-
worker_id_proc&.call(thread_idx, fiber_idx)
|
|
465
|
-
end
|
|
466
466
|
end
|
|
467
467
|
end
|
|
@@ -0,0 +1,48 @@
|
|
|
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
|
+
module Zizq
|
|
8
|
+
# Defaults for `Zizq::Worker` instances. Accessed via
|
|
9
|
+
# `Zizq.configuration.worker` and typically populated inside an
|
|
10
|
+
# application's `Zizq.configure` block:
|
|
11
|
+
#
|
|
12
|
+
# Zizq.configure do |c|
|
|
13
|
+
# c.url = "https://..."
|
|
14
|
+
# c.worker.queues = ["emails", "webhooks"]
|
|
15
|
+
# c.worker.thread_count = 1
|
|
16
|
+
# c.worker.fiber_count = 25
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# Every field defaults to `nil`, meaning "use the Worker's own
|
|
20
|
+
# hardcoded default." Anything explicitly passed to `Worker.new` —
|
|
21
|
+
# or set via CLI flag / env var when launching `zizq-worker` —
|
|
22
|
+
# overrides whatever is set here.
|
|
23
|
+
#
|
|
24
|
+
# See `Zizq::Worker#initialize` for the full resolution order
|
|
25
|
+
# (explicit kwarg → Zizq.configuration.worker → `Worker::DEFAULT_*`).
|
|
26
|
+
#
|
|
27
|
+
# Fields:
|
|
28
|
+
#
|
|
29
|
+
# * `queues` — Queues to consume. `[]` means all queues.
|
|
30
|
+
# * `thread_count` — Number of worker threads.
|
|
31
|
+
# * `fiber_count` — Number of fibers per worker thread.
|
|
32
|
+
# * `prefetch` — Server-side prefetch limit. Defaults to
|
|
33
|
+
# `2 * threads * fibers`.
|
|
34
|
+
# * `retry_min_wait` — Minimum reconnect backoff in seconds.
|
|
35
|
+
# * `retry_max_wait` — Maximum reconnect backoff in seconds.
|
|
36
|
+
# * `retry_multiplier` — Multiplicative backoff factor between
|
|
37
|
+
# reconnect attempts.
|
|
38
|
+
WorkerConfiguration = Struct.new(
|
|
39
|
+
:queues, #: Array[String]?
|
|
40
|
+
:thread_count, #: Integer?
|
|
41
|
+
:fiber_count, #: Integer?
|
|
42
|
+
:prefetch, #: Integer?
|
|
43
|
+
:retry_min_wait, #: (Float | Integer)?
|
|
44
|
+
:retry_max_wait, #: (Float | Integer)?
|
|
45
|
+
:retry_multiplier, #: (Float | Integer)?
|
|
46
|
+
keyword_init: true
|
|
47
|
+
)
|
|
48
|
+
end
|
data/lib/zizq.rb
CHANGED
|
@@ -29,7 +29,9 @@ module Zizq
|
|
|
29
29
|
autoload :Lifecycle, "zizq/lifecycle"
|
|
30
30
|
autoload :Query, "zizq/query"
|
|
31
31
|
autoload :Resources, "zizq/resources"
|
|
32
|
+
autoload :TlsConfiguration, "zizq/tls_configuration"
|
|
32
33
|
autoload :Worker, "zizq/worker"
|
|
34
|
+
autoload :WorkerConfiguration, "zizq/worker_configuration"
|
|
33
35
|
|
|
34
36
|
# Sentinel indicating a field should not be included in the request.
|
|
35
37
|
# Used as the default for update parameters.
|
|
@@ -22,19 +22,6 @@ module Zizq
|
|
|
22
22
|
# Logger instance to which to write log messages.
|
|
23
23
|
attr_accessor logger: Logger
|
|
24
24
|
|
|
25
|
-
# TLS options for connecting to the server over HTTPS.
|
|
26
|
-
#
|
|
27
|
-
# All values may be PEM-encoded strings or file paths.
|
|
28
|
-
#
|
|
29
|
-
# {
|
|
30
|
-
# ca: "path/to/ca-cert.pem", # CA certificate for server verification
|
|
31
|
-
# client_cert: "path/to/client-cert.pem", # Client certificate for mTLS
|
|
32
|
-
# client_key: "path/to/client-key.pem", # Client private key for mTLS
|
|
33
|
-
# }
|
|
34
|
-
#
|
|
35
|
-
# Note: Mutual TLS support requires a Zizq Pro license on the server.
|
|
36
|
-
attr_accessor tls: Zizq::tls_options?
|
|
37
|
-
|
|
38
25
|
# Per-operation socket I/O timeout (seconds) for regular API calls
|
|
39
26
|
# (enqueue, queries, mutations). Each socket read/write is bounded
|
|
40
27
|
# by this value. A request whose handshake or any single read exceeds
|
|
@@ -66,6 +53,42 @@ module Zizq
|
|
|
66
53
|
|
|
67
54
|
def initialize: () -> untyped
|
|
68
55
|
|
|
56
|
+
# TLS settings for connecting to the server over HTTPS.
|
|
57
|
+
#
|
|
58
|
+
# Configure via the `c.tls` accessors inside a `Zizq.configure`
|
|
59
|
+
# block:
|
|
60
|
+
#
|
|
61
|
+
# Zizq.configure do |c|
|
|
62
|
+
# c.tls.ca = "/path/to/server-ca-cert.pem"
|
|
63
|
+
# c.tls.client_cert = "/path/to/client-cert.pem"
|
|
64
|
+
# c.tls.client_key = "/path/to/client-key.pem"
|
|
65
|
+
# end
|
|
66
|
+
#
|
|
67
|
+
# All values may be PEM-encoded strings or file paths. Set
|
|
68
|
+
# `c.tls = nil` to explicitly disable TLS.
|
|
69
|
+
#
|
|
70
|
+
# Note: Mutual TLS support requires a Zizq Pro license on the
|
|
71
|
+
# server.
|
|
72
|
+
def tls: () -> untyped
|
|
73
|
+
|
|
74
|
+
def tls=: (untyped value) -> untyped
|
|
75
|
+
|
|
76
|
+
# Defaults for `Zizq::Worker` instances. Apps populate this in
|
|
77
|
+
# their `Zizq.configure` block:
|
|
78
|
+
#
|
|
79
|
+
# Zizq.configure do |c|
|
|
80
|
+
# c.worker.queues = ["emails"]
|
|
81
|
+
# c.worker.fiber_count = 25
|
|
82
|
+
# end
|
|
83
|
+
#
|
|
84
|
+
# Anything left unset here falls through to the Worker's
|
|
85
|
+
# hardcoded defaults; anything explicitly passed to `Worker.new`
|
|
86
|
+
# (or set via `zizq-worker` CLI flags / env vars) overrides
|
|
87
|
+
# whatever is configured here.
|
|
88
|
+
def worker: () -> untyped
|
|
89
|
+
|
|
90
|
+
def worker=: (untyped value) -> untyped
|
|
91
|
+
|
|
69
92
|
# The job dispatcher.
|
|
70
93
|
# This is the terminal of the dequeue middleware chain.
|
|
71
94
|
# Defaults to `Zizq::Job` which finds and executes jobs written by mixing
|
|
@@ -100,8 +123,7 @@ module Zizq
|
|
|
100
123
|
|
|
101
124
|
private
|
|
102
125
|
|
|
103
|
-
|
|
104
|
-
def validate_tls!: (Zizq::tls_options tls) -> untyped
|
|
126
|
+
def validate_tls!: (untyped tls) -> untyped
|
|
105
127
|
|
|
106
128
|
# Load a certificate from a PEM string or file path.
|
|
107
129
|
def load_cert: (untyped pem_or_path) -> untyped
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Generated from lib/zizq/tls_configuration.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Zizq
|
|
4
|
+
# TLS settings for connecting to the Zizq server over HTTPS.
|
|
5
|
+
#
|
|
6
|
+
# Set inside a `Zizq.configure` block via the `c.tls` accessors:
|
|
7
|
+
#
|
|
8
|
+
# Zizq.configure do |c|
|
|
9
|
+
# c.tls.ca = "/path/to/ca-cert.pem"
|
|
10
|
+
# c.tls.client_cert = "/path/to/client-cert.pem"
|
|
11
|
+
# c.tls.client_key = "/path/to/client-key.pem"
|
|
12
|
+
# end
|
|
13
|
+
#
|
|
14
|
+
# All values may be PEM-encoded strings or file paths.
|
|
15
|
+
#
|
|
16
|
+
# Note: Mutual TLS support requires a Zizq Pro license on the server.
|
|
17
|
+
class TlsConfiguration < Struct[String?]
|
|
18
|
+
attr_accessor ca(): String?
|
|
19
|
+
|
|
20
|
+
attr_accessor client_cert(): String?
|
|
21
|
+
|
|
22
|
+
attr_accessor client_key(): String?
|
|
23
|
+
|
|
24
|
+
def self.new: (?ca: String?, ?client_cert: String?, ?client_key: String?) -> instance
|
|
25
|
+
| ({ ?ca: String?, ?client_cert: String?, ?client_key: String? }) -> instance
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -46,11 +46,6 @@ module Zizq
|
|
|
46
46
|
# pipeline full while ack round-trips are in flight.
|
|
47
47
|
attr_reader prefetch: Integer
|
|
48
48
|
|
|
49
|
-
# Proc to derive a worker ID string for each thread and fiber.
|
|
50
|
-
#
|
|
51
|
-
# When not present, the Zizq server assigns a random worker ID.
|
|
52
|
-
attr_reader worker_id_proc: (^(Integer, Integer) -> String?)?
|
|
53
|
-
|
|
54
49
|
# An instance of a Logger to be used for worker logging.
|
|
55
50
|
attr_reader logger: Logger
|
|
56
51
|
|
|
@@ -62,18 +57,25 @@ module Zizq
|
|
|
62
57
|
# their own `Zizq::Middleware::Chain` if middleware needs to be applied.
|
|
63
58
|
attr_reader dispatcher: ^(Resources::Job) -> void
|
|
64
59
|
|
|
65
|
-
#
|
|
66
|
-
#
|
|
67
|
-
#
|
|
60
|
+
# All keyword arguments default to `nil` and follow a three-level
|
|
61
|
+
# fallback chain:
|
|
62
|
+
#
|
|
63
|
+
# 1. Explicit kwarg passed to `Worker.new`.
|
|
64
|
+
# 2. `Zizq.configuration.worker.<field>` set in the app's
|
|
65
|
+
# `Zizq.configure` block.
|
|
66
|
+
# 3. The Worker's hardcoded `DEFAULT_*` constants.
|
|
67
|
+
#
|
|
68
|
+
# @rbs queues: Array[String]?
|
|
69
|
+
# @rbs thread_count: Integer?
|
|
70
|
+
# @rbs fiber_count: Integer?
|
|
68
71
|
# @rbs prefetch: Integer?
|
|
69
|
-
# @rbs retry_min_wait: (Float | Integer)
|
|
70
|
-
# @rbs retry_max_wait: (Float | Integer)
|
|
71
|
-
# @rbs retry_multiplier: (Float | Integer)
|
|
72
|
-
# @rbs worker_id: (^(Integer, Integer) -> String?)?
|
|
72
|
+
# @rbs retry_min_wait: (Float | Integer)?
|
|
73
|
+
# @rbs retry_max_wait: (Float | Integer)?
|
|
74
|
+
# @rbs retry_multiplier: (Float | Integer)?
|
|
73
75
|
# @rbs logger: Logger?
|
|
74
76
|
# @rbs dispatcher: (^(Resources::Job) -> void)?
|
|
75
77
|
# @rbs return: void
|
|
76
|
-
def initialize: (?queues: Array[String]
|
|
78
|
+
def initialize: (?queues: Array[String]?, ?thread_count: Integer?, ?fiber_count: Integer?, ?prefetch: Integer?, ?retry_min_wait: (Float | Integer)?, ?retry_max_wait: (Float | Integer)?, ?retry_multiplier: (Float | Integer)?, ?logger: Logger?, ?dispatcher: (^(Resources::Job) -> void)?) -> void
|
|
77
79
|
|
|
78
80
|
# Request a graceful shutdown.
|
|
79
81
|
#
|
|
@@ -136,7 +138,7 @@ module Zizq
|
|
|
136
138
|
#
|
|
137
139
|
# Delegates to the configured dispatcher (default: `Zizq::Job.dispatch`)
|
|
138
140
|
# and reports success or failure.
|
|
139
|
-
def dispatch: (untyped job
|
|
141
|
+
def dispatch: (untyped job) -> untyped
|
|
140
142
|
|
|
141
143
|
# @rbs job_id: String
|
|
142
144
|
# @rbs return: void
|
|
@@ -146,7 +148,5 @@ module Zizq
|
|
|
146
148
|
# @rbs error: Exception
|
|
147
149
|
# @rbs return: void
|
|
148
150
|
def push_nack: (String job_id, Exception error) -> void
|
|
149
|
-
|
|
150
|
-
def resolve_worker_id: (untyped thread_idx, untyped fiber_idx) -> untyped
|
|
151
151
|
end
|
|
152
152
|
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Generated from lib/zizq/worker_configuration.rb with RBS::Inline
|
|
2
|
+
|
|
3
|
+
module Zizq
|
|
4
|
+
# Defaults for `Zizq::Worker` instances. Accessed via
|
|
5
|
+
# `Zizq.configuration.worker` and typically populated inside an
|
|
6
|
+
# application's `Zizq.configure` block:
|
|
7
|
+
#
|
|
8
|
+
# Zizq.configure do |c|
|
|
9
|
+
# c.url = "https://..."
|
|
10
|
+
# c.worker.queues = ["emails", "webhooks"]
|
|
11
|
+
# c.worker.thread_count = 1
|
|
12
|
+
# c.worker.fiber_count = 25
|
|
13
|
+
# end
|
|
14
|
+
#
|
|
15
|
+
# Every field defaults to `nil`, meaning "use the Worker's own
|
|
16
|
+
# hardcoded default." Anything explicitly passed to `Worker.new` —
|
|
17
|
+
# or set via CLI flag / env var when launching `zizq-worker` —
|
|
18
|
+
# overrides whatever is set here.
|
|
19
|
+
#
|
|
20
|
+
# See `Zizq::Worker#initialize` for the full resolution order
|
|
21
|
+
# (explicit kwarg → Zizq.configuration.worker → `Worker::DEFAULT_*`).
|
|
22
|
+
#
|
|
23
|
+
# Fields:
|
|
24
|
+
#
|
|
25
|
+
# * `queues` — Queues to consume. `[]` means all queues.
|
|
26
|
+
# * `thread_count` — Number of worker threads.
|
|
27
|
+
# * `fiber_count` — Number of fibers per worker thread.
|
|
28
|
+
# * `prefetch` — Server-side prefetch limit. Defaults to
|
|
29
|
+
# `2 * threads * fibers`.
|
|
30
|
+
# * `retry_min_wait` — Minimum reconnect backoff in seconds.
|
|
31
|
+
# * `retry_max_wait` — Maximum reconnect backoff in seconds.
|
|
32
|
+
# * `retry_multiplier` — Multiplicative backoff factor between
|
|
33
|
+
# reconnect attempts.
|
|
34
|
+
class WorkerConfiguration < Struct[Array[String]? | Integer? | (Float | Integer)?]
|
|
35
|
+
attr_accessor queues(): Array[String]?
|
|
36
|
+
|
|
37
|
+
attr_accessor thread_count(): Integer?
|
|
38
|
+
|
|
39
|
+
attr_accessor fiber_count(): Integer?
|
|
40
|
+
|
|
41
|
+
attr_accessor prefetch(): Integer?
|
|
42
|
+
|
|
43
|
+
attr_accessor retry_min_wait(): (Float | Integer)?
|
|
44
|
+
|
|
45
|
+
attr_accessor retry_max_wait(): (Float | Integer)?
|
|
46
|
+
|
|
47
|
+
attr_accessor retry_multiplier(): (Float | Integer)?
|
|
48
|
+
|
|
49
|
+
def self.new: (?queues: Array[String]?, ?thread_count: Integer?, ?fiber_count: Integer?, ?prefetch: Integer?, ?retry_min_wait: (Float | Integer)?, ?retry_max_wait: (Float | Integer)?, ?retry_multiplier: (Float | Integer)?) -> instance
|
|
50
|
+
| ({ ?queues: Array[String]?, ?thread_count: Integer?, ?fiber_count: Integer?, ?prefetch: Integer?, ?retry_min_wait: (Float | Integer)?, ?retry_max_wait: (Float | Integer)?, ?retry_multiplier: (Float | Integer)? }) -> instance
|
|
51
|
+
end
|
|
52
|
+
end
|
data/sig/zizq.rbs
CHANGED
|
@@ -67,7 +67,8 @@ module Zizq
|
|
|
67
67
|
?paused: bool?
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
# TLS options
|
|
70
|
+
# TLS options hash accepted by `Configuration#tls=` for back-compat.
|
|
71
|
+
# Values are PEM strings or file paths.
|
|
71
72
|
type tls_options = { ?ca: String, ?client_cert: String, ?client_key: String }
|
|
72
73
|
|
|
73
74
|
# Any object that can dispatch a job. Must respond to #call(job).
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: zizq
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Chris Corbyn <chris@zizq.io>
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-05-
|
|
11
|
+
date: 2026-05-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: async-http
|
|
@@ -100,8 +100,10 @@ files:
|
|
|
100
100
|
- lib/zizq/resources/job_template.rb
|
|
101
101
|
- lib/zizq/resources/page.rb
|
|
102
102
|
- lib/zizq/resources/resource.rb
|
|
103
|
+
- lib/zizq/tls_configuration.rb
|
|
103
104
|
- lib/zizq/version.rb
|
|
104
105
|
- lib/zizq/worker.rb
|
|
106
|
+
- lib/zizq/worker_configuration.rb
|
|
105
107
|
- sig/generated/zizq.rbs
|
|
106
108
|
- sig/generated/zizq/ack_processor.rbs
|
|
107
109
|
- sig/generated/zizq/active_job_config.rbs
|
|
@@ -131,8 +133,10 @@ files:
|
|
|
131
133
|
- sig/generated/zizq/resources/job_template.rbs
|
|
132
134
|
- sig/generated/zizq/resources/page.rbs
|
|
133
135
|
- sig/generated/zizq/resources/resource.rbs
|
|
136
|
+
- sig/generated/zizq/tls_configuration.rbs
|
|
134
137
|
- sig/generated/zizq/version.rbs
|
|
135
138
|
- sig/generated/zizq/worker.rbs
|
|
139
|
+
- sig/generated/zizq/worker_configuration.rbs
|
|
136
140
|
- sig/zizq.rbs
|
|
137
141
|
homepage: https://zizq.io
|
|
138
142
|
licenses:
|