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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +132 -0
- data/LICENSE +374 -0
- data/docs/README.md +765 -0
- data/docs/migrations.md +121 -0
- data/docs/testing.md +173 -0
- data/docs/workers.md +126 -0
- data/exe/river +7 -0
- data/lib/cli.rb +55 -0
- data/lib/client.rb +314 -54
- data/lib/client_runtime.rb +612 -0
- data/lib/config.rb +154 -0
- data/lib/driver/job_row_decoder.rb +85 -0
- data/lib/driver/postgres_capabilities.rb +41 -0
- data/lib/driver/runtime.rb +661 -0
- data/lib/driver.rb +13 -6
- data/lib/errors.rb +83 -0
- data/lib/event.rb +78 -0
- data/lib/insert_opts.rb +40 -11
- data/lib/job.rb +28 -13
- data/lib/job_persisted_logging/plugin.rb +108 -0
- data/lib/migration_cli.rb +90 -0
- data/lib/migrator.rb +189 -0
- data/lib/params.rb +96 -0
- data/lib/periodic_cron.rb +24 -0
- data/lib/periodic_job.rb +135 -0
- data/lib/resumable.rb +148 -0
- data/lib/riverqueue/testing/minitest.rb +18 -0
- data/lib/riverqueue/testing/rspec.rb +109 -0
- data/lib/riverqueue/testing.rb +134 -0
- data/lib/riverqueue.rb +16 -0
- data/lib/unique_args.rb +97 -0
- data/lib/unique_bitmask.rb +14 -12
- data/lib/worker.rb +152 -0
- data/lib/worker_runner.rb +106 -0
- data/migration/LICENSE +374 -0
- data/migration/README.md +11 -0
- data/migration/manifest.json +38 -0
- data/migration/postgresql/main/001_create_river_migration.down.sql +1 -0
- data/migration/postgresql/main/001_create_river_migration.up.sql +8 -0
- data/migration/postgresql/main/002_initial_schema.down.sql +5 -0
- data/migration/postgresql/main/002_initial_schema.up.sql +96 -0
- data/migration/postgresql/main/003_river_job_tags_non_null.down.sql +3 -0
- data/migration/postgresql/main/003_river_job_tags_non_null.up.sql +3 -0
- data/migration/postgresql/main/004_pending_and_more.down.sql +42 -0
- data/migration/postgresql/main/004_pending_and_more.up.sql +45 -0
- data/migration/postgresql/main/005_migration_unique_client.down.sql +57 -0
- data/migration/postgresql/main/005_migration_unique_client.up.sql +79 -0
- data/migration/postgresql/main/006_bulk_unique.down.sql +16 -0
- data/migration/postgresql/main/006_bulk_unique.up.sql +40 -0
- data/migration/postgresql/main/007_notification_outbox_sqlite_jsonb_and_sql_cleanup.down.sql +56 -0
- data/migration/postgresql/main/007_notification_outbox_sqlite_jsonb_and_sql_cleanup.up.sql +44 -0
- data/migration/postgresql/main/008_job_id_autoincrement.down.sql +3 -0
- data/migration/postgresql/main/008_job_id_autoincrement.up.sql +3 -0
- data/migration/sqlite/main/001_create_river_migration.down.sql +1 -0
- data/migration/sqlite/main/001_create_river_migration.up.sql +8 -0
- data/migration/sqlite/main/002_initial_schema.down.sql +8 -0
- data/migration/sqlite/main/002_initial_schema.up.sql +19 -0
- data/migration/sqlite/main/003_river_job_tags_non_null.down.sql +6 -0
- data/migration/sqlite/main/003_river_job_tags_non_null.up.sql +6 -0
- data/migration/sqlite/main/004_pending_and_more.down.sql +26 -0
- data/migration/sqlite/main/004_pending_and_more.up.sql +33 -0
- data/migration/sqlite/main/005_migration_unique_client.down.sql +37 -0
- data/migration/sqlite/main/005_migration_unique_client.up.sql +64 -0
- data/migration/sqlite/main/006_bulk_unique.down.sql +7 -0
- data/migration/sqlite/main/006_bulk_unique.up.sql +63 -0
- data/migration/sqlite/main/007_notification_outbox_sqlite_jsonb_and_sql_cleanup.down.sql +255 -0
- data/migration/sqlite/main/007_notification_outbox_sqlite_jsonb_and_sql_cleanup.up.sql +261 -0
- data/migration/sqlite/main/008_job_id_autoincrement.down.sql +121 -0
- data/migration/sqlite/main/008_job_id_autoincrement.up.sql +123 -0
- data/sig/client.rbs +95 -0
- data/sig/driver.rbs +170 -0
- data/sig/insert_opts.rbs +25 -0
- data/sig/job.rbs +72 -0
- data/sig/job_persisted_logging/plugin.rbs +29 -0
- data/sig/migrator.rbs +44 -0
- data/sig/riverqueue.rbs +2 -0
- data/sig/runtime.rbs +382 -0
- data/sig/testing.rbs +95 -0
- data/sig/unique_args.rbs +8 -0
- data/sig/unique_bitmask.rbs +8 -0
- data/sig/worker_runner.rbs +22 -0
- metadata +165 -10
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
-- Rebuild river_job so automatically generated IDs are never reused after the
|
|
2
|
+
-- job holding the largest ID is deleted. Unlike PostgreSQL sequences, SQLite's
|
|
3
|
+
-- default ROWID allocator may otherwise reuse that deleted ID.
|
|
4
|
+
|
|
5
|
+
-- Rebuilding river_job would discard schema installed by River Pro. Check
|
|
6
|
+
-- schema objects instead of migration records to also catch manually applied
|
|
7
|
+
-- Pro migrations and the legacy workflow migration line.
|
|
8
|
+
CREATE TEMP TABLE river_job_pro_schema_guard (
|
|
9
|
+
id integer NOT NULL
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
CREATE TEMP TRIGGER river_job_pro_schema_guard_enforce
|
|
13
|
+
BEFORE INSERT ON river_job_pro_schema_guard
|
|
14
|
+
WHEN EXISTS (
|
|
15
|
+
SELECT 1
|
|
16
|
+
FROM /* TEMPLATE: schema */sqlite_master
|
|
17
|
+
WHERE name IN ('river_job_sequence', 'river_job_workflow_scheduling', 'river_workflow')
|
|
18
|
+
)
|
|
19
|
+
BEGIN
|
|
20
|
+
SELECT RAISE(ABORT, 'River SQLite migration 008 cannot run while River Pro schema is installed');
|
|
21
|
+
END;
|
|
22
|
+
|
|
23
|
+
INSERT INTO river_job_pro_schema_guard (id) VALUES (1);
|
|
24
|
+
|
|
25
|
+
DROP TRIGGER river_job_pro_schema_guard_enforce;
|
|
26
|
+
DROP TABLE river_job_pro_schema_guard;
|
|
27
|
+
|
|
28
|
+
DROP INDEX /* TEMPLATE: schema */river_job_kind;
|
|
29
|
+
DROP INDEX /* TEMPLATE: schema */river_job_state_and_finalized_at_index;
|
|
30
|
+
DROP INDEX /* TEMPLATE: schema */river_job_prioritized_fetching_index;
|
|
31
|
+
DROP INDEX /* TEMPLATE: schema */river_job_unique_idx;
|
|
32
|
+
|
|
33
|
+
ALTER TABLE /* TEMPLATE: schema */river_job RENAME TO river_job_old;
|
|
34
|
+
|
|
35
|
+
CREATE TABLE /* TEMPLATE: schema */river_job (
|
|
36
|
+
id integer PRIMARY KEY AUTOINCREMENT,
|
|
37
|
+
args blob NOT NULL DEFAULT (jsonb('{}')),
|
|
38
|
+
attempt integer NOT NULL DEFAULT 0,
|
|
39
|
+
attempted_at timestamp,
|
|
40
|
+
attempted_by blob, -- json
|
|
41
|
+
created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
42
|
+
errors blob, -- json
|
|
43
|
+
finalized_at timestamp,
|
|
44
|
+
kind text NOT NULL,
|
|
45
|
+
max_attempts integer NOT NULL DEFAULT 25,
|
|
46
|
+
metadata blob NOT NULL DEFAULT (jsonb('{}')),
|
|
47
|
+
priority integer NOT NULL DEFAULT 1,
|
|
48
|
+
queue text NOT NULL DEFAULT 'default',
|
|
49
|
+
state text NOT NULL DEFAULT 'available',
|
|
50
|
+
scheduled_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
51
|
+
tags blob NOT NULL DEFAULT (jsonb('[]')),
|
|
52
|
+
unique_key blob,
|
|
53
|
+
unique_states integer,
|
|
54
|
+
CONSTRAINT finalized_or_finalized_at_null CHECK (
|
|
55
|
+
(finalized_at IS NULL AND state NOT IN ('cancelled', 'completed', 'discarded')) OR
|
|
56
|
+
(finalized_at IS NOT NULL AND state IN ('cancelled', 'completed', 'discarded'))
|
|
57
|
+
),
|
|
58
|
+
CONSTRAINT priority_in_range CHECK (priority >= 1 AND priority <= 4),
|
|
59
|
+
CONSTRAINT queue_length CHECK (length(queue) > 0 AND length(queue) < 128),
|
|
60
|
+
CONSTRAINT kind_length CHECK (length(kind) > 0 AND length(kind) < 128),
|
|
61
|
+
CONSTRAINT state_valid CHECK (state IN ('available', 'cancelled', 'completed', 'discarded', 'pending', 'retryable', 'running', 'scheduled'))
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
INSERT INTO /* TEMPLATE: schema */river_job (
|
|
65
|
+
id,
|
|
66
|
+
args,
|
|
67
|
+
attempt,
|
|
68
|
+
attempted_at,
|
|
69
|
+
attempted_by,
|
|
70
|
+
created_at,
|
|
71
|
+
errors,
|
|
72
|
+
finalized_at,
|
|
73
|
+
kind,
|
|
74
|
+
max_attempts,
|
|
75
|
+
metadata,
|
|
76
|
+
priority,
|
|
77
|
+
queue,
|
|
78
|
+
state,
|
|
79
|
+
scheduled_at,
|
|
80
|
+
tags,
|
|
81
|
+
unique_key,
|
|
82
|
+
unique_states
|
|
83
|
+
)
|
|
84
|
+
SELECT
|
|
85
|
+
id,
|
|
86
|
+
args,
|
|
87
|
+
attempt,
|
|
88
|
+
attempted_at,
|
|
89
|
+
attempted_by,
|
|
90
|
+
created_at,
|
|
91
|
+
errors,
|
|
92
|
+
finalized_at,
|
|
93
|
+
kind,
|
|
94
|
+
max_attempts,
|
|
95
|
+
metadata,
|
|
96
|
+
priority,
|
|
97
|
+
queue,
|
|
98
|
+
state,
|
|
99
|
+
scheduled_at,
|
|
100
|
+
tags,
|
|
101
|
+
unique_key,
|
|
102
|
+
unique_states
|
|
103
|
+
FROM /* TEMPLATE: schema */river_job_old;
|
|
104
|
+
|
|
105
|
+
DROP TABLE /* TEMPLATE: schema */river_job_old;
|
|
106
|
+
|
|
107
|
+
CREATE INDEX /* TEMPLATE: schema */river_job_kind ON river_job (kind);
|
|
108
|
+
CREATE INDEX /* TEMPLATE: schema */river_job_state_and_finalized_at_index ON river_job (state, finalized_at) WHERE finalized_at IS NOT NULL;
|
|
109
|
+
CREATE INDEX /* TEMPLATE: schema */river_job_prioritized_fetching_index ON river_job (state, queue, priority, scheduled_at, id);
|
|
110
|
+
CREATE UNIQUE INDEX /* TEMPLATE: schema */river_job_unique_idx ON river_job (unique_key)
|
|
111
|
+
WHERE unique_key IS NOT NULL
|
|
112
|
+
AND unique_states IS NOT NULL
|
|
113
|
+
AND CASE state
|
|
114
|
+
WHEN 'available' THEN unique_states & (1 << 0)
|
|
115
|
+
WHEN 'cancelled' THEN unique_states & (1 << 1)
|
|
116
|
+
WHEN 'completed' THEN unique_states & (1 << 2)
|
|
117
|
+
WHEN 'discarded' THEN unique_states & (1 << 3)
|
|
118
|
+
WHEN 'pending' THEN unique_states & (1 << 4)
|
|
119
|
+
WHEN 'retryable' THEN unique_states & (1 << 5)
|
|
120
|
+
WHEN 'running' THEN unique_states & (1 << 6)
|
|
121
|
+
WHEN 'scheduled' THEN unique_states & (1 << 7)
|
|
122
|
+
ELSE 0
|
|
123
|
+
END >= 1;
|
data/sig/client.rbs
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
module River
|
|
2
|
+
MAX_ATTEMPTS_DEFAULT: Integer
|
|
3
|
+
PRIORITY_DEFAULT: Integer
|
|
4
|
+
QUEUE_DEFAULT: String
|
|
5
|
+
|
|
6
|
+
class Client
|
|
7
|
+
@config: Config
|
|
8
|
+
@driver: _Driver
|
|
9
|
+
@runtime: ClientRuntime
|
|
10
|
+
@time_now_utc: ^() -> Time
|
|
11
|
+
|
|
12
|
+
attr_reader config: Config
|
|
13
|
+
attr_reader driver: _Driver
|
|
14
|
+
|
|
15
|
+
def initialize: (_Driver driver, ?config: Config?) -> void
|
|
16
|
+
def __finish_claimed_job: (JobRow, ?Exception?) -> untyped
|
|
17
|
+
def __perform_job: (Integer, ?allow_scheduled: bool) -> untyped
|
|
18
|
+
def __interrupt_workers: () -> untyped
|
|
19
|
+
def __runtime_healthy?: () -> bool
|
|
20
|
+
def id: () -> String
|
|
21
|
+
def insert: (jobArgs, ?insert_opts: InsertOpts?, ?max_attempts: Integer?,
|
|
22
|
+
?metadata: Hash[String | Symbol, untyped]?, ?priority: Integer?, ?queue: (String | Symbol)?,
|
|
23
|
+
?scheduled_at: Time?, ?state: jobStateInput?, ?tags: Array[String]?, ?unique_opts: UniqueOpts?) -> JobInsertResult
|
|
24
|
+
def insert_many: (Array[jobArgs | InsertManyParams]) -> Array[JobInsertResult]
|
|
25
|
+
def job_cancel: (Integer) -> JobRow
|
|
26
|
+
def job_delete: (Integer) -> JobRow
|
|
27
|
+
def job_delete_many: (?JobListParams?, ?after: untyped, ?after_id: untyped,
|
|
28
|
+
?ids: untyped, ?kinds: untyped, ?limit: untyped, ?metadata: untyped, ?priorities: untyped,
|
|
29
|
+
?queues: untyped, ?sort_by: untyped, ?sort_order: untyped, ?states: untyped,
|
|
30
|
+
?tags_all: untyped, ?tags_any: untyped) -> untyped
|
|
31
|
+
def job_get: (Integer) -> JobRow
|
|
32
|
+
def job_list: (?JobListParams?, ?after: untyped, ?after_id: untyped,
|
|
33
|
+
?ids: untyped, ?kinds: untyped, ?limit: untyped, ?metadata: untyped, ?priorities: untyped,
|
|
34
|
+
?queues: untyped, ?sort_by: untyped, ?sort_order: untyped, ?states: untyped,
|
|
35
|
+
?tags_all: untyped, ?tags_any: untyped) -> untyped
|
|
36
|
+
def job_retry: (Integer) -> JobRow
|
|
37
|
+
def job_update: (Integer, ?JobUpdateParams?, ?attempt: untyped, ?attempted_at: untyped,
|
|
38
|
+
?attempted_by: untyped, ?errors: untyped, ?finalized_at: untyped, ?max_attempts: untyped,
|
|
39
|
+
?metadata: untyped, ?state: untyped) -> JobRow
|
|
40
|
+
def periodic_jobs: () -> PeriodicJobBundle
|
|
41
|
+
def queue_add: (String | Symbol, QueueConfig | Integer) -> self
|
|
42
|
+
def queue_get: (String | Symbol) -> Queue
|
|
43
|
+
def queue_list: (?max: Integer) -> untyped
|
|
44
|
+
def queue_pause: (String | Symbol) -> bool
|
|
45
|
+
def queue_remove: (String | Symbol) -> self
|
|
46
|
+
def queue_resume: (String | Symbol) -> bool
|
|
47
|
+
def queue_update: (String | Symbol, metadata: Hash[untyped, untyped]) -> Queue
|
|
48
|
+
def start: () -> self
|
|
49
|
+
def started?: () -> bool
|
|
50
|
+
def stop: (?wait: bool) -> self
|
|
51
|
+
def stop_and_cancel: () -> self
|
|
52
|
+
def stopped?: () -> bool
|
|
53
|
+
def subscribe: (*Symbol | String kinds, ?buffer_size: Integer) -> Subscription
|
|
54
|
+
|
|
55
|
+
DEFAULT_UNIQUE_STATES: Array[jobStateAll]
|
|
56
|
+
EMPTY_INSERT_OPTS: InsertOpts
|
|
57
|
+
REQUIRED_UNIQUE_STATES: Array[jobStateAll]
|
|
58
|
+
TAG_RE: Regexp
|
|
59
|
+
|
|
60
|
+
private def insert_and_check_unique_job: (Driver::JobInsertParams) -> JobInsertResult
|
|
61
|
+
private def make_insert_params: (jobArgs, InsertOpts) -> Driver::JobInsertParams
|
|
62
|
+
private def make_unique_key_and_bitmask: (Driver::JobInsertParams, UniqueOpts) -> [String, String]
|
|
63
|
+
private def run_insert_plugins: (Array[Driver::JobInsertParams]) { () -> Array[JobInsertResult] } -> Array[JobInsertResult]
|
|
64
|
+
private def truncate_time: (Time, Integer | Rational) -> Time
|
|
65
|
+
private def uint64_to_int64: (Integer) -> Integer
|
|
66
|
+
private def validate_tags: (Array[String]) -> Array[String]
|
|
67
|
+
private def validate_unique_states: (Array[jobStateInput]) -> Array[jobStateAll]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
class InsertManyParams
|
|
71
|
+
@args: jobArgs
|
|
72
|
+
@insert_opts: InsertOpts?
|
|
73
|
+
|
|
74
|
+
attr_reader args: jobArgs
|
|
75
|
+
attr_reader insert_opts: InsertOpts?
|
|
76
|
+
|
|
77
|
+
def initialize: (jobArgs job, ?insert_opts: InsertOpts?, ?max_attempts: Integer?,
|
|
78
|
+
?metadata: Hash[String | Symbol, untyped]?, ?priority: Integer?, ?queue: (String | Symbol)?,
|
|
79
|
+
?scheduled_at: Time?, ?state: jobStateInput?, ?tags: Array[String]?, ?unique_opts: UniqueOpts?) -> void
|
|
80
|
+
def is_a?: (Class) -> bool
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
class JobInsertResult
|
|
84
|
+
@job: JobRow
|
|
85
|
+
@unique_skipped_as_duplicate: bool
|
|
86
|
+
|
|
87
|
+
attr_reader job: JobRow
|
|
88
|
+
def unique_skipped_as_duplicate?: () -> bool
|
|
89
|
+
alias unique_skipped_as_duplicated unique_skipped_as_duplicate?
|
|
90
|
+
|
|
91
|
+
def initialize: (JobRow job, unique_skipped_as_duplicated: bool) -> void
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
class InsertResult = JobInsertResult
|
|
95
|
+
end
|
data/sig/driver.rbs
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
module River
|
|
2
|
+
interface _Driver
|
|
3
|
+
def respond_to?: (Symbol, ?bool) -> bool
|
|
4
|
+
def init_driver: () -> void
|
|
5
|
+
def migration_backend: () -> Symbol
|
|
6
|
+
def migration_connection: [A] () { (untyped) -> A } -> A
|
|
7
|
+
def advisory_lock: (Integer) -> void
|
|
8
|
+
def job_cancel: (Integer, ?now: Time) -> JobRow?
|
|
9
|
+
def job_delete: (Integer) -> JobRow?
|
|
10
|
+
def job_delete_finalized: (**untyped) -> Integer
|
|
11
|
+
def job_delete_if_running: (Integer) -> bool
|
|
12
|
+
def job_delete_many: (JobListParams) -> Array[JobRow]
|
|
13
|
+
def job_get_available: (queue: String, max: Integer, attempted_by: String, ?kinds: Array[String]?, ?now: Time) -> Array[JobRow]
|
|
14
|
+
def job_claim: (id: Integer, attempted_by: String, ?allow_scheduled: bool, ?now: Time) -> JobRow?
|
|
15
|
+
def job_get_cancelled_ids: (Array[Integer]) -> Array[Integer]
|
|
16
|
+
def job_complete: (id: Integer, finalized_at: Time, ?metadata: Hash[untyped, untyped]?, ?now: Time) -> (JobRow | :cancelled)?
|
|
17
|
+
def job_get_by_kind_and_unique_properties: (Driver::JobGetByKindAndUniquePropertiesParam) -> JobRow?
|
|
18
|
+
def job_insert: (Driver::JobInsertParams) -> [JobRow, bool]
|
|
19
|
+
def job_insert_many: (Array[Driver::JobInsertParams]) -> Array[[JobRow, bool]]
|
|
20
|
+
def job_metadata_merge: (Integer, Hash[untyped, untyped]) -> JobRow?
|
|
21
|
+
def job_rescue_stuck: (**untyped) -> Integer
|
|
22
|
+
def job_retry: (Integer, ?now: Time) -> JobRow?
|
|
23
|
+
def job_schedule: (?now: Time, ?max: Integer) -> Integer
|
|
24
|
+
def job_set_state_if_running: (**untyped) -> JobRow?
|
|
25
|
+
def job_update: (Integer, JobUpdateParams) -> JobRow?
|
|
26
|
+
def leader_acquire: (String, ?ttl: Integer, ?now: Time) -> bool
|
|
27
|
+
def leader_release: (String) -> untyped
|
|
28
|
+
def leader_renew: (String, ?ttl: Integer, ?now: Time) -> bool
|
|
29
|
+
def notification_delete_before: (horizon: Time, ?max: Integer) -> Integer
|
|
30
|
+
def queue_get: (String) -> Queue?
|
|
31
|
+
def queue_list: (?max: Integer) -> Array[Queue]
|
|
32
|
+
def queue_pause: (String, ?now: Time) -> untyped
|
|
33
|
+
def queue_resume: (String, ?now: Time) -> untyped
|
|
34
|
+
def queue_update: (String, metadata: Hash[untyped, untyped], ?now: Time) -> Queue?
|
|
35
|
+
def queue_upsert: (String, ?metadata: Hash[untyped, untyped], ?now: Time) -> Queue?
|
|
36
|
+
def transaction: [T] () { () -> T } -> T
|
|
37
|
+
|
|
38
|
+
# this set of methods is used only in tests
|
|
39
|
+
def advisory_lock_try: (Integer) -> bool
|
|
40
|
+
def job_get_by_id: (Integer) -> JobRow?
|
|
41
|
+
def job_list: (?JobListParams | :all) -> Array[JobRow]
|
|
42
|
+
def rollback_exception: -> Exception
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
module Driver
|
|
46
|
+
class JobRowDecoder
|
|
47
|
+
ZERO_TIME: Time
|
|
48
|
+
@errors: Array[String]
|
|
49
|
+
def self.attempt_error: (untyped) -> AttemptError
|
|
50
|
+
def self.error_time: (untyped) -> Time
|
|
51
|
+
def self.error_integer: (untyped) -> Integer
|
|
52
|
+
def self.error_string: (untyped) -> String
|
|
53
|
+
def initialize: () -> void
|
|
54
|
+
def json: (Symbol, untyped, ?type: Class?, ?strings: bool, ?default: untyped) -> untyped
|
|
55
|
+
def decoded: (Symbol, untyped, ?type: Class?, ?strings: bool, ?default: untyped) -> untyped
|
|
56
|
+
def finish: (JobRow) -> JobRow
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
class PostgresCapabilities
|
|
60
|
+
attr_reader supports_listen_notify: bool
|
|
61
|
+
attr_reader unique_insert_mode: :metadata_nonce | :returning_old | :xmax
|
|
62
|
+
attr_reader unique_insert_sql: String
|
|
63
|
+
def initialize: (product: String, version_num: Integer, yb_listen_notify_enabled: bool) -> void
|
|
64
|
+
|
|
65
|
+
class Cache
|
|
66
|
+
@mutex: Mutex
|
|
67
|
+
@values: Hash[untyped, PostgresCapabilities]
|
|
68
|
+
def initialize: () -> void
|
|
69
|
+
def fetch: (untyped) { () -> PostgresCapabilities } -> PostgresCapabilities
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
class JobGetByKindAndUniquePropertiesParam
|
|
74
|
+
attr_accessor created_at: [Time, Time]?
|
|
75
|
+
attr_accessor encoded_args: String?
|
|
76
|
+
attr_accessor kind: String
|
|
77
|
+
attr_accessor queue: String?
|
|
78
|
+
attr_accessor state: Array[jobStateAll]?
|
|
79
|
+
|
|
80
|
+
def initialize: (kind: String, ?created_at: [Time, Time]?, ?encoded_args: String?, ?queue: String?, ?state: Array[jobStateAll]?) -> void
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
class JobInsertParams
|
|
84
|
+
attr_accessor args: untyped
|
|
85
|
+
attr_accessor encoded_args: String
|
|
86
|
+
attr_accessor kind: String
|
|
87
|
+
attr_accessor max_attempts: Integer
|
|
88
|
+
attr_accessor metadata: Hash[untyped, untyped]
|
|
89
|
+
attr_accessor priority: Integer
|
|
90
|
+
attr_accessor queue: String
|
|
91
|
+
attr_accessor scheduled_at: Time?
|
|
92
|
+
attr_accessor state: jobStateAll
|
|
93
|
+
attr_accessor tags: Array[String]?
|
|
94
|
+
attr_accessor unique_key: String?
|
|
95
|
+
attr_accessor unique_states: String?
|
|
96
|
+
|
|
97
|
+
def initialize: (?args: untyped, encoded_args: String, kind: String, max_attempts: Integer, ?metadata: Hash[untyped, untyped], priority: Integer, queue: String, scheduled_at: Time?, state: jobStateAll, tags: Array[String]?, ?unique_key: String?, ?unique_states: String?) -> void
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
module Runtime
|
|
101
|
+
def runtime_read_job: (untyped) -> untyped
|
|
102
|
+
def runtime_decode_sqlite_job: (untyped) -> JobRow
|
|
103
|
+
def runtime_decode_postgres_job: (untyped) -> JobRow
|
|
104
|
+
@postgres_capabilities_cache: PostgresCapabilities::Cache
|
|
105
|
+
def init_driver: () -> void
|
|
106
|
+
def postgres_capabilities: () -> PostgresCapabilities
|
|
107
|
+
def postgres_notify_insert: (Array[JobInsertParams]) -> void
|
|
108
|
+
def job_get_cancelled_ids: (Array[Integer]) -> Array[Integer]
|
|
109
|
+
def job_complete: (id: untyped, finalized_at: untyped, ?metadata: untyped, ?now: untyped) -> untyped
|
|
110
|
+
def job_cancel: (untyped, ?now: untyped) -> untyped
|
|
111
|
+
def job_delete: (untyped) -> untyped
|
|
112
|
+
def job_delete_finalized: (retention: untyped, ?now: untyped, ?max: untyped) -> untyped
|
|
113
|
+
def job_delete_if_running: (untyped) -> untyped
|
|
114
|
+
def job_delete_many: (untyped) -> untyped
|
|
115
|
+
def job_get_available: (queue: untyped, max: untyped, attempted_by: untyped, ?kinds: untyped, ?now: untyped) -> untyped
|
|
116
|
+
def job_claim: (id: untyped, attempted_by: untyped, ?allow_scheduled: untyped, ?now: untyped) -> untyped
|
|
117
|
+
private def runtime_claim_jobs: (untyped, untyped, untyped, untyped) -> untyped
|
|
118
|
+
def job_list: (?untyped) -> untyped
|
|
119
|
+
def job_metadata_merge: (untyped, untyped) -> untyped
|
|
120
|
+
def job_rescue_stuck: (horizon: untyped, retry_policy: untyped, ?now: untyped, ?max: untyped) -> untyped
|
|
121
|
+
def job_retry: (untyped, ?now: untyped) -> untyped
|
|
122
|
+
def job_schedule: (?now: untyped, ?max: untyped) -> untyped
|
|
123
|
+
def job_set_state_if_running: (id: untyped, state: untyped, ?now: untyped, ?attempt: untyped, ?error: untyped, ?finalized_at: untyped, ?metadata: untyped, ?scheduled_at: untyped) -> untyped
|
|
124
|
+
def job_update: (untyped, untyped) -> untyped
|
|
125
|
+
def leader_acquire: (untyped, ?ttl: untyped, ?now: untyped) -> untyped
|
|
126
|
+
def leader_release: (untyped) -> untyped
|
|
127
|
+
def leader_renew: (untyped, ?ttl: untyped, ?now: untyped) -> untyped
|
|
128
|
+
def notification_delete_before: (horizon: untyped, ?max: untyped) -> untyped
|
|
129
|
+
def queue_get: (untyped) -> untyped
|
|
130
|
+
def queue_list: (?max: untyped) -> untyped
|
|
131
|
+
def queue_pause: (untyped, ?now: untyped) -> untyped
|
|
132
|
+
def queue_resume: (untyped, ?now: untyped) -> untyped
|
|
133
|
+
def queue_update: (untyped, metadata: untyped, ?now: untyped) -> untyped
|
|
134
|
+
def queue_upsert: (untyped, ?metadata: untyped, ?now: untyped) -> untyped
|
|
135
|
+
|
|
136
|
+
private
|
|
137
|
+
|
|
138
|
+
def job_get_by_id: (untyped) -> untyped
|
|
139
|
+
def runtime_append_error: (untyped) -> untyped
|
|
140
|
+
def runtime_cancel_attempted: () -> untyped
|
|
141
|
+
def runtime_connection_pool: () -> untyped
|
|
142
|
+
def runtime_cursor_clause: (untyped) -> String
|
|
143
|
+
def runtime_execute: (String) -> untyped
|
|
144
|
+
def runtime_in_clause: (untyped, untyped) -> untyped
|
|
145
|
+
def runtime_job_list_without_params: () -> untyped
|
|
146
|
+
def runtime_job_rows: (String) -> untyped
|
|
147
|
+
def runtime_json: (untyped) -> untyped
|
|
148
|
+
def runtime_merge_metadata: (untyped) -> untyped
|
|
149
|
+
def runtime_metadata_equals: (untyped, untyped) -> untyped
|
|
150
|
+
def runtime_nullable_time: (untyped) -> untyped
|
|
151
|
+
def runtime_notify: (String, untyped) -> untyped
|
|
152
|
+
def sqlite_insert_nonces: (Array[JobInsertParams]) -> Array[String]
|
|
153
|
+
def runtime_parse_json: (untyped) -> untyped
|
|
154
|
+
def runtime_parse_time: (untyped) -> untyped
|
|
155
|
+
def runtime_postgres?: () -> bool
|
|
156
|
+
def runtime_query_rows: (String) -> untyped
|
|
157
|
+
def runtime_queue_columns: () -> untyped
|
|
158
|
+
def runtime_queue_from_row: (untyped) -> untyped
|
|
159
|
+
def runtime_quote: (untyped) -> String
|
|
160
|
+
def runtime_returning_ids: (untyped) -> untyped
|
|
161
|
+
def runtime_state: (untyped) -> untyped
|
|
162
|
+
def runtime_tag_contains: (untyped) -> untyped
|
|
163
|
+
def runtime_time: (untyped) -> untyped
|
|
164
|
+
def runtime_unique_violation_class: () -> singleton(Exception)
|
|
165
|
+
def runtime_update_value: (untyped, untyped) -> untyped
|
|
166
|
+
def runtime_value: (untyped, untyped) -> untyped
|
|
167
|
+
def transaction: () { () -> untyped } -> untyped
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
data/sig/insert_opts.rbs
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module River
|
|
2
|
+
class InsertOpts
|
|
3
|
+
attr_accessor max_attempts: Integer?
|
|
4
|
+
attr_accessor metadata: Hash[String | Symbol, untyped]?
|
|
5
|
+
attr_accessor priority: Integer?
|
|
6
|
+
attr_accessor queue: (String | Symbol)?
|
|
7
|
+
attr_accessor scheduled_at: Time?
|
|
8
|
+
attr_accessor state: jobStateInput?
|
|
9
|
+
attr_accessor tags: Array[String]?
|
|
10
|
+
attr_accessor unique_opts: UniqueOpts?
|
|
11
|
+
|
|
12
|
+
def initialize: (?max_attempts: Integer?, ?metadata: Hash[String | Symbol, untyped]?, ?priority: Integer?, ?queue: (String | Symbol)?, ?scheduled_at: Time?, ?state: jobStateInput?, ?tags: Array[String]?, ?unique_opts: UniqueOpts?) -> void
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
class UniqueOpts
|
|
16
|
+
def empty?: () -> bool
|
|
17
|
+
attr_accessor by_args: bool? | Array[String | Symbol | Array[String | Symbol]]?
|
|
18
|
+
attr_accessor by_period: (Integer | Rational)?
|
|
19
|
+
attr_accessor by_queue: bool?
|
|
20
|
+
attr_accessor by_state: Array[jobStateInput]?
|
|
21
|
+
attr_accessor exclude_kind: bool?
|
|
22
|
+
|
|
23
|
+
def initialize: (?by_args: bool? | Array[String | Symbol | Array[String | Symbol]]?, ?by_period: (Integer | Rational)?, ?by_queue: bool?, ?by_state: Array[jobStateInput]?, ?exclude_kind: bool?) -> void
|
|
24
|
+
end
|
|
25
|
+
end
|
data/sig/job.rbs
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
module River
|
|
2
|
+
JOB_STATE_AVAILABLE: "available"
|
|
3
|
+
JOB_STATE_CANCELLED: "cancelled"
|
|
4
|
+
JOB_STATE_COMPLETED: "completed"
|
|
5
|
+
JOB_STATE_DISCARDED: "discarded"
|
|
6
|
+
JOB_STATE_PENDING: "pending"
|
|
7
|
+
JOB_STATE_RETRYABLE: "retryable"
|
|
8
|
+
JOB_STATE_RUNNING: "running"
|
|
9
|
+
JOB_STATE_SCHEDULED: "scheduled"
|
|
10
|
+
|
|
11
|
+
type jobStateAll = "available" | "cancelled" | "completed" | "discarded" | "pending" | "retryable" | "running" | "scheduled"
|
|
12
|
+
type jobStateInput = jobStateAll | :available | :cancelled | :completed | :discarded | :pending | :retryable | :running | :scheduled
|
|
13
|
+
|
|
14
|
+
interface _JobArgs
|
|
15
|
+
def is_a?: (Class) -> bool
|
|
16
|
+
def kind: () -> (String | Symbol)
|
|
17
|
+
def respond_to?: (Symbol) -> bool
|
|
18
|
+
def to_json: () -> String
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
interface _JobArgsWithInsertOpts
|
|
22
|
+
include _JobArgs
|
|
23
|
+
|
|
24
|
+
def insert_opts: () -> InsertOpts?
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
type jobArgs = _JobArgs | _JobArgsWithInsertOpts
|
|
28
|
+
|
|
29
|
+
class JobArgsHash
|
|
30
|
+
@hash: Hash[String | Symbol, untyped]
|
|
31
|
+
@kind: String
|
|
32
|
+
|
|
33
|
+
attr_reader kind: String
|
|
34
|
+
|
|
35
|
+
def initialize: (String | Symbol kind, Hash[String | Symbol, untyped] hash) -> void
|
|
36
|
+
def to_json: () -> String
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class JobRow
|
|
40
|
+
attr_accessor __decode_error: JobRowDecodeError?
|
|
41
|
+
attr_accessor args: Hash[String, untyped]
|
|
42
|
+
attr_accessor attempt: Integer
|
|
43
|
+
attr_accessor attempted_at: Time?
|
|
44
|
+
attr_accessor attempted_by: Array[String]?
|
|
45
|
+
attr_accessor created_at: Time
|
|
46
|
+
attr_accessor errors: Array[AttemptError]?
|
|
47
|
+
attr_accessor finalized_at: Time?
|
|
48
|
+
attr_accessor id: Integer
|
|
49
|
+
attr_accessor kind: String
|
|
50
|
+
attr_accessor max_attempts: Integer
|
|
51
|
+
attr_accessor metadata: Hash[String, untyped]
|
|
52
|
+
attr_accessor priority: Integer
|
|
53
|
+
attr_accessor queue: String
|
|
54
|
+
attr_accessor scheduled_at: Time
|
|
55
|
+
attr_accessor state: jobStateAll
|
|
56
|
+
attr_accessor tags: Array[String]?
|
|
57
|
+
attr_accessor unique_key: String?
|
|
58
|
+
attr_accessor unique_states: Array[jobStateAll]?
|
|
59
|
+
|
|
60
|
+
def initialize: (id: Integer, args: Hash[String, untyped], attempt: Integer, ?attempted_at: Time?, ?attempted_by: Array[String]?, created_at: Time, ?errors: Array[AttemptError]?, ?finalized_at: Time?, kind: String, max_attempts: Integer, metadata: Hash[String, untyped], priority: Integer, queue: String, scheduled_at: Time, state: jobStateAll, ?tags: Array[String]?, ?unique_key: String?, ?unique_states: Array[jobStateAll]?) -> void
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
class AttemptError
|
|
64
|
+
attr_accessor at: Time
|
|
65
|
+
attr_accessor attempt: Integer
|
|
66
|
+
attr_accessor error: String
|
|
67
|
+
attr_accessor trace: String
|
|
68
|
+
|
|
69
|
+
def initialize: (at: Time, attempt: Integer, error: String, trace: String) -> void
|
|
70
|
+
def to_h: () -> Hash[Symbol, untyped]
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module River
|
|
2
|
+
module JobPersistedLogging
|
|
3
|
+
class Plugin
|
|
4
|
+
@logger_factory: (^(Buffer) -> untyped)?
|
|
5
|
+
@max_size_bytes: Integer
|
|
6
|
+
@max_total_bytes: Integer
|
|
7
|
+
|
|
8
|
+
def initialize: (?max_size_bytes: Integer, ?max_total_bytes: Integer) ?{ (Buffer) -> untyped } -> void
|
|
9
|
+
def work: [T] (Job, ^() -> T) -> T
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def persist_log: (Job, Buffer) -> void
|
|
14
|
+
|
|
15
|
+
class Buffer
|
|
16
|
+
@closed: bool
|
|
17
|
+
@data: String
|
|
18
|
+
@limit: Integer
|
|
19
|
+
@mutex: Mutex
|
|
20
|
+
@truncated: bool
|
|
21
|
+
|
|
22
|
+
def initialize: (Integer) -> void
|
|
23
|
+
def close: () -> nil
|
|
24
|
+
def finish: () -> [String, bool]
|
|
25
|
+
def write: (_ToS) -> Integer
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
data/sig/migrator.rbs
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
class Gem::Specification
|
|
2
|
+
def self.find_all_by_name: (String, *untyped) -> Array[Gem::Specification]
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
module River
|
|
6
|
+
module MigrationCLI
|
|
7
|
+
def self.detect_driver: () -> String
|
|
8
|
+
def self.run: (Array[String], ?err: untyped, ?out: untyped) -> Integer
|
|
9
|
+
end
|
|
10
|
+
class Migrator
|
|
11
|
+
class Migration < Data
|
|
12
|
+
attr_reader version: Integer
|
|
13
|
+
attr_reader name: String
|
|
14
|
+
attr_reader sql_up: String
|
|
15
|
+
attr_reader sql_down: String
|
|
16
|
+
def self.new: (Integer, untyped, String, String) -> instance
|
|
17
|
+
end
|
|
18
|
+
class Status < Data
|
|
19
|
+
attr_reader version: Integer
|
|
20
|
+
attr_reader name: String
|
|
21
|
+
attr_reader applied: bool
|
|
22
|
+
def self.new: (Integer, String, bool) -> instance
|
|
23
|
+
end
|
|
24
|
+
@backend: Symbol
|
|
25
|
+
@connection: untyped
|
|
26
|
+
@driver: untyped
|
|
27
|
+
@line: String
|
|
28
|
+
@migrations: Array[Migration]
|
|
29
|
+
@mutex: Mutex
|
|
30
|
+
@requested_schema: untyped
|
|
31
|
+
@schema: untyped
|
|
32
|
+
attr_reader migrations: Array[Migration]
|
|
33
|
+
def initialize: (untyped, ?line: String, ?migrations_path: String, ?schema: untyped) -> void
|
|
34
|
+
def migrate: (?direction: Symbol, ?dry_run: bool, ?steps: untyped, ?target: untyped) -> Array[Migration]
|
|
35
|
+
def status: () -> Array[Status]
|
|
36
|
+
private
|
|
37
|
+
def execute: (String) -> untyped
|
|
38
|
+
def existing_versions: () -> Array[Integer]
|
|
39
|
+
def line_column?: () -> bool
|
|
40
|
+
def query: (String) -> untyped
|
|
41
|
+
def session: [A] (?lock: bool) { () -> A } -> A
|
|
42
|
+
def table: () -> String
|
|
43
|
+
end
|
|
44
|
+
end
|
data/sig/riverqueue.rbs
ADDED