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
|
@@ -0,0 +1,241 @@
|
|
|
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
|
+
module Resources
|
|
9
|
+
# Provides a lazy Enumerator across all errors on a job following the
|
|
10
|
+
# cursor-based pagination.
|
|
11
|
+
class ErrorEnumerator
|
|
12
|
+
# Maximum page size the server can handle.
|
|
13
|
+
MAX_PAGE_SIZE = 2000 #: Integer
|
|
14
|
+
|
|
15
|
+
# @rbs skip
|
|
16
|
+
include Enumerable
|
|
17
|
+
|
|
18
|
+
# @rbs!
|
|
19
|
+
# include ::Enumerable[Zizq::Resources::ErrorRecord]
|
|
20
|
+
|
|
21
|
+
# Initialize the enumerator.
|
|
22
|
+
#
|
|
23
|
+
# @rbs id: String
|
|
24
|
+
# @rbs order: Zizq::sort_direction?
|
|
25
|
+
# @rbs limit: Integer?
|
|
26
|
+
# @rbs page_size: Integer?
|
|
27
|
+
# @rbs return: void
|
|
28
|
+
def initialize(id,
|
|
29
|
+
order: nil,
|
|
30
|
+
limit: nil,
|
|
31
|
+
page_size: nil)
|
|
32
|
+
@id = id
|
|
33
|
+
@order = order
|
|
34
|
+
@limit = limit
|
|
35
|
+
@page_size = page_size
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Set the page size for paginated iteration.
|
|
39
|
+
#
|
|
40
|
+
# When set, `each_page` fetches pages of this size, and `each` fetches
|
|
41
|
+
# errors in pages of this size.
|
|
42
|
+
#
|
|
43
|
+
# @rbs page_size: Integer?
|
|
44
|
+
# @rbs return: ErrorEnumerator
|
|
45
|
+
def in_pages_of(page_size)
|
|
46
|
+
rebuild(page_size:)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Set the sort order for iteration.
|
|
50
|
+
#
|
|
51
|
+
# @rbs order: Zizq::sort_direction?
|
|
52
|
+
# @rbs return: ErrorEnumerator
|
|
53
|
+
def order(order)
|
|
54
|
+
rebuild(order:)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Limit the total number of errors returned.
|
|
58
|
+
#
|
|
59
|
+
# This is a total limit, imposed across potentially multiple page fetches.
|
|
60
|
+
#
|
|
61
|
+
# @rbs limit: Integer?
|
|
62
|
+
# @rbs return: ErrorEnumerator
|
|
63
|
+
def limit(limit)
|
|
64
|
+
rebuild(limit:)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Reverse the sort order.
|
|
68
|
+
#
|
|
69
|
+
# Returns a new query with the opposite order. If no order was set,
|
|
70
|
+
# defaults to descending (the server default is ascending).
|
|
71
|
+
#
|
|
72
|
+
# @rbs return: ErrorEnumerator
|
|
73
|
+
def reverse_order
|
|
74
|
+
rebuild(order: @order == :desc ? :asc : :desc)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Returns true if there are no errors.
|
|
78
|
+
#
|
|
79
|
+
# Optimised: fetches a single error to check.
|
|
80
|
+
#
|
|
81
|
+
# @rbs return: bool
|
|
82
|
+
def empty?
|
|
83
|
+
first.nil?
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Returns true if there are any errors.
|
|
87
|
+
#
|
|
88
|
+
# Without a block, optimised to fetch a single error. With a block,
|
|
89
|
+
# falls back to Enumerable (tests each error against the block).
|
|
90
|
+
#
|
|
91
|
+
# @rbs &block: ?(Resources::ErrorRecord) -> bool
|
|
92
|
+
# @rbs return: bool
|
|
93
|
+
def any?
|
|
94
|
+
return super if block_given?
|
|
95
|
+
|
|
96
|
+
!first.nil?
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Returns true if there are no errors.
|
|
100
|
+
#
|
|
101
|
+
# Without a block, optimised to fetch a single error. With a block,
|
|
102
|
+
# falls back to Enumerable (tests each error against the block).
|
|
103
|
+
#
|
|
104
|
+
# @rbs &block: ?(Resources::ErrorRecord) -> bool
|
|
105
|
+
# @rbs return: bool
|
|
106
|
+
def none?
|
|
107
|
+
return super if block_given?
|
|
108
|
+
|
|
109
|
+
first.nil?
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Returns true if there is exactly one error.
|
|
113
|
+
#
|
|
114
|
+
# Without a block, optimised to fetch at most two errors. With a block,
|
|
115
|
+
# falls back to Enumerable.
|
|
116
|
+
#
|
|
117
|
+
# @rbs &block: ?(Resources::ErrorRecord) -> bool
|
|
118
|
+
# @rbs return: bool
|
|
119
|
+
def one?
|
|
120
|
+
return super if block_given?
|
|
121
|
+
|
|
122
|
+
limit(2).to_a.size == 1
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Iterate over errors in reverse order.
|
|
126
|
+
#
|
|
127
|
+
# Optimised: pushes the reverse ordering to the server instead of
|
|
128
|
+
# fetching all errors into memory and reversing.
|
|
129
|
+
#
|
|
130
|
+
# @rbs &block: ?(Resources::ErrorRecord) -> void
|
|
131
|
+
# @rbs return: ::Enumerator[Zizq::Resources::ErrorRecord, void]
|
|
132
|
+
def reverse_each(&block)
|
|
133
|
+
reverse_order.each(&block)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Return the first error, or nil if no errors.
|
|
137
|
+
#
|
|
138
|
+
# Optimised: fetches a single error from the server (`?limit=1`).
|
|
139
|
+
#
|
|
140
|
+
# @rbs return: Resources::ErrorRecord?
|
|
141
|
+
def first
|
|
142
|
+
limit(1).each.first
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Return the last error, or nil if no errors.
|
|
146
|
+
#
|
|
147
|
+
# Optimised: reverses the order and fetches a single error.
|
|
148
|
+
#
|
|
149
|
+
# @rbs return: Resources::ErrorRecord?
|
|
150
|
+
def last
|
|
151
|
+
reverse_order.first
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Return the first `n` errors.
|
|
155
|
+
#
|
|
156
|
+
# Optimised: sets the limit to `n` so the server only returns what's
|
|
157
|
+
# needed.
|
|
158
|
+
#
|
|
159
|
+
# @rbs n: Integer
|
|
160
|
+
# @rbs return: Array[Resources::ErrorRecord]
|
|
161
|
+
def take(n)
|
|
162
|
+
limit(n).to_a
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
# Iterate over errors, lazily paginating through results.
|
|
166
|
+
#
|
|
167
|
+
# Respects `limit` if set. Without a block, returns an `Enumerator`.
|
|
168
|
+
#
|
|
169
|
+
# @rbs &block: ?(Resources::ErrorRecord) -> void
|
|
170
|
+
# @rbs return: ::Enumerator[Zizq::Resources::ErrorRecord, void]
|
|
171
|
+
def each(&block)
|
|
172
|
+
enumerator = enum_for(:each)
|
|
173
|
+
|
|
174
|
+
if block_given?
|
|
175
|
+
remaining = @limit
|
|
176
|
+
|
|
177
|
+
each_page do |page|
|
|
178
|
+
page.errors.each do |error|
|
|
179
|
+
if remaining
|
|
180
|
+
break if remaining <= 0
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
yield error
|
|
184
|
+
|
|
185
|
+
remaining -= 1 if remaining
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
enumerator
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Iterate over pages of errors.
|
|
194
|
+
#
|
|
195
|
+
# Each page is a `Resources::ErrorPage`. Without a block, returns an
|
|
196
|
+
# `Enumerator`.
|
|
197
|
+
#
|
|
198
|
+
# If `limit` is set, terminates after the last page is reached that
|
|
199
|
+
# exceeds the limit, but does not truncate the page.
|
|
200
|
+
#
|
|
201
|
+
# @rbs &block: ?(Resources::ErrorPage) -> void
|
|
202
|
+
# @rbs return: ::Enumerator[Zizq::Resources::ErrorPage, void]
|
|
203
|
+
def each_page(&block)
|
|
204
|
+
enumerator = enum_for(:each_page)
|
|
205
|
+
|
|
206
|
+
if block_given?
|
|
207
|
+
page = Zizq.client.list_errors(
|
|
208
|
+
@id,
|
|
209
|
+
limit: [@page_size, @limit, (@page_size || @limit) && MAX_PAGE_SIZE].compact.min,
|
|
210
|
+
order: @order,
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
remaining = @limit
|
|
214
|
+
|
|
215
|
+
while page
|
|
216
|
+
yield page
|
|
217
|
+
|
|
218
|
+
if remaining
|
|
219
|
+
remaining -= page.errors.size
|
|
220
|
+
break if remaining <= 0
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
page = page.next_page
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
enumerator
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
private
|
|
231
|
+
|
|
232
|
+
# Build a new ErrorEnumerator with the given overrides, preserving all
|
|
233
|
+
# other fields.
|
|
234
|
+
#
|
|
235
|
+
# @rbs return: ErrorEnumerator
|
|
236
|
+
def rebuild(id = @id, order: @order, limit: @limit, page_size: @page_size)
|
|
237
|
+
self.class.new(id, limit:, order:, page_size:)
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
module Resources
|
|
9
|
+
# Paginated list of error records.
|
|
10
|
+
# @rbs inherits Page[ErrorRecord]
|
|
11
|
+
class ErrorPage < Page
|
|
12
|
+
def items #: () -> Array[ErrorRecord]
|
|
13
|
+
@items ||= (@data["errors"] || []).map { |e| ErrorRecord.new(client, e) }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
alias errors items
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
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
|
+
module Resources
|
|
9
|
+
# Typed wrapper around a single error record from the job error history.
|
|
10
|
+
class ErrorRecord < Resource
|
|
11
|
+
def attempt = @data["attempt"] #: () -> Integer
|
|
12
|
+
def message = @data["message"] #: () -> String
|
|
13
|
+
def error_type = @data["error_type"] #: () -> String?
|
|
14
|
+
def backtrace = @data["backtrace"] #: () -> String?
|
|
15
|
+
def dequeued_at = ms_to_seconds(@data["dequeued_at"]) #: () -> Float
|
|
16
|
+
def failed_at = ms_to_seconds(@data["failed_at"]) #: () -> Float
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,124 @@
|
|
|
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
|
+
module Resources
|
|
9
|
+
# Typed wrapper around a job response hash.
|
|
10
|
+
#
|
|
11
|
+
# Exposes named accessor methods with Ruby-idiomatic types (fractional
|
|
12
|
+
# seconds instead of milliseconds) and link methods that follow related
|
|
13
|
+
# resources through the Client.
|
|
14
|
+
class Job < Resource
|
|
15
|
+
def id = @data["id"] #: () -> String
|
|
16
|
+
def type = @data["type"] #: () -> String
|
|
17
|
+
def queue = @data["queue"] #: () -> String
|
|
18
|
+
def priority = @data["priority"] #: () -> Integer
|
|
19
|
+
def status = @data["status"] #: () -> String
|
|
20
|
+
def ready_at = ms_to_seconds(@data["ready_at"]) #: () -> Float?
|
|
21
|
+
def attempts = @data["attempts"] #: () -> Integer
|
|
22
|
+
def payload = @data["payload"] #: () -> Hash[String, untyped]?
|
|
23
|
+
def dequeued_at = ms_to_seconds(@data["dequeued_at"]) #: () -> Float?
|
|
24
|
+
def failed_at = ms_to_seconds(@data["failed_at"]) #: () -> Float?
|
|
25
|
+
def completed_at = ms_to_seconds(@data["completed_at"]) #: () -> Float?
|
|
26
|
+
def retry_limit = @data["retry_limit"] #: () -> Integer?
|
|
27
|
+
def unique_key = @data["unique_key"] #: () -> String?
|
|
28
|
+
def unique_while = @data["unique_while"]&.to_sym #: () -> Zizq::unique_scope?
|
|
29
|
+
def duplicate? = @data["duplicate"] == true #: () -> bool
|
|
30
|
+
|
|
31
|
+
# Backoff configuration converted from the wire format (ms) to the
|
|
32
|
+
# Ruby-idiomatic format (seconds), matching the Zizq::backoff type.
|
|
33
|
+
def backoff #: () -> Zizq::backoff?
|
|
34
|
+
raw = @data["backoff"]
|
|
35
|
+
return nil unless raw
|
|
36
|
+
|
|
37
|
+
{
|
|
38
|
+
exponent: raw["exponent"].to_f,
|
|
39
|
+
base: raw["base_ms"] / 1000.0,
|
|
40
|
+
jitter: raw["jitter_ms"] / 1000.0
|
|
41
|
+
}
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Retention configuration converted from the wire format (ms) to the
|
|
45
|
+
# Ruby-idiomatic format (seconds), matching the Zizq::retention type.
|
|
46
|
+
def retention #: () -> Zizq::retention?
|
|
47
|
+
raw = @data["retention"]
|
|
48
|
+
return nil unless raw
|
|
49
|
+
|
|
50
|
+
result = {} #: Hash[Symbol, Float]
|
|
51
|
+
result[:completed] = raw["completed_ms"] / 1000.0 if raw["completed_ms"]
|
|
52
|
+
result[:dead] = raw["dead_ms"] / 1000.0 if raw["dead_ms"]
|
|
53
|
+
result
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Fetch the error history for this job.
|
|
57
|
+
#
|
|
58
|
+
# @rbs order: Zizq::sort_direction?
|
|
59
|
+
# @rbs limit: Integer?
|
|
60
|
+
# @rbs page_size: Integer?
|
|
61
|
+
# @rbs return: ErrorEnumerator
|
|
62
|
+
def errors(order: nil, limit: nil, page_size: nil)
|
|
63
|
+
ErrorEnumerator.new(id, order:, limit:, page_size:)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Mark this job as successfully completed.
|
|
67
|
+
def complete! #: () -> nil
|
|
68
|
+
@client.report_success(id)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Report this job as failed.
|
|
72
|
+
#
|
|
73
|
+
# @rbs message: String
|
|
74
|
+
# @rbs error_type: String?
|
|
75
|
+
# @rbs backtrace: String?
|
|
76
|
+
# @rbs retry_at: Float?
|
|
77
|
+
# @rbs kill: bool
|
|
78
|
+
# @rbs return: Job
|
|
79
|
+
def fail!(message:, error_type: nil, backtrace: nil, retry_at: nil, kill: false)
|
|
80
|
+
@client.report_failure(id, message:, error_type:, backtrace:, retry_at:, kill:)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Delete this job.
|
|
84
|
+
#
|
|
85
|
+
# @rbs return: void
|
|
86
|
+
def delete
|
|
87
|
+
@client.delete_job(id)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Update this job's mutable fields.
|
|
91
|
+
#
|
|
92
|
+
# Returns the updated job.
|
|
93
|
+
#
|
|
94
|
+
# @rbs queue: (String | singleton(Zizq::UNCHANGED))?
|
|
95
|
+
# @rbs priority: (Integer | singleton(Zizq::UNCHANGED))?
|
|
96
|
+
# @rbs ready_at: (Zizq::to_f | singleton(Zizq::RESET) | singleton(Zizq::UNCHANGED))?
|
|
97
|
+
# @rbs retry_limit: (Integer | singleton(Zizq::RESET) | singleton(Zizq::UNCHANGED))?
|
|
98
|
+
# @rbs backoff: (Zizq::backoff | singleton(Zizq::RESET) | singleton(Zizq::UNCHANGED))?
|
|
99
|
+
# @rbs retention: (Zizq::retention | singleton(Zizq::RESET) | singleton(Zizq::UNCHANGED))?
|
|
100
|
+
# @rbs return: Job
|
|
101
|
+
def update(queue: Zizq::UNCHANGED,
|
|
102
|
+
priority: Zizq::UNCHANGED,
|
|
103
|
+
ready_at: Zizq::UNCHANGED,
|
|
104
|
+
retry_limit: Zizq::UNCHANGED,
|
|
105
|
+
backoff: Zizq::UNCHANGED,
|
|
106
|
+
retention: Zizq::UNCHANGED)
|
|
107
|
+
job = @client.update_job(
|
|
108
|
+
id,
|
|
109
|
+
queue:,
|
|
110
|
+
priority:,
|
|
111
|
+
ready_at:,
|
|
112
|
+
retry_limit:,
|
|
113
|
+
backoff:,
|
|
114
|
+
retention:
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
# Make sure this job's fields are updated.
|
|
118
|
+
@data.merge!(job.to_h)
|
|
119
|
+
|
|
120
|
+
job
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
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
|
+
module Resources
|
|
9
|
+
# Paginated list of jobs.
|
|
10
|
+
# @rbs inherits Page[Job]
|
|
11
|
+
class JobPage < Page
|
|
12
|
+
def items #: () -> Array[Job]
|
|
13
|
+
@items ||= (@data["jobs"] || []).map { |j| Job.new(client, j) }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
alias jobs items
|
|
17
|
+
|
|
18
|
+
# Delete all jobs on this page.
|
|
19
|
+
#
|
|
20
|
+
# Returns the number of deleted jobs.
|
|
21
|
+
#
|
|
22
|
+
# @rbs return: Integer
|
|
23
|
+
def delete_all
|
|
24
|
+
ids = jobs.map(&:id)
|
|
25
|
+
return 0 if ids.empty?
|
|
26
|
+
|
|
27
|
+
client.delete_all_jobs(where: { id: ids })
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Update all jobs on this page with the given field values.
|
|
31
|
+
#
|
|
32
|
+
# Returns the number of updated jobs.
|
|
33
|
+
#
|
|
34
|
+
# @rbs queue: (String | singleton(Zizq::UNCHANGED))?
|
|
35
|
+
# @rbs priority: (Integer | singleton(Zizq::UNCHANGED))?
|
|
36
|
+
# @rbs ready_at: (Zizq::to_f | singleton(Zizq::RESET) | singleton(Zizq::UNCHANGED))?
|
|
37
|
+
# @rbs retry_limit: (Integer | singleton(Zizq::RESET) | singleton(Zizq::UNCHANGED))?
|
|
38
|
+
# @rbs backoff: (Zizq::backoff | singleton(Zizq::RESET) | singleton(Zizq::UNCHANGED))?
|
|
39
|
+
# @rbs retention: (Zizq::retention | singleton(Zizq::RESET) | singleton(Zizq::UNCHANGED))?
|
|
40
|
+
# @rbs return: Integer
|
|
41
|
+
def update_all(queue: Zizq::UNCHANGED,
|
|
42
|
+
priority: Zizq::UNCHANGED,
|
|
43
|
+
ready_at: Zizq::UNCHANGED,
|
|
44
|
+
retry_limit: Zizq::UNCHANGED,
|
|
45
|
+
backoff: Zizq::UNCHANGED,
|
|
46
|
+
retention: Zizq::UNCHANGED)
|
|
47
|
+
ids = jobs.map(&:id)
|
|
48
|
+
return 0 if ids.empty?
|
|
49
|
+
|
|
50
|
+
client.update_all_jobs(
|
|
51
|
+
where: { id: ids },
|
|
52
|
+
apply: { queue:, priority:, ready_at:, retry_limit:, backoff:, retention: },
|
|
53
|
+
)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,77 @@
|
|
|
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
|
+
module Resources
|
|
9
|
+
# Base class for paginated list responses.
|
|
10
|
+
#
|
|
11
|
+
# Stores the raw response data and provides navigation helpers that
|
|
12
|
+
# follow pagination links through the Client.
|
|
13
|
+
#
|
|
14
|
+
# @rbs generic T < Resource
|
|
15
|
+
class Page < Resource
|
|
16
|
+
# @rbs skip
|
|
17
|
+
include Enumerable
|
|
18
|
+
|
|
19
|
+
# @rbs!
|
|
20
|
+
# include ::Enumerable[T]
|
|
21
|
+
|
|
22
|
+
# Wrapped resource objects for this page.
|
|
23
|
+
def items #: () -> Array[T]
|
|
24
|
+
raise NotImplementedError, "#{self.class.name}#items must be implemented"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Returns the underlying raw response hash.
|
|
28
|
+
#
|
|
29
|
+
# Re-declared here because Enumerable#to_h would otherwise shadow
|
|
30
|
+
# the Resource#to_h definition.
|
|
31
|
+
def to_h #: () -> Hash[String, untyped]
|
|
32
|
+
@data
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Yields each item on this page. Required by Enumerable.
|
|
36
|
+
#
|
|
37
|
+
# @rbs &block: (T) -> void
|
|
38
|
+
# @rbs return: Enumerator[T, void] | void
|
|
39
|
+
def each(&block)
|
|
40
|
+
items.each(&block)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Returns true if there is a next page that can be fetched.
|
|
44
|
+
def has_next? #: () -> bool
|
|
45
|
+
!!@data.dig("pages", "next")
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Returns true if there is a previous page that can be fetched.
|
|
49
|
+
def has_prev? #: () -> bool
|
|
50
|
+
!!@data.dig("pages", "prev")
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Fetch the next page, or nil if there isn't one.
|
|
54
|
+
def next_page #: () -> Page?
|
|
55
|
+
path = @data.dig("pages", "next")
|
|
56
|
+
return nil unless path
|
|
57
|
+
|
|
58
|
+
wrap_page(client.get_path(path))
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Fetch the previous page, or nil if there isn't one.
|
|
62
|
+
def prev_page #: () -> Page?
|
|
63
|
+
path = @data.dig("pages", "prev")
|
|
64
|
+
return nil unless path
|
|
65
|
+
|
|
66
|
+
wrap_page(client.get_path(path))
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
# Subclasses override to wrap the raw page data in the correct Page type.
|
|
72
|
+
def wrap_page(data) #: (Hash[String, untyped]) -> Page
|
|
73
|
+
self.class.new(client, data)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
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
|
+
module Resources
|
|
9
|
+
# Base class for all typed response wrappers. Holds a reference to the
|
|
10
|
+
# Client (for following links) and the raw response hash.
|
|
11
|
+
class Resource
|
|
12
|
+
# Returns the client instance that returned this resource.
|
|
13
|
+
attr_reader :client #: Client
|
|
14
|
+
|
|
15
|
+
# @rbs client: Zizq::Client
|
|
16
|
+
# @rbs data: Hash[String, untyped]
|
|
17
|
+
# @rbs return: void
|
|
18
|
+
def initialize(client, data)
|
|
19
|
+
@client = client
|
|
20
|
+
@data = data
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Returns the underlying raw response hash.
|
|
24
|
+
def to_h #: () -> Hash[String, untyped]
|
|
25
|
+
@data
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Omit the client from inspect output to reduce noise.
|
|
29
|
+
def inspect #: () -> String
|
|
30
|
+
ivars = instance_variables
|
|
31
|
+
.reject { |v| v == :@client }
|
|
32
|
+
.map { |v| " #{v}=#{instance_variable_get(v).inspect}" }
|
|
33
|
+
.join
|
|
34
|
+
"#<#{self.class}#{ivars}>"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
protected
|
|
38
|
+
|
|
39
|
+
# Convert a millisecond timestamp to fractional seconds, nil-safe.
|
|
40
|
+
def ms_to_seconds(value) #: (Integer?) -> Float?
|
|
41
|
+
value&./(1000.0)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Copyright (c) 2026 Chris Corbyn <chris@zizq.io>
|
|
2
|
+
# Licensed under the MIT License. See LICENSE file for details.
|
|
3
|
+
|
|
4
|
+
# frozen_string_literal: true
|
|
5
|
+
|
|
6
|
+
module Zizq
|
|
7
|
+
module Resources
|
|
8
|
+
autoload :Resource, "zizq/resources/resource"
|
|
9
|
+
autoload :Job, "zizq/resources/job"
|
|
10
|
+
autoload :ErrorRecord, "zizq/resources/error_record"
|
|
11
|
+
autoload :Page, "zizq/resources/page"
|
|
12
|
+
autoload :JobPage, "zizq/resources/job_page"
|
|
13
|
+
autoload :ErrorPage, "zizq/resources/error_page"
|
|
14
|
+
autoload :ErrorEnumerator, "zizq/resources/error_enumerator"
|
|
15
|
+
end
|
|
16
|
+
end
|