riverqueue-sequel 0.11.0 → 0.13.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/lib/driver.rb +197 -173
- data/lib/riverqueue-sequel.rb +3 -0
- metadata +19 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bb0d975eb6921905735667d53aeba24da81b090f92af870935bd112cbc9a7b5e
|
|
4
|
+
data.tar.gz: 9f4b514ebc0ac579caeb7eacec5227a9e9e2b497cbfbd9d15366a3795e271ee9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9dc23c4d8a76b28a7d39e3422b011db46d648c3e5c7adfd652e6fa391643a003617362f5edc1e17e71722c1aa5f52d0db35fc95315242c28ab9d4f534c557620
|
|
7
|
+
data.tar.gz: 8fdce85797d7deefb7b82223ac81531bc61962b32a43b96bd29452a8f88e8352dedd2fac1da555e5e194991f281f9c3d5d4468bed82a2c6410404218b63adaf1
|
data/lib/driver.rb
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require "securerandom"
|
|
2
4
|
|
|
3
5
|
module River::Driver
|
|
4
|
-
# Provides a Sequel driver for River
|
|
6
|
+
# Provides a Sequel driver for River supporting PostgreSQL, YugabyteDB, and SQLite.
|
|
5
7
|
#
|
|
6
8
|
# Used in conjunction with a River client like:
|
|
7
9
|
#
|
|
@@ -14,7 +16,88 @@ module River::Driver
|
|
|
14
16
|
# client = River::Client.new(River::Driver::Sequel.new(DB))
|
|
15
17
|
#
|
|
16
18
|
class Sequel
|
|
17
|
-
|
|
19
|
+
include River::Driver::Runtime
|
|
20
|
+
|
|
21
|
+
# Creates a driver backed by a connected Sequel::Database for PostgreSQL or
|
|
22
|
+
# SQLite.
|
|
23
|
+
def initialize(db)
|
|
24
|
+
@db = db
|
|
25
|
+
@postgres_capabilities_cache = PostgresCapabilities::Cache.new
|
|
26
|
+
@is_sqlite = (db.database_type == :sqlite)
|
|
27
|
+
|
|
28
|
+
unless @is_sqlite
|
|
29
|
+
db.extension(:pg_array)
|
|
30
|
+
db.extension(:pg_json)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def job_get_by_id(id)
|
|
35
|
+
if @is_sqlite
|
|
36
|
+
row = sqlite_job_rows("WHERE id = ? LIMIT 1", id).first
|
|
37
|
+
row ? sqlite_to_job_row_from_raw(row) : nil
|
|
38
|
+
else
|
|
39
|
+
row = @db[:river_job].where(id: id).first
|
|
40
|
+
row ? to_job_row(row) : nil
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def job_insert(insert_params)
|
|
45
|
+
job_insert_many([insert_params]).first
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def job_insert_many(insert_params_array)
|
|
49
|
+
return [] if insert_params_array.empty?
|
|
50
|
+
|
|
51
|
+
return sqlite_job_insert_many(insert_params_array) if @is_sqlite
|
|
52
|
+
|
|
53
|
+
transaction do
|
|
54
|
+
results = postgres_job_insert_many(insert_params_array)
|
|
55
|
+
postgres_notify_insert(insert_params_array)
|
|
56
|
+
results
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def job_list(params = :all)
|
|
61
|
+
return super unless params == :all
|
|
62
|
+
|
|
63
|
+
runtime_job_rows("ORDER BY id")
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def rollback_exception
|
|
67
|
+
::Sequel::Rollback
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Backend used by River::Migrator.
|
|
71
|
+
def migration_backend = @is_sqlite ? :sqlite : :postgresql
|
|
72
|
+
|
|
73
|
+
# Pins a raw connection for the complete migration operation.
|
|
74
|
+
def migration_connection
|
|
75
|
+
@db.synchronize do |connection|
|
|
76
|
+
raise River::Error, "migrations cannot run inside an application transaction" if @db.in_transaction?
|
|
77
|
+
|
|
78
|
+
yield connection
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Runs the block in a Sequel transaction or savepoint and returns the
|
|
83
|
+
# block's result.
|
|
84
|
+
def transaction
|
|
85
|
+
block_error = nil
|
|
86
|
+
@db.transaction(savepoint: true) do
|
|
87
|
+
yield
|
|
88
|
+
rescue ArgumentError => error
|
|
89
|
+
block_error = error
|
|
90
|
+
raise
|
|
91
|
+
end
|
|
92
|
+
rescue ::Sequel::DatabaseError => error
|
|
93
|
+
# SQLite treats ArgumentError as an adapter error, even when it came
|
|
94
|
+
# from an application callback. Preserve that error after rollback.
|
|
95
|
+
raise block_error if block_error && error.wrapped_exception.equal?(block_error)
|
|
96
|
+
|
|
97
|
+
raise
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
SQLITE_CONFLICT_WHERE = <<~SQL.chomp.freeze
|
|
18
101
|
unique_key IS NOT NULL
|
|
19
102
|
AND unique_states IS NOT NULL
|
|
20
103
|
AND CASE state
|
|
@@ -29,105 +112,147 @@ module River::Driver
|
|
|
29
112
|
ELSE 0
|
|
30
113
|
END >= 1
|
|
31
114
|
SQL
|
|
32
|
-
private_constant :SQLITE_CONFLICT_WHERE
|
|
33
115
|
|
|
34
116
|
# SQLite 3.45+ may store JSON as binary JSONB. Always project JSON columns
|
|
35
117
|
# through json() so this driver can read both the current JSONB format and
|
|
36
118
|
# the text JSON used by River migrations through version 006. Cast times to
|
|
37
119
|
# text so Sequel doesn't interpret timezone-less SQLite timestamps in the
|
|
38
|
-
# process timezone.
|
|
39
|
-
|
|
120
|
+
# process timezone. Flag 10 validates JSONB contents, not just its header,
|
|
121
|
+
# so damaged blobs reach the row decoder without aborting the SQL query.
|
|
122
|
+
SQLITE_JOB_COLUMNS = <<~SQL.chomp.freeze
|
|
40
123
|
id,
|
|
41
|
-
json(args) AS args,
|
|
124
|
+
CASE WHEN json_valid(args, 10) THEN json(args) ELSE args END AS args,
|
|
42
125
|
attempt,
|
|
43
126
|
CAST(attempted_at AS text) AS attempted_at,
|
|
44
|
-
json(attempted_by) AS attempted_by,
|
|
127
|
+
CASE WHEN json_valid(attempted_by, 10) THEN json(attempted_by) ELSE attempted_by END AS attempted_by,
|
|
45
128
|
CAST(created_at AS text) AS created_at,
|
|
46
|
-
json(errors) AS errors,
|
|
129
|
+
CASE WHEN json_valid(errors, 10) THEN json(errors) ELSE errors END AS errors,
|
|
47
130
|
CAST(finalized_at AS text) AS finalized_at,
|
|
48
131
|
kind,
|
|
49
132
|
max_attempts,
|
|
50
|
-
json(metadata) AS metadata,
|
|
133
|
+
CASE WHEN json_valid(metadata, 10) THEN json(metadata) ELSE metadata END AS metadata,
|
|
51
134
|
priority,
|
|
52
135
|
queue,
|
|
53
136
|
state,
|
|
54
137
|
CAST(scheduled_at AS text) AS scheduled_at,
|
|
55
|
-
json(tags) AS tags,
|
|
138
|
+
CASE WHEN json_valid(tags, 10) THEN json(tags) ELSE tags END AS tags,
|
|
56
139
|
unique_key,
|
|
57
140
|
unique_states
|
|
58
141
|
SQL
|
|
59
|
-
private_constant :SQLITE_JOB_COLUMNS
|
|
60
142
|
|
|
61
|
-
|
|
62
|
-
private_constant :SQLITE_UNIQUE_NONCE_KEY
|
|
143
|
+
UNIQUE_INSERT_METADATA_KEY = "river:unique_nonce"
|
|
63
144
|
|
|
64
|
-
|
|
65
|
-
@db = db
|
|
66
|
-
@is_sqlite = (db.database_type == :sqlite)
|
|
145
|
+
private_constant :SQLITE_CONFLICT_WHERE, :SQLITE_JOB_COLUMNS, :UNIQUE_INSERT_METADATA_KEY
|
|
67
146
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
db.extension(:pg_json)
|
|
71
|
-
end
|
|
147
|
+
private def format_time(time)
|
|
148
|
+
time.getutc.round(3).strftime("%Y-%m-%d %H:%M:%S.%3N")
|
|
72
149
|
end
|
|
73
150
|
|
|
74
|
-
def
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
151
|
+
private def postgres_insert_params_to_hash(insert_params, nonce)
|
|
152
|
+
metadata = insert_params.metadata || {}
|
|
153
|
+
metadata = metadata.merge(UNIQUE_INSERT_METADATA_KEY => nonce) if nonce
|
|
154
|
+
{
|
|
155
|
+
args: insert_params.encoded_args,
|
|
156
|
+
kind: insert_params.kind,
|
|
157
|
+
max_attempts: insert_params.max_attempts,
|
|
158
|
+
metadata: ::Sequel.pg_jsonb(metadata),
|
|
159
|
+
priority: insert_params.priority,
|
|
160
|
+
queue: insert_params.queue,
|
|
161
|
+
scheduled_at: insert_params.scheduled_at,
|
|
162
|
+
state: insert_params.state,
|
|
163
|
+
tags: ::Sequel.pg_array(insert_params.tags || [], :text),
|
|
164
|
+
unique_key: insert_params.unique_key ? ::Sequel.blob(insert_params.unique_key) : nil,
|
|
165
|
+
unique_states: insert_params.unique_states
|
|
166
|
+
}
|
|
82
167
|
end
|
|
83
168
|
|
|
84
|
-
def
|
|
85
|
-
|
|
169
|
+
private def postgres_job_insert_many(insert_params_array)
|
|
170
|
+
capabilities = postgres_capabilities
|
|
171
|
+
nonce = SecureRandom.hex(8) if capabilities.unique_insert_mode == :metadata_nonce
|
|
172
|
+
@db[:river_job]
|
|
173
|
+
.insert_conflict(
|
|
174
|
+
conflict_where: ::Sequel.lit(
|
|
175
|
+
"unique_key IS NOT NULL AND unique_states IS NOT NULL AND river_job_state_in_bitmask(unique_states, state)"
|
|
176
|
+
),
|
|
177
|
+
target: [:unique_key],
|
|
178
|
+
update: {kind: ::Sequel[:river_job][:kind]}
|
|
179
|
+
)
|
|
180
|
+
.returning(::Sequel.lit("*, #{capabilities.unique_insert_sql} AS unique_skipped_as_duplicate"))
|
|
181
|
+
.multi_insert(insert_params_array.map { |p| postgres_insert_params_to_hash(p, nonce) })
|
|
182
|
+
.map do |row|
|
|
183
|
+
job = to_job_row(row)
|
|
184
|
+
[job, nonce ? job.metadata[UNIQUE_INSERT_METADATA_KEY] != nonce : row[:unique_skipped_as_duplicate]]
|
|
185
|
+
end
|
|
86
186
|
end
|
|
87
187
|
|
|
88
|
-
def
|
|
89
|
-
|
|
188
|
+
private def postgres_to_job_row(river_job)
|
|
189
|
+
runtime_decode_postgres_job(river_job)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
private def runtime_connection_pool
|
|
193
|
+
@db
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
private def runtime_execute(sql)
|
|
197
|
+
@db.run(sql)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
private def runtime_job_list_without_params
|
|
201
|
+
job_list(:all)
|
|
90
202
|
end
|
|
91
203
|
|
|
92
|
-
def
|
|
204
|
+
private def runtime_job_rows(suffix)
|
|
93
205
|
if @is_sqlite
|
|
94
|
-
sqlite_job_rows(
|
|
206
|
+
sqlite_job_rows(suffix).map { |row| sqlite_to_job_row_from_raw(row) }
|
|
95
207
|
else
|
|
96
|
-
@db
|
|
208
|
+
@db.fetch("SELECT * FROM river_job #{suffix}").map { |row| to_job_row(row) }
|
|
97
209
|
end
|
|
98
210
|
end
|
|
99
211
|
|
|
100
|
-
def
|
|
101
|
-
|
|
212
|
+
private def runtime_postgres?
|
|
213
|
+
!@is_sqlite
|
|
102
214
|
end
|
|
103
215
|
|
|
104
|
-
def
|
|
105
|
-
@db.
|
|
216
|
+
private def runtime_query_rows(sql)
|
|
217
|
+
@db.fetch(sql).all
|
|
106
218
|
end
|
|
107
219
|
|
|
108
|
-
private def
|
|
109
|
-
@db
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
220
|
+
private def runtime_quote(value)
|
|
221
|
+
@db.literal(value)
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
private def runtime_unique_violation_class
|
|
225
|
+
::Sequel::UniqueConstraintViolation
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
private def runtime_value(row, key)
|
|
229
|
+
row[key] || row[key.to_s]
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
private def sqlite_insert_params_to_hash(insert_params, nonce)
|
|
233
|
+
{
|
|
234
|
+
args: JSON.parse(insert_params.encoded_args),
|
|
235
|
+
kind: insert_params.kind,
|
|
236
|
+
max_attempts: insert_params.max_attempts,
|
|
237
|
+
metadata: {UNIQUE_INSERT_METADATA_KEY => nonce},
|
|
238
|
+
priority: insert_params.priority,
|
|
239
|
+
queue: insert_params.queue,
|
|
240
|
+
scheduled_at: insert_params.scheduled_at ? format_time(insert_params.scheduled_at) : nil,
|
|
241
|
+
state: insert_params.state,
|
|
242
|
+
tags: insert_params.tags || [],
|
|
243
|
+
unique_key: insert_params.unique_key&.unpack1("H*"),
|
|
244
|
+
unique_states: insert_params.unique_states&.to_i(2)
|
|
245
|
+
}.tap { |values| values[:metadata] = (insert_params.metadata || {}).merge(values[:metadata]) }
|
|
120
246
|
end
|
|
121
247
|
|
|
122
248
|
# River's current SQLite driver uses json_each to make a batch a single,
|
|
123
249
|
# atomic statement. The JSON columns are converted to SQLite JSONB here,
|
|
124
250
|
# matching migration 007 and newer River databases.
|
|
125
251
|
private def sqlite_job_insert_many(insert_params_array)
|
|
126
|
-
|
|
127
|
-
|
|
252
|
+
nonces = sqlite_insert_nonces(insert_params_array)
|
|
128
253
|
@db.transaction(savepoint: true) do
|
|
129
|
-
|
|
130
|
-
|
|
254
|
+
jobs = insert_params_array.zip(nonces).map { |param, nonce| sqlite_insert_params_to_hash(param, nonce) }
|
|
255
|
+
inserted_nonces = nonces.to_h { |nonce| [nonce, true] }
|
|
131
256
|
|
|
132
257
|
sql = <<~SQL
|
|
133
258
|
INSERT INTO river_job (
|
|
@@ -163,134 +288,20 @@ module River::Driver
|
|
|
163
288
|
FROM json_each(cast(? AS blob))
|
|
164
289
|
WHERE true
|
|
165
290
|
ON CONFLICT (unique_key) WHERE #{SQLITE_CONFLICT_WHERE}
|
|
166
|
-
DO UPDATE SET kind =
|
|
291
|
+
DO UPDATE SET kind = river_job.kind
|
|
167
292
|
RETURNING #{SQLITE_JOB_COLUMNS}
|
|
168
293
|
SQL
|
|
169
294
|
|
|
170
|
-
rows = @db.fetch(sql, JSON.
|
|
295
|
+
rows = @db.fetch(sql, JSON.generate(jobs)).all
|
|
171
296
|
sqlite_notify_insert(insert_params_array)
|
|
172
297
|
|
|
173
298
|
rows.map do |row|
|
|
174
299
|
metadata = JSON.parse(row[:metadata])
|
|
175
|
-
[sqlite_to_job_row_from_raw(row), metadata[
|
|
300
|
+
[sqlite_to_job_row_from_raw(row), !inserted_nonces.key?(metadata[UNIQUE_INSERT_METADATA_KEY])]
|
|
176
301
|
end
|
|
177
302
|
end
|
|
178
303
|
end
|
|
179
304
|
|
|
180
|
-
private def postgres_insert_params_to_hash(insert_params)
|
|
181
|
-
{
|
|
182
|
-
args: insert_params.encoded_args,
|
|
183
|
-
kind: insert_params.kind,
|
|
184
|
-
max_attempts: insert_params.max_attempts,
|
|
185
|
-
priority: insert_params.priority,
|
|
186
|
-
queue: insert_params.queue,
|
|
187
|
-
state: insert_params.state,
|
|
188
|
-
scheduled_at: insert_params.scheduled_at,
|
|
189
|
-
tags: ::Sequel.pg_array(insert_params.tags || [], :text),
|
|
190
|
-
unique_key: insert_params.unique_key ? ::Sequel.blob(insert_params.unique_key) : nil,
|
|
191
|
-
unique_states: insert_params.unique_states
|
|
192
|
-
}
|
|
193
|
-
end
|
|
194
|
-
|
|
195
|
-
private def sqlite_insert_params_to_hash(insert_params, nonce)
|
|
196
|
-
{
|
|
197
|
-
args: JSON.parse(insert_params.encoded_args),
|
|
198
|
-
kind: insert_params.kind,
|
|
199
|
-
max_attempts: insert_params.max_attempts,
|
|
200
|
-
metadata: {SQLITE_UNIQUE_NONCE_KEY => nonce},
|
|
201
|
-
priority: insert_params.priority,
|
|
202
|
-
queue: insert_params.queue,
|
|
203
|
-
scheduled_at: insert_params.scheduled_at ? format_time(insert_params.scheduled_at) : nil,
|
|
204
|
-
state: insert_params.state,
|
|
205
|
-
tags: insert_params.tags || [],
|
|
206
|
-
unique_key: insert_params.unique_key&.unpack1("H*"),
|
|
207
|
-
unique_states: insert_params.unique_states&.to_i(2)
|
|
208
|
-
}
|
|
209
|
-
end
|
|
210
|
-
|
|
211
|
-
private def to_job_row(river_job)
|
|
212
|
-
if @is_sqlite
|
|
213
|
-
row = sqlite_job_rows("WHERE id = ? LIMIT 1", river_job[:id]).first
|
|
214
|
-
sqlite_to_job_row_from_raw(row)
|
|
215
|
-
else
|
|
216
|
-
postgres_to_job_row(river_job)
|
|
217
|
-
end
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
private def postgres_to_job_row(river_job)
|
|
221
|
-
River::JobRow.new(
|
|
222
|
-
id: river_job[:id],
|
|
223
|
-
args: river_job[:args].to_h,
|
|
224
|
-
attempt: river_job[:attempt],
|
|
225
|
-
attempted_at: river_job[:attempted_at]&.getutc,
|
|
226
|
-
attempted_by: river_job[:attempted_by],
|
|
227
|
-
created_at: river_job[:created_at].getutc,
|
|
228
|
-
errors: river_job[:errors]&.map { |deserialized_error|
|
|
229
|
-
River::AttemptError.new(
|
|
230
|
-
at: Time.parse(deserialized_error["at"]),
|
|
231
|
-
attempt: deserialized_error["attempt"],
|
|
232
|
-
error: deserialized_error["error"],
|
|
233
|
-
trace: deserialized_error["trace"]
|
|
234
|
-
)
|
|
235
|
-
},
|
|
236
|
-
finalized_at: river_job[:finalized_at]&.getutc,
|
|
237
|
-
kind: river_job[:kind],
|
|
238
|
-
max_attempts: river_job[:max_attempts],
|
|
239
|
-
metadata: river_job[:metadata],
|
|
240
|
-
priority: river_job[:priority],
|
|
241
|
-
queue: river_job[:queue],
|
|
242
|
-
scheduled_at: river_job[:scheduled_at].getutc,
|
|
243
|
-
state: river_job[:state],
|
|
244
|
-
tags: river_job[:tags].to_a,
|
|
245
|
-
unique_key: river_job[:unique_key]&.to_s,
|
|
246
|
-
unique_states: ::River::UniqueBitmask.to_states(river_job[:unique_states]&.to_i(2))
|
|
247
|
-
)
|
|
248
|
-
end
|
|
249
|
-
|
|
250
|
-
private def sqlite_to_job_row_from_raw(river_job)
|
|
251
|
-
errors = river_job[:errors] ? JSON.parse(river_job[:errors]) : []
|
|
252
|
-
|
|
253
|
-
River::JobRow.new(
|
|
254
|
-
id: river_job[:id],
|
|
255
|
-
args: JSON.parse(river_job[:args]),
|
|
256
|
-
attempt: river_job[:attempt],
|
|
257
|
-
attempted_at: parse_sqlite_time(river_job[:attempted_at]),
|
|
258
|
-
attempted_by: river_job[:attempted_by] ? JSON.parse(river_job[:attempted_by]) : nil,
|
|
259
|
-
created_at: parse_sqlite_time(river_job[:created_at]),
|
|
260
|
-
errors: errors.map { |deserialized_error|
|
|
261
|
-
River::AttemptError.new(
|
|
262
|
-
at: Time.parse(deserialized_error["at"]),
|
|
263
|
-
attempt: deserialized_error["attempt"],
|
|
264
|
-
error: deserialized_error["error"],
|
|
265
|
-
trace: deserialized_error["trace"]
|
|
266
|
-
)
|
|
267
|
-
},
|
|
268
|
-
finalized_at: parse_sqlite_time(river_job[:finalized_at]),
|
|
269
|
-
kind: river_job[:kind],
|
|
270
|
-
max_attempts: river_job[:max_attempts],
|
|
271
|
-
metadata: JSON.parse(river_job[:metadata]),
|
|
272
|
-
priority: river_job[:priority],
|
|
273
|
-
queue: river_job[:queue],
|
|
274
|
-
scheduled_at: parse_sqlite_time(river_job[:scheduled_at]),
|
|
275
|
-
state: river_job[:state],
|
|
276
|
-
tags: JSON.parse(river_job[:tags]),
|
|
277
|
-
unique_key: river_job[:unique_key]&.to_s,
|
|
278
|
-
unique_states: river_job[:unique_states] ? ::River::UniqueBitmask.to_states(river_job[:unique_states]) : nil
|
|
279
|
-
)
|
|
280
|
-
end
|
|
281
|
-
|
|
282
|
-
private def format_time(time)
|
|
283
|
-
time.getutc.round(3).strftime("%Y-%m-%d %H:%M:%S.%3N")
|
|
284
|
-
end
|
|
285
|
-
|
|
286
|
-
private def parse_sqlite_time(value)
|
|
287
|
-
return nil unless value
|
|
288
|
-
|
|
289
|
-
value = value.to_s
|
|
290
|
-
value += " UTC" unless value.match?(/(?:Z|[+-]\d{2}:?\d{2})\z/)
|
|
291
|
-
Time.parse(value).utc
|
|
292
|
-
end
|
|
293
|
-
|
|
294
305
|
private def sqlite_job_rows(suffix, *binds)
|
|
295
306
|
@db.fetch("SELECT #{SQLITE_JOB_COLUMNS} FROM river_job #{suffix}", *binds).all
|
|
296
307
|
end
|
|
@@ -303,8 +314,21 @@ module River::Driver
|
|
|
303
314
|
return if queues.empty?
|
|
304
315
|
|
|
305
316
|
@db[:river_notification].multi_insert(queues.map do |queue|
|
|
306
|
-
{payload: JSON.
|
|
317
|
+
{payload: JSON.generate({queue: queue}), topic: "river_insert"}
|
|
307
318
|
end)
|
|
308
319
|
end
|
|
320
|
+
|
|
321
|
+
private def sqlite_to_job_row_from_raw(row)
|
|
322
|
+
runtime_decode_sqlite_job(row)
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
private def to_job_row(river_job)
|
|
326
|
+
if @is_sqlite
|
|
327
|
+
row = sqlite_job_rows("WHERE id = ? LIMIT 1", river_job[:id]).first
|
|
328
|
+
sqlite_to_job_row_from_raw(row)
|
|
329
|
+
else
|
|
330
|
+
postgres_to_job_row(river_job)
|
|
331
|
+
end
|
|
332
|
+
end
|
|
309
333
|
end
|
|
310
334
|
end
|
data/lib/riverqueue-sequel.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: riverqueue-sequel
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.13.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Blake Gentry
|
|
@@ -30,8 +30,22 @@ dependencies:
|
|
|
30
30
|
- - "<"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
32
|
version: '1000'
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
- !ruby/object:Gem::Dependency
|
|
34
|
+
name: riverqueue
|
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - '='
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: 0.13.0
|
|
40
|
+
type: :runtime
|
|
41
|
+
prerelease: false
|
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - '='
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: 0.13.0
|
|
47
|
+
description: Sequel PostgreSQL and SQLite driver for inserting and working River jobs
|
|
48
|
+
in Ruby.
|
|
35
49
|
email: brandur@brandur.org
|
|
36
50
|
executables: []
|
|
37
51
|
extensions: []
|
|
@@ -41,7 +55,7 @@ files:
|
|
|
41
55
|
- lib/riverqueue-sequel.rb
|
|
42
56
|
homepage: https://riverqueue.com
|
|
43
57
|
licenses:
|
|
44
|
-
-
|
|
58
|
+
- MPL-2.0
|
|
45
59
|
metadata: {}
|
|
46
60
|
rdoc_options: []
|
|
47
61
|
require_paths:
|
|
@@ -50,7 +64,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
50
64
|
requirements:
|
|
51
65
|
- - ">="
|
|
52
66
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: '
|
|
67
|
+
version: '3.2'
|
|
54
68
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
55
69
|
requirements:
|
|
56
70
|
- - ">="
|