riverqueue 0.11.0 → 0.12.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 (83) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +132 -0
  3. data/LICENSE +374 -0
  4. data/docs/README.md +765 -0
  5. data/docs/migrations.md +121 -0
  6. data/docs/testing.md +173 -0
  7. data/docs/workers.md +126 -0
  8. data/exe/river +7 -0
  9. data/lib/cli.rb +55 -0
  10. data/lib/client.rb +314 -54
  11. data/lib/client_runtime.rb +612 -0
  12. data/lib/config.rb +154 -0
  13. data/lib/driver/job_row_decoder.rb +85 -0
  14. data/lib/driver/postgres_capabilities.rb +41 -0
  15. data/lib/driver/runtime.rb +661 -0
  16. data/lib/driver.rb +13 -6
  17. data/lib/errors.rb +83 -0
  18. data/lib/event.rb +78 -0
  19. data/lib/insert_opts.rb +40 -11
  20. data/lib/job.rb +28 -13
  21. data/lib/job_persisted_logging/plugin.rb +108 -0
  22. data/lib/migration_cli.rb +90 -0
  23. data/lib/migrator.rb +189 -0
  24. data/lib/params.rb +96 -0
  25. data/lib/periodic_cron.rb +24 -0
  26. data/lib/periodic_job.rb +135 -0
  27. data/lib/resumable.rb +148 -0
  28. data/lib/riverqueue/testing/minitest.rb +18 -0
  29. data/lib/riverqueue/testing/rspec.rb +109 -0
  30. data/lib/riverqueue/testing.rb +134 -0
  31. data/lib/riverqueue.rb +16 -0
  32. data/lib/unique_args.rb +97 -0
  33. data/lib/unique_bitmask.rb +14 -12
  34. data/lib/worker.rb +152 -0
  35. data/lib/worker_runner.rb +106 -0
  36. data/migration/LICENSE +374 -0
  37. data/migration/README.md +11 -0
  38. data/migration/manifest.json +38 -0
  39. data/migration/postgresql/main/001_create_river_migration.down.sql +1 -0
  40. data/migration/postgresql/main/001_create_river_migration.up.sql +8 -0
  41. data/migration/postgresql/main/002_initial_schema.down.sql +5 -0
  42. data/migration/postgresql/main/002_initial_schema.up.sql +96 -0
  43. data/migration/postgresql/main/003_river_job_tags_non_null.down.sql +3 -0
  44. data/migration/postgresql/main/003_river_job_tags_non_null.up.sql +3 -0
  45. data/migration/postgresql/main/004_pending_and_more.down.sql +42 -0
  46. data/migration/postgresql/main/004_pending_and_more.up.sql +45 -0
  47. data/migration/postgresql/main/005_migration_unique_client.down.sql +57 -0
  48. data/migration/postgresql/main/005_migration_unique_client.up.sql +79 -0
  49. data/migration/postgresql/main/006_bulk_unique.down.sql +16 -0
  50. data/migration/postgresql/main/006_bulk_unique.up.sql +40 -0
  51. data/migration/postgresql/main/007_notification_outbox_sqlite_jsonb_and_sql_cleanup.down.sql +56 -0
  52. data/migration/postgresql/main/007_notification_outbox_sqlite_jsonb_and_sql_cleanup.up.sql +44 -0
  53. data/migration/postgresql/main/008_job_id_autoincrement.down.sql +3 -0
  54. data/migration/postgresql/main/008_job_id_autoincrement.up.sql +3 -0
  55. data/migration/sqlite/main/001_create_river_migration.down.sql +1 -0
  56. data/migration/sqlite/main/001_create_river_migration.up.sql +8 -0
  57. data/migration/sqlite/main/002_initial_schema.down.sql +8 -0
  58. data/migration/sqlite/main/002_initial_schema.up.sql +19 -0
  59. data/migration/sqlite/main/003_river_job_tags_non_null.down.sql +6 -0
  60. data/migration/sqlite/main/003_river_job_tags_non_null.up.sql +6 -0
  61. data/migration/sqlite/main/004_pending_and_more.down.sql +26 -0
  62. data/migration/sqlite/main/004_pending_and_more.up.sql +33 -0
  63. data/migration/sqlite/main/005_migration_unique_client.down.sql +37 -0
  64. data/migration/sqlite/main/005_migration_unique_client.up.sql +64 -0
  65. data/migration/sqlite/main/006_bulk_unique.down.sql +7 -0
  66. data/migration/sqlite/main/006_bulk_unique.up.sql +63 -0
  67. data/migration/sqlite/main/007_notification_outbox_sqlite_jsonb_and_sql_cleanup.down.sql +255 -0
  68. data/migration/sqlite/main/007_notification_outbox_sqlite_jsonb_and_sql_cleanup.up.sql +261 -0
  69. data/migration/sqlite/main/008_job_id_autoincrement.down.sql +121 -0
  70. data/migration/sqlite/main/008_job_id_autoincrement.up.sql +123 -0
  71. data/sig/client.rbs +95 -0
  72. data/sig/driver.rbs +170 -0
  73. data/sig/insert_opts.rbs +25 -0
  74. data/sig/job.rbs +72 -0
  75. data/sig/job_persisted_logging/plugin.rbs +29 -0
  76. data/sig/migrator.rbs +44 -0
  77. data/sig/riverqueue.rbs +2 -0
  78. data/sig/runtime.rbs +382 -0
  79. data/sig/testing.rbs +95 -0
  80. data/sig/unique_args.rbs +8 -0
  81. data/sig/unique_bitmask.rbs +8 -0
  82. data/sig/worker_runner.rbs +22 -0
  83. metadata +165 -10
data/sig/runtime.rbs ADDED
@@ -0,0 +1,382 @@
1
+ class Thread
2
+ def self.handle_interrupt: [T] (Hash[Class, Symbol]) { () -> T } -> T
3
+ end
4
+
5
+ module River
6
+ FETCH_COOLDOWN_DEFAULT: Float
7
+ FETCH_POLL_INTERVAL_DEFAULT: Float
8
+ JOB_TIMEOUT_DEFAULT: Float
9
+ QUEUE_NAME_REGEX: Regexp
10
+ QUEUE_NUM_WORKERS_MAX: Integer
11
+
12
+ EVENT_JOB_CANCELLED: Symbol
13
+ EVENT_JOB_COMPLETED: Symbol
14
+ EVENT_JOB_FAILED: Symbol
15
+ EVENT_JOB_INTERRUPTED: Symbol
16
+ EVENT_JOB_SNOOZED: Symbol
17
+ EVENT_QUEUE_PAUSED: Symbol
18
+ EVENT_QUEUE_RESUMED: Symbol
19
+
20
+ Event: untyped
21
+ JobDeleteManyResult: untyped
22
+ JobListCursor: untyped
23
+ JobListResult: untyped
24
+ JobStatistics: untyped
25
+ QueueListResult: untyped
26
+ class Queue
27
+ def initialize: (String, Time, Hash[untyped, untyped], Time?, Time) -> void
28
+ def created_at: () -> Time
29
+ def metadata: () -> Hash[untyped, untyped]
30
+ def name: () -> String
31
+ def paused_at: () -> Time?
32
+ def updated_at: () -> Time
33
+ end
34
+
35
+ class Error < StandardError
36
+ end
37
+
38
+ class NotFoundError < Error
39
+ end
40
+
41
+ class JobRunningError < Error
42
+ end
43
+
44
+ class JobRowDecodeError < Error
45
+ attr_reader job: JobRow
46
+ def initialize: (JobRow, String) -> void
47
+ end
48
+
49
+ class JobCancelError < Error
50
+ @cause: untyped
51
+ attr_reader cause: untyped
52
+ def initialize: (?String, ?cause: untyped) -> void
53
+ end
54
+
55
+ class JobSnoozeError < Error
56
+ @duration: Float
57
+ attr_reader duration: Float
58
+ def initialize: (Numeric) -> void
59
+ end
60
+
61
+ class UnknownJobKindError < Error
62
+ @kind: untyped
63
+ attr_reader kind: untyped
64
+ def initialize: (untyped) -> void
65
+ end
66
+
67
+ class ClientNotStartedError < Error
68
+ end
69
+
70
+ class ClientAlreadyStartedError < Error
71
+ end
72
+
73
+ def self.job_cancel: (?(String | Exception)?) -> JobCancelError
74
+ def self.job_snooze: (Numeric) -> JobSnoozeError
75
+
76
+ class Workers
77
+ @workers: Hash[String, untyped]
78
+ def initialize: () -> void
79
+ def add: (untyped, ?untyped, ?aliases: Array[untyped]) -> self
80
+ def []: (String | Symbol) -> untyped
81
+ def fetch: (String | Symbol) -> untyped
82
+ | (String | Symbol, untyped) -> untyped
83
+ | (String | Symbol) { (String) -> untyped } -> untyped
84
+ def include?: (String | Symbol) -> bool
85
+ def kinds: () -> Array[String]
86
+ end
87
+
88
+ class Job
89
+ RESUMABLE_CURSOR_UNSET: Object
90
+ @client: Client
91
+ @logger: untyped
92
+ @metadata_updates: Hash[String, untyped]
93
+ @resumable_state: ResumableState
94
+ @row: JobRow
95
+ attr_reader client: Client
96
+ attr_reader row: JobRow
97
+ def initialize: (Client, JobRow) -> void
98
+ def __capture_resumable_metadata!: () -> untyped
99
+ def __finish_resumable_work!: () -> untyped
100
+ def __with_logger: [T] (untyped logger) { () -> T } -> T
101
+ def args: () -> untyped
102
+ def logger: () -> untyped
103
+ def metadata: () -> Hash[untyped, untyped]
104
+ def metadata_updates: () -> Hash[String, untyped]
105
+ def method_missing: (Symbol, *untyped, **untyped) -> untyped
106
+ def output=: (untyped) -> untyped
107
+ def resumable_checkpoint: (?cursor: untyped) -> JobRow
108
+ def respond_to_missing?: (Symbol, ?bool) -> bool
109
+ def resumable_set_cursor: (untyped) -> untyped
110
+ def resumable_step: (String | Symbol) { () -> untyped } -> untyped
111
+ def resumable_step_cursor: (String | Symbol, ?default: untyped) { (untyped) -> untyped } -> untyped
112
+ def update_metadata: (Hash[untyped, untyped]) -> self
113
+
114
+ private
115
+
116
+ def initialize_resumable_state: () -> ResumableState
117
+ def run_resumable_step: (String, cursor: bool, default: untyped) { () -> untyped } -> untyped
118
+ | (String, cursor: bool, default: untyped) { (untyped) -> untyped } -> untyped
119
+ end
120
+
121
+ RESUMABLE_CURSOR_METADATA_KEY: String
122
+ RESUMABLE_STEP_METADATA_KEY: String
123
+
124
+ class ResumableState
125
+ attr_reader all_step_names: Hash[String, bool]
126
+ attr_accessor completed_step: String?
127
+ attr_reader cursors: Hash[String, untyped]
128
+ attr_accessor cursors_dirty: bool
129
+ attr_accessor resume_matched: bool
130
+ attr_reader resume_step: String?
131
+ attr_accessor step_name: String?
132
+ def initialize: (Hash[String, untyped]) -> void
133
+ def register: (String) -> bool
134
+ end
135
+
136
+ class DefaultClientRetryPolicy
137
+ MAX_DELAY: Rational
138
+ @random: untyped
139
+ def initialize: (?random: untyped) -> void
140
+ def next_retry: (untyped, ?untyped, ?now: Time) -> Time
141
+ end
142
+
143
+ class QueueConfig
144
+ @fetch_cooldown: Float?
145
+ @fetch_poll_interval: Float?
146
+ @max_workers: Integer
147
+ attr_reader fetch_cooldown: Float?
148
+ attr_reader fetch_poll_interval: Float?
149
+ attr_reader max_workers: Integer
150
+ def initialize: (max_workers: Integer, ?fetch_cooldown: Numeric?, ?fetch_poll_interval: Numeric?) -> void
151
+ def resolved_fetch_cooldown: (Config) -> Float
152
+ def resolved_fetch_poll_interval: (Config) -> Float
153
+ end
154
+
155
+ class Config
156
+ @cancelled_job_retention_period: Float?
157
+ @completed_job_retention_period: Float?
158
+ @discarded_job_retention_period: Float?
159
+ @error_handler: untyped
160
+ @fetch_cooldown: Float
161
+ @fetch_only_known_kinds: bool
162
+ @fetch_poll_interval: Float
163
+ @id: String
164
+ @job_timeout: Float?
165
+ @leader_election_disabled: bool
166
+ @logger: untyped
167
+ @maintenance_services: Array[untyped]
168
+ @periodic_jobs: Array[untyped]
169
+ @plugins: Array[untyped]
170
+ @queues: Hash[String, QueueConfig]
171
+ @retry_policy: untyped
172
+ @workers: Workers
173
+
174
+ attr_reader cancelled_job_retention_period: Float?
175
+ attr_reader completed_job_retention_period: Float?
176
+ attr_reader discarded_job_retention_period: Float?
177
+ attr_reader error_handler: untyped
178
+ attr_reader fetch_cooldown: Float
179
+ attr_reader fetch_only_known_kinds: bool
180
+ attr_reader fetch_poll_interval: Float
181
+ attr_reader id: String
182
+ attr_reader job_timeout: Float?
183
+ attr_reader leader_election_disabled: bool
184
+ attr_reader logger: untyped
185
+ attr_reader maintenance_services: Array[untyped]
186
+ attr_reader periodic_jobs: Array[untyped]
187
+ attr_reader plugins: Array[untyped]
188
+ attr_reader queues: Hash[String, QueueConfig]
189
+ attr_reader retry_policy: untyped
190
+ attr_reader workers: Workers
191
+
192
+ def initialize: (?queues: untyped, ?workers: untyped, ?id: untyped,
193
+ ?fetch_cooldown: untyped, ?fetch_only_known_kinds: bool, ?fetch_poll_interval: untyped, ?job_timeout: untyped,
194
+ ?leader_election_disabled: bool,
195
+ ?retry_policy: untyped, ?error_handler: untyped, ?plugins: untyped,
196
+ ?maintenance_services: untyped, ?periodic_jobs: untyped,
197
+ ?cancelled_job_retention_period: untyped, ?completed_job_retention_period: untyped,
198
+ ?discarded_job_retention_period: untyped, ?logger: untyped) -> void
199
+ def with: (**untyped) -> Config
200
+
201
+ private
202
+
203
+ def normalize_queues: (untyped) -> Hash[String, QueueConfig]
204
+ def retention: (untyped) -> Float?
205
+ def validate: () -> void
206
+ end
207
+
208
+ class Subscription
209
+ @closed: bool
210
+ @kinds: Array[Symbol]
211
+ @mutex: Mutex
212
+ @on_close: untyped
213
+ @queue: untyped
214
+ def initialize: (Array[Symbol | String], ?buffer_size: Integer, ?on_close: untyped) -> void
215
+ def close: () -> untyped
216
+ def each: () { (untyped) -> void } -> untyped
217
+ | () -> Enumerator[untyped, untyped]
218
+ def pop: (?bool) -> untyped
219
+ def publish: (untyped) -> untyped
220
+ end
221
+
222
+ class JobListParams
223
+ @after: untyped
224
+ @after_id: untyped
225
+ @ids: untyped
226
+ @kinds: untyped
227
+ @limit: Integer
228
+ @metadata: untyped
229
+ @priorities: untyped
230
+ @queues: untyped
231
+ @sort_by: Symbol
232
+ @sort_order: Symbol
233
+ @states: untyped
234
+ @tags_all: untyped
235
+ @tags_any: untyped
236
+ attr_reader after_id: untyped
237
+ attr_reader after: untyped
238
+ attr_reader ids: untyped
239
+ attr_reader kinds: untyped
240
+ attr_reader limit: Integer
241
+ attr_reader metadata: untyped
242
+ attr_reader priorities: untyped
243
+ attr_reader queues: untyped
244
+ attr_reader sort_by: Symbol
245
+ attr_reader sort_order: Symbol
246
+ attr_reader states: untyped
247
+ attr_reader tags_all: untyped
248
+ attr_reader tags_any: untyped
249
+ def initialize: (?after: untyped, ?after_id: untyped, ?ids: untyped, ?kinds: untyped, ?limit: untyped,
250
+ ?priorities: untyped, ?metadata: untyped, ?queues: untyped, ?sort_by: untyped,
251
+ ?sort_order: untyped, ?states: untyped, ?tags_all: untyped, ?tags_any: untyped) -> void
252
+ def filters?: () -> bool
253
+ end
254
+
255
+ class JobUpdateParams
256
+ UNSET: Object
257
+ @attempt: untyped
258
+ @attempted_at: untyped
259
+ @attempted_by: untyped
260
+ @errors: untyped
261
+ @finalized_at: untyped
262
+ @max_attempts: untyped
263
+ @metadata: untyped
264
+ @state: untyped
265
+ attr_reader attempt: untyped
266
+ attr_reader attempted_at: untyped
267
+ attr_reader attempted_by: untyped
268
+ attr_reader errors: untyped
269
+ attr_reader finalized_at: untyped
270
+ attr_reader max_attempts: untyped
271
+ attr_reader metadata: untyped
272
+ attr_reader state: untyped
273
+ def initialize: (?attempt: untyped, ?attempted_at: untyped, ?attempted_by: untyped,
274
+ ?errors: untyped, ?finalized_at: untyped, ?max_attempts: untyped,
275
+ ?metadata: untyped, ?state: untyped) -> void
276
+ def each: () { (Symbol, untyped) -> void } -> untyped
277
+ | () -> Enumerator[[Symbol, untyped], untyped]
278
+ end
279
+
280
+ class PeriodicJob
281
+ attr_reader constructor: untyped
282
+ attr_reader id: String?
283
+ attr_reader run_on_start: bool
284
+ attr_reader schedule: untyped
285
+ def initialize: (schedule: untyped, ?constructor: untyped, ?id: (String | Symbol)?, ?run_on_start: bool) ?{ () -> untyped } -> void
286
+ def next_at: (Time) -> Time
287
+ end
288
+
289
+ class PeriodicCron
290
+ @cron: untyped
291
+ def initialize: (String, ?timezone: String) -> void
292
+ def next: (Time) -> Time
293
+ end
294
+
295
+ class PeriodicInterval
296
+ @seconds: Float
297
+ def initialize: (Numeric) -> void
298
+ def next: (Time) -> Time
299
+ end
300
+
301
+ class PeriodicJobBundle
302
+ @jobs: Hash[Integer, untyped]
303
+ @mutex: Mutex
304
+ @next_handle: Integer
305
+ @wake: untyped
306
+ def initialize: (Array[PeriodicJob], wake: untyped) -> void
307
+ def add: (PeriodicJob) -> Integer
308
+ def add_many: (Array[PeriodicJob]) -> Array[Integer]
309
+ def clear: () -> self
310
+ def due: (Time) ?{ (PeriodicJob, StandardError) -> void } -> Array[PeriodicJob]
311
+ def remove: (Integer) -> PeriodicJob?
312
+ def remove_by_id: (untyped) -> bool
313
+ end
314
+
315
+ class ClientRuntime
316
+ class Interrupted < StandardError
317
+ end
318
+
319
+ @client: Client
320
+ @condition: ConditionVariable
321
+ @config: Config
322
+ @driver: _Driver
323
+ @maintenance_thread: Thread?
324
+ @mutex: Mutex
325
+ @periodic_jobs: PeriodicJobBundle
326
+ @performing: bool?
327
+ @producer_threads: Hash[String, Thread]
328
+ @queue_configs: Hash[String, QueueConfig]
329
+ @removed_queues: Hash[String, bool]
330
+ @running: Hash[Integer, untyped]
331
+ @started: bool
332
+ @stop_requested: bool
333
+ @stopped: bool
334
+ @subscriptions: Array[Subscription]
335
+ @threads: Array[Thread]
336
+
337
+ attr_reader periodic_jobs: PeriodicJobBundle
338
+ def initialize: (Client, _Driver, Config) -> void
339
+ def finish_claimed: (JobRow, ?Exception?) -> untyped
340
+ def healthy?: () -> bool
341
+ def interrupt_workers: () -> untyped
342
+ def perform_job: (Integer, ?allow_scheduled: bool) -> untyped
343
+ def publish_queue: (Symbol, Queue) -> untyped
344
+ def queue_add: (String, QueueConfig | Integer) -> QueueConfig
345
+ def queue_remove: (String) -> bool
346
+ def start: () -> self
347
+ def started?: () -> bool
348
+ def stop: (?cancel: bool, ?wait: bool) -> self
349
+ def stopped?: () -> bool
350
+ def subscribe: (Array[Symbol | String], ?buffer_size: Integer) -> Subscription
351
+ def wake: () -> untyped
352
+
353
+ private
354
+
355
+ def begin_work: (Integer) -> untyped
356
+ def check_remote_cancellations: (String) -> untyped
357
+ def error_handler_cancel?: (Exception, Job) -> bool
358
+ def execute: (JobRow) -> untyped
359
+ def finish_failed: (JobRow, Job, Exception, Time, ?cancelled: bool, ?worker: untyped) -> untyped
360
+ def finish_snoozed: (JobRow, Job, JobSnoozeError, Time) -> untyped
361
+ def finish_work: (Integer) -> untyped
362
+ def invoke_plugins: (Symbol, *untyped) -> Array[untyped]
363
+ def invoke_worker: (untyped, Job) -> untyped
364
+ def launch: (JobRow) -> untyped
365
+ def maintenance_loop: () -> untyped
366
+ def monotonic_now: () -> Float
367
+ def next_retry: (JobRow, Exception, Time, ?worker: untyped) -> Time
368
+ def retry_allowed?: (untyped, Job, Exception) -> untyped
369
+ def perform_work: (untyped, Job) -> untyped
370
+ def producer_loop: (String, QueueConfig) -> untyped
371
+ def publish: (Symbol, JobRow, Time) -> untyped
372
+ def queue_stopping?: (String) -> bool
373
+ def remove_subscription: (Subscription) -> Subscription?
374
+ def resolve_worker: (String) -> untyped
375
+ def run_periodic: (Time) -> untyped
376
+ def running_count: (String) -> Integer
377
+ def start_maintenance: () -> untyped
378
+ def start_producer: (String, QueueConfig) -> untyped
379
+ def stopping?: () -> bool
380
+ def wait: (Float | Integer) -> untyped
381
+ end
382
+ end
data/sig/testing.rbs ADDED
@@ -0,0 +1,95 @@
1
+ module RSpec
2
+ module Matchers
3
+ module Composable
4
+ def and: (untyped) -> untyped
5
+ def or: (untyped) -> untyped
6
+ private def surface_descriptions_in: (untyped) -> untyped
7
+ private def values_match?: (untyped, untyped) -> bool
8
+ end
9
+ end
10
+ end
11
+
12
+ module River
13
+ module Testing
14
+ class AssertionError < StandardError
15
+ end
16
+ class DrainLimitError < StandardError
17
+ end
18
+
19
+ JOB_ATTRIBUTES: Array[Symbol]
20
+
21
+ class ExecutionResult < Data
22
+ attr_reader id: Integer
23
+ attr_reader error: Exception?
24
+ attr_reader job: JobRow?
25
+ attr_reader outcome: Symbol
26
+ def self.new: (id: Integer, error: Exception?, job: JobRow?, outcome: Symbol) -> instance
27
+ end
28
+
29
+ def self.drain: (Client, queue: String | Symbol, ?max_jobs: Integer) -> Array[ExecutionResult]
30
+ def self.normalize_attributes: (Hash[Symbol, untyped]) -> Hash[Symbol, untyped]
31
+ def self.inserted_jobs: (Client, **untyped) ?{ () -> untyped } -> Array[JobRow]
32
+ def self.perform_job: (Client, Integer, ?allow_scheduled: bool) -> ExecutionResult
33
+ def self.jobs: (Client) -> Array[JobRow]
34
+
35
+ module Assertions
36
+ include Kernel
37
+ def assert_job_cancelled: (ExecutionResult) -> ExecutionResult
38
+ def assert_job_completed: (ExecutionResult) -> ExecutionResult
39
+ def assert_job_discarded: (ExecutionResult) -> ExecutionResult
40
+ def assert_job_inserted: (Client, **untyped) ?{ () -> untyped } -> JobRow
41
+ def assert_jobs_inserted: (Client, count: Integer, **untyped) ?{ () -> untyped } -> Array[JobRow]
42
+ def assert_no_jobs_inserted: (Client, **untyped) ?{ () -> untyped } -> Array[JobRow]
43
+ private def river_assert: (bool, String) -> untyped
44
+ end
45
+
46
+ interface _MinitestAssertions
47
+ def assert: (untyped, String) -> untyped
48
+ end
49
+
50
+ module Minitest : Object, _MinitestAssertions
51
+ include Assertions
52
+ private def river_assert: (bool, String) -> untyped
53
+ end
54
+
55
+ module RSpec
56
+ include Kernel
57
+ def have_job: (**untyped) -> JobMatcher
58
+ def insert_job: (Client, **untyped) -> InsertionMatcher
59
+ def insert_jobs: (Client, ?count: Integer, **untyped) -> InsertionMatcher
60
+
61
+ class JobMatcher
62
+ include ::RSpec::Matchers::Composable
63
+ @attributes: Hash[Symbol, untyped]
64
+ @comparison: Symbol
65
+ @count: Integer
66
+ @count_description: String
67
+ @rows: Array[JobRow]
68
+ def initialize: (Integer, Hash[Symbol, untyped]) -> void
69
+ def at_least: (Integer) -> self
70
+ def at_most: (Integer) -> self
71
+ def description: () -> String
72
+ def does_not_match?: (untyped) -> bool
73
+ def exactly: (Integer) -> self
74
+ def failure_message: () -> String
75
+ def failure_message_when_negated: () -> String
76
+ def matches?: (untyped) -> bool
77
+ def supports_block_expectations?: () -> bool
78
+ def supports_value_expectations?: () -> bool
79
+ private def candidates: (untyped) -> Array[JobRow]
80
+ private def matching_rows: (untyped) -> Array[JobRow]
81
+ private def set_count: (Integer, Symbol, String) -> self
82
+ private def verb: () -> String
83
+ end
84
+
85
+ class InsertionMatcher < JobMatcher
86
+ @client: Client
87
+ def initialize: (Client, Integer, Hash[Symbol, untyped]) -> void
88
+ def supports_block_expectations?: () -> bool
89
+ def supports_value_expectations?: () -> bool
90
+ private def candidates: (untyped) -> Array[JobRow]
91
+ private def verb: () -> String
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,8 @@
1
+ module River
2
+ module UniqueArgs
3
+ def self.encode: (String json, bool? | Array[String | Symbol | Array[String | Symbol]] fields) -> String
4
+ def self.members: (String json) -> Hash[String, String]
5
+ def self.encode_object: (Hash[String, untyped] object) -> String
6
+ def self.encode_key: (String key) -> String
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module River
2
+ class UniqueBitmask
3
+ def self.from_states: (Array[jobStateAll]) -> String
4
+ def self.to_states: (Integer) -> Array[jobStateAll]
5
+
6
+ JOB_STATE_BIT_POSITIONS: Hash[jobStateAll, Integer]
7
+ end
8
+ end
@@ -0,0 +1,22 @@
1
+ module Process
2
+ def self.exit!: (?Integer) -> bot
3
+ end
4
+
5
+ module River
6
+ module CLI
7
+ def self.run: (Array[String], ?err: untyped, ?out: untyped) -> Integer
8
+ def self.worker: (Array[String], out: untyped) -> Integer
9
+ end
10
+
11
+ class WorkerRunner
12
+ @client: Client
13
+ @finalization_timeout: Float
14
+ @out: untyped
15
+ @stop_timeout: Float
16
+ def initialize: (Client, ?finalization_timeout: Numeric, ?out: untyped, ?stop_timeout: Numeric) -> void
17
+ def run: () -> Integer
18
+ private def log: (String) -> void
19
+ private def monotonic_now: () -> Float
20
+ private def supervise: (IO) -> Integer
21
+ end
22
+ end