delayed 2.2.0 → 3.0.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/README.md +3 -3
- data/app/models/delayed/job.rb +0 -9
- data/db/migrate/08_add_run_at_and_name_not_null_check.rb +34 -0
- data/db/migrate/09_validate_run_at_and_name_not_null.rb +41 -0
- data/lib/delayed/active_job_adapter.rb +41 -8
- data/lib/delayed/backend/base.rb +67 -11
- data/lib/delayed/backend/job_preparer.rb +20 -0
- data/lib/delayed/lifecycle.rb +1 -1
- data/lib/delayed/plugins/instrumentation.rb +9 -3
- data/lib/delayed/version.rb +1 -1
- data/lib/delayed/worker.rb +0 -8
- data/spec/delayed/active_job_adapter_spec.rb +285 -46
- data/spec/delayed/job_spec.rb +181 -32
- data/spec/delayed/monitor_spec.rb +1 -0
- data/spec/delayed/plugins/instrumentation_spec.rb +41 -0
- data/spec/helper.rb +9 -0
- data/spec/lifecycle_spec.rb +1 -1
- data/spec/message_sending_spec.rb +3 -13
- data/spec/performable_method_spec.rb +0 -6
- data/spec/sample_jobs.rb +0 -10
- metadata +12 -10
- /data/db/migrate/{1_create_delayed_jobs.rb → 01_create_delayed_jobs.rb} +0 -0
- /data/db/migrate/{2_add_name_to_delayed_jobs.rb → 02_add_name_to_delayed_jobs.rb} +0 -0
- /data/db/migrate/{3_add_index_to_delayed_jobs_name.rb → 03_add_index_to_delayed_jobs_name.rb} +0 -0
- /data/db/migrate/{4_index_live_jobs.rb → 04_index_live_jobs.rb} +0 -0
- /data/db/migrate/{5_index_failed_jobs.rb → 05_index_failed_jobs.rb} +0 -0
- /data/db/migrate/{6_set_postgres_fillfactor.rb → 06_set_postgres_fillfactor.rb} +0 -0
- /data/db/migrate/{7_remove_legacy_index.rb → 07_remove_legacy_index.rb} +0 -0
|
@@ -10,9 +10,29 @@ RSpec.describe Delayed::ActiveJobAdapter do
|
|
|
10
10
|
def perform; end
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
|
+
let(:enqueued_delayed_jobs) { [] }
|
|
13
14
|
|
|
14
15
|
before do
|
|
15
16
|
stub_const 'JobClass', job_class
|
|
17
|
+
|
|
18
|
+
next_id = 0
|
|
19
|
+
allow(Delayed::Job).to receive(:enqueue_job) do |options|
|
|
20
|
+
delayed_job = Delayed::Job.new(options)
|
|
21
|
+
next_id += 1
|
|
22
|
+
delayed_job.id = next_id
|
|
23
|
+
enqueued_delayed_jobs << delayed_job
|
|
24
|
+
delayed_job
|
|
25
|
+
end
|
|
26
|
+
allow(Delayed::Job).to receive(:enqueue_all) do |delayed_jobs|
|
|
27
|
+
if Delayed::Job.connection.supports_insert_returning?
|
|
28
|
+
delayed_jobs.each do |delayed_job|
|
|
29
|
+
next_id += 1
|
|
30
|
+
delayed_job.id = next_id
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
enqueued_delayed_jobs.concat(delayed_jobs)
|
|
34
|
+
delayed_jobs.size
|
|
35
|
+
end
|
|
16
36
|
end
|
|
17
37
|
|
|
18
38
|
around do |example|
|
|
@@ -38,7 +58,7 @@ RSpec.describe Delayed::ActiveJobAdapter do
|
|
|
38
58
|
JobClass.perform_later
|
|
39
59
|
end
|
|
40
60
|
|
|
41
|
-
|
|
61
|
+
enqueued_delayed_jobs.last.tap do |dj|
|
|
42
62
|
expect(dj.handler.lines).to match [
|
|
43
63
|
"--- !ruby/object:Delayed::JobWrapper\n",
|
|
44
64
|
"job_data:\n",
|
|
@@ -58,49 +78,79 @@ RSpec.describe Delayed::ActiveJobAdapter do
|
|
|
58
78
|
end
|
|
59
79
|
end
|
|
60
80
|
|
|
61
|
-
it '
|
|
62
|
-
JobClass.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
expect { dj.payload_object }.not_to raise_error
|
|
67
|
-
expect { dj.payload_object.job_id }.to raise_error(NameError, 'uninitialized constant MissingJobClass')
|
|
81
|
+
it 'bubbles out an error if the job fails to serialize' do
|
|
82
|
+
JobClass.class_eval do
|
|
83
|
+
def serialize(*)
|
|
84
|
+
raise "uh oh, serialize failed!"
|
|
85
|
+
end
|
|
68
86
|
end
|
|
69
|
-
|
|
70
|
-
expect
|
|
87
|
+
|
|
88
|
+
expect { JobClass.perform_later }.to raise_error(RuntimeError, "uh oh, serialize failed!")
|
|
71
89
|
end
|
|
72
90
|
|
|
73
|
-
it '
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
91
|
+
it 'bubbles out an error if Delayed::Job.enqueue_job raises (single-job path)' do
|
|
92
|
+
allow(Delayed::Job).to receive(:enqueue_all).and_raise('uh oh, enqueue failed!')
|
|
93
|
+
|
|
94
|
+
expect { JobClass.perform_later }.to raise_error(RuntimeError, 'uh oh, enqueue failed!')
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it 'bubbles out an error if Delayed::Job.enqueue_all raises (bulk path)' do
|
|
98
|
+
allow(Delayed::Job).to receive(:enqueue_all).and_raise('uh oh, enqueue failed!')
|
|
99
|
+
|
|
100
|
+
expect { ActiveJob::Base.queue_adapter.enqueue_all([JobClass.new]) }
|
|
101
|
+
.to raise_error(RuntimeError, 'uh oh, enqueue failed!')
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
context 'when integrated end-to-end (and_call_original)' do
|
|
105
|
+
before do
|
|
106
|
+
allow(Delayed::Job).to receive(:enqueue_job).and_call_original
|
|
107
|
+
allow(Delayed::Job).to receive(:enqueue_all).and_call_original
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it 'deserializes even if the underlying job class is not defined' do
|
|
111
|
+
JobClass.perform_later
|
|
112
|
+
|
|
113
|
+
Delayed::Job.last.tap do |dj|
|
|
114
|
+
dj.update!(handler: dj.handler.gsub('JobClass', 'MissingJobClass'))
|
|
115
|
+
expect { dj.payload_object }.not_to raise_error
|
|
116
|
+
expect { dj.payload_object.job_id }.to raise_error(NameError, 'uninitialized constant MissingJobClass')
|
|
117
|
+
end
|
|
118
|
+
expect(Delayed::Worker.new.work_off).to eq([0, 1])
|
|
119
|
+
expect(Delayed::Job.last.last_error).to match(/uninitialized constant MissingJobClass/)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it 'deserializes even if an underlying argument gid is not defined' do
|
|
123
|
+
ActiveJobJob.perform_later(story: Story.create!)
|
|
124
|
+
Delayed::Job.last.tap do |dj|
|
|
125
|
+
dj.update!(handler: dj.handler.gsub('Story', 'MissingArgumentClass'))
|
|
126
|
+
expect { dj.payload_object }.not_to raise_error
|
|
127
|
+
expect { dj.payload_object.perform_now }.to raise_error(ActiveJob::DeserializationError)
|
|
128
|
+
end
|
|
129
|
+
expect(Delayed::Worker.new.work_off).to eq([0, 1])
|
|
130
|
+
expect(Delayed::Job.last.last_error).to match(/Error while trying to deserialize arguments/)
|
|
79
131
|
end
|
|
80
|
-
expect(Delayed::Worker.new.work_off).to eq([0, 1])
|
|
81
|
-
expect(Delayed::Job.last.last_error).to match(/Error while trying to deserialize arguments/)
|
|
82
132
|
end
|
|
83
133
|
|
|
84
134
|
describe '.set' do
|
|
85
135
|
it 'supports priority as an integer' do
|
|
86
136
|
JobClass.set(priority: 43).perform_later
|
|
87
137
|
|
|
88
|
-
expect(
|
|
89
|
-
expect(
|
|
138
|
+
expect(enqueued_delayed_jobs.last.priority).to be_reporting
|
|
139
|
+
expect(enqueued_delayed_jobs.last.priority).to eq(43)
|
|
90
140
|
end
|
|
91
141
|
|
|
92
142
|
it 'supports priority as a Delayed::Priority' do
|
|
93
143
|
JobClass.set(priority: Delayed::Priority.eventual).perform_later
|
|
94
144
|
|
|
95
|
-
expect(
|
|
96
|
-
expect(
|
|
145
|
+
expect(enqueued_delayed_jobs.last.priority).to be_eventual
|
|
146
|
+
expect(enqueued_delayed_jobs.last.priority).to eq(20)
|
|
97
147
|
end
|
|
98
148
|
|
|
99
149
|
it 'supports priority as a symbol' do
|
|
100
150
|
JobClass.set(priority: :eventual).perform_later
|
|
101
151
|
|
|
102
|
-
expect(
|
|
103
|
-
expect(
|
|
152
|
+
expect(enqueued_delayed_jobs.last.priority).to be_eventual
|
|
153
|
+
expect(enqueued_delayed_jobs.last.priority).to eq(20)
|
|
104
154
|
end
|
|
105
155
|
|
|
106
156
|
it 'raises an error when run_at is used' do
|
|
@@ -111,7 +161,7 @@ RSpec.describe Delayed::ActiveJobAdapter do
|
|
|
111
161
|
it 'converts wait_until to run_at' do
|
|
112
162
|
JobClass.set(wait_until: arbitrary_time).perform_later
|
|
113
163
|
|
|
114
|
-
expect(
|
|
164
|
+
expect(enqueued_delayed_jobs.last.run_at).to eq('2021-01-05 03:34:33 UTC')
|
|
115
165
|
end
|
|
116
166
|
|
|
117
167
|
context 'when running at a specific time' do
|
|
@@ -122,7 +172,7 @@ RSpec.describe Delayed::ActiveJobAdapter do
|
|
|
122
172
|
it 'adds wait input to current time' do
|
|
123
173
|
JobClass.set(wait: (1.day + 1.hour + 1.minute)).perform_later
|
|
124
174
|
|
|
125
|
-
expect(
|
|
175
|
+
expect(enqueued_delayed_jobs.last.run_at).to eq('2021-01-06 04:35:33 UTC')
|
|
126
176
|
end
|
|
127
177
|
end
|
|
128
178
|
|
|
@@ -142,7 +192,7 @@ RSpec.describe Delayed::ActiveJobAdapter do
|
|
|
142
192
|
it 'calls the expected setter' do
|
|
143
193
|
JobClass.set(foo: 'bar').perform_later
|
|
144
194
|
|
|
145
|
-
expect(
|
|
195
|
+
expect(enqueued_delayed_jobs.last.queue).to eq('foo-bar')
|
|
146
196
|
end
|
|
147
197
|
end
|
|
148
198
|
|
|
@@ -160,7 +210,7 @@ RSpec.describe Delayed::ActiveJobAdapter do
|
|
|
160
210
|
it 'surfaces max_attempts on the JobWrapper' do
|
|
161
211
|
JobClass.perform_later
|
|
162
212
|
|
|
163
|
-
expect(
|
|
213
|
+
expect(enqueued_delayed_jobs.last.max_attempts).to eq 3
|
|
164
214
|
end
|
|
165
215
|
end
|
|
166
216
|
|
|
@@ -178,7 +228,7 @@ RSpec.describe Delayed::ActiveJobAdapter do
|
|
|
178
228
|
it 'surfaces arbitrary_method on the JobWrapper' do
|
|
179
229
|
JobClass.perform_later
|
|
180
230
|
|
|
181
|
-
expect(
|
|
231
|
+
expect(enqueued_delayed_jobs.last.payload_object.arbitrary_method).to eq 'hello'
|
|
182
232
|
end
|
|
183
233
|
end
|
|
184
234
|
end
|
|
@@ -187,15 +237,15 @@ RSpec.describe Delayed::ActiveJobAdapter do
|
|
|
187
237
|
it 'applies the default ActiveJob queue and priority' do
|
|
188
238
|
JobClass.perform_later
|
|
189
239
|
|
|
190
|
-
expect(
|
|
191
|
-
expect(
|
|
240
|
+
expect(enqueued_delayed_jobs.last.queue).to eq('default')
|
|
241
|
+
expect(enqueued_delayed_jobs.last.priority).to eq(10)
|
|
192
242
|
end
|
|
193
243
|
|
|
194
244
|
it 'supports overriding queue and priority' do
|
|
195
245
|
JobClass.set(queue: 'a', priority: 3).perform_later
|
|
196
246
|
|
|
197
|
-
expect(
|
|
198
|
-
expect(
|
|
247
|
+
expect(enqueued_delayed_jobs.last.queue).to eq('a')
|
|
248
|
+
expect(enqueued_delayed_jobs.last.priority).to eq(3)
|
|
199
249
|
end
|
|
200
250
|
|
|
201
251
|
context 'when all default queues and priorities are nil' do
|
|
@@ -209,15 +259,15 @@ RSpec.describe Delayed::ActiveJobAdapter do
|
|
|
209
259
|
it 'applies no queue or priority' do
|
|
210
260
|
JobClass.perform_later
|
|
211
261
|
|
|
212
|
-
expect(
|
|
213
|
-
expect(
|
|
262
|
+
expect(enqueued_delayed_jobs.last.queue).to be_nil
|
|
263
|
+
expect(enqueued_delayed_jobs.last.priority).to eq(0)
|
|
214
264
|
end
|
|
215
265
|
|
|
216
266
|
it 'supports overriding queue and priority' do
|
|
217
267
|
JobClass.set(queue: 'a', priority: 3).perform_later
|
|
218
268
|
|
|
219
|
-
expect(
|
|
220
|
-
expect(
|
|
269
|
+
expect(enqueued_delayed_jobs.last.queue).to eq('a')
|
|
270
|
+
expect(enqueued_delayed_jobs.last.priority).to eq(3)
|
|
221
271
|
end
|
|
222
272
|
end
|
|
223
273
|
|
|
@@ -232,15 +282,15 @@ RSpec.describe Delayed::ActiveJobAdapter do
|
|
|
232
282
|
it 'applies the default Delayed queue and priority' do
|
|
233
283
|
JobClass.perform_later
|
|
234
284
|
|
|
235
|
-
expect(
|
|
236
|
-
expect(
|
|
285
|
+
expect(enqueued_delayed_jobs.last.queue).to eq('dj_default')
|
|
286
|
+
expect(enqueued_delayed_jobs.last.priority).to eq(99)
|
|
237
287
|
end
|
|
238
288
|
|
|
239
289
|
it 'supports overriding queue and priority' do
|
|
240
290
|
JobClass.set(queue: 'a', priority: 3).perform_later
|
|
241
291
|
|
|
242
|
-
expect(
|
|
243
|
-
expect(
|
|
292
|
+
expect(enqueued_delayed_jobs.last.queue).to eq('a')
|
|
293
|
+
expect(enqueued_delayed_jobs.last.priority).to eq(3)
|
|
244
294
|
end
|
|
245
295
|
end
|
|
246
296
|
|
|
@@ -253,15 +303,15 @@ RSpec.describe Delayed::ActiveJobAdapter do
|
|
|
253
303
|
it 'applies the default ActiveJob queue and priority' do
|
|
254
304
|
JobClass.perform_later
|
|
255
305
|
|
|
256
|
-
expect(
|
|
257
|
-
expect(
|
|
306
|
+
expect(enqueued_delayed_jobs.last.queue).to eq('aj_default')
|
|
307
|
+
expect(enqueued_delayed_jobs.last.priority).to eq(11)
|
|
258
308
|
end
|
|
259
309
|
|
|
260
310
|
it 'supports overriding queue and priority' do
|
|
261
311
|
JobClass.set(queue: 'a', priority: 3).perform_later
|
|
262
312
|
|
|
263
|
-
expect(
|
|
264
|
-
expect(
|
|
313
|
+
expect(enqueued_delayed_jobs.last.queue).to eq('a')
|
|
314
|
+
expect(enqueued_delayed_jobs.last.priority).to eq(3)
|
|
265
315
|
end
|
|
266
316
|
end
|
|
267
317
|
|
|
@@ -277,7 +327,7 @@ RSpec.describe Delayed::ActiveJobAdapter do
|
|
|
277
327
|
it 'applies the specified priority' do
|
|
278
328
|
JobClass.perform_later
|
|
279
329
|
|
|
280
|
-
expect(
|
|
330
|
+
expect(enqueued_delayed_jobs.last.priority).to eq(30)
|
|
281
331
|
end
|
|
282
332
|
end
|
|
283
333
|
|
|
@@ -292,6 +342,11 @@ RSpec.describe Delayed::ActiveJobAdapter do
|
|
|
292
342
|
end
|
|
293
343
|
end
|
|
294
344
|
|
|
345
|
+
before do
|
|
346
|
+
allow(Delayed::Job).to receive(:enqueue_job).and_call_original
|
|
347
|
+
allow(Delayed::Job).to receive(:enqueue_all).and_call_original
|
|
348
|
+
end
|
|
349
|
+
|
|
295
350
|
it 'passes arguments through to the perform method' do
|
|
296
351
|
JobClass.perform_later('foo', kwarg: 'bar')
|
|
297
352
|
|
|
@@ -381,4 +436,188 @@ RSpec.describe Delayed::ActiveJobAdapter do
|
|
|
381
436
|
end
|
|
382
437
|
end
|
|
383
438
|
end
|
|
439
|
+
|
|
440
|
+
describe '.enqueue_all' do # rubocop:disable Metrics/BlockLength
|
|
441
|
+
let(:adapter) { ActiveJob::Base.queue_adapter }
|
|
442
|
+
|
|
443
|
+
it 'returns 0 when given no jobs' do
|
|
444
|
+
expect(adapter.enqueue_all([])).to eq(0)
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
it 'does not delegate to Delayed::Job.enqueue_all for empty input' do
|
|
448
|
+
adapter.enqueue_all([])
|
|
449
|
+
expect(enqueued_delayed_jobs).to be_empty
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
it 'delegates to Delayed::Job.enqueue_all with an Array<Delayed::Job>' do
|
|
453
|
+
jobs = Array.new(3) { JobClass.new }
|
|
454
|
+
adapter.enqueue_all(jobs)
|
|
455
|
+
|
|
456
|
+
expect(Delayed::Job).to have_received(:enqueue_all).once
|
|
457
|
+
expect(enqueued_delayed_jobs.size).to eq(3)
|
|
458
|
+
expect(enqueued_delayed_jobs).to all(be_a(Delayed::Job))
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
it 'returns the count of jobs delegated' do
|
|
462
|
+
jobs = Array.new(3) { JobClass.new }
|
|
463
|
+
expect(adapter.enqueue_all(jobs)).to eq(3)
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
it 'honors per-job scheduled_at on the delegated Delayed::Job' do
|
|
467
|
+
job = JobClass.new
|
|
468
|
+
job.scheduled_at = arbitrary_time
|
|
469
|
+
adapter.enqueue_all([JobClass.new, job])
|
|
470
|
+
|
|
471
|
+
expect(enqueued_delayed_jobs[1].run_at).to eq(arbitrary_time)
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
it 'applies db_time_now to run_at when no scheduled_at is set' do
|
|
475
|
+
Timecop.freeze(arbitrary_time) do
|
|
476
|
+
adapter.enqueue_all([JobClass.new])
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
expect(enqueued_delayed_jobs.last.run_at).to eq(arbitrary_time)
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
it 'honors per-job queue and priority overrides on the delegated Delayed::Job' do
|
|
483
|
+
a = JobClass.new.tap do |j|
|
|
484
|
+
j.queue_name = 'q-a'
|
|
485
|
+
j.priority = 3
|
|
486
|
+
end
|
|
487
|
+
b = JobClass.new.tap do |j|
|
|
488
|
+
j.queue_name = 'q-b'
|
|
489
|
+
j.priority = 7
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
adapter.enqueue_all([a, b])
|
|
493
|
+
|
|
494
|
+
expect(enqueued_delayed_jobs[0]).to have_attributes(queue: 'q-a', priority: 3)
|
|
495
|
+
expect(enqueued_delayed_jobs[1]).to have_attributes(queue: 'q-b', priority: 7)
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
it 'supports a mix of job classes in one call' do
|
|
499
|
+
other_class = Class.new(ActiveJob::Base) do # rubocop:disable Rails/ApplicationJob
|
|
500
|
+
def perform; end
|
|
501
|
+
end
|
|
502
|
+
stub_const('OtherJobClass', other_class)
|
|
503
|
+
|
|
504
|
+
adapter.enqueue_all([JobClass.new, OtherJobClass.new])
|
|
505
|
+
|
|
506
|
+
expect(enqueued_delayed_jobs.map(&:name)).to eq(%w(JobClass OtherJobClass))
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
it 'sets the name on the delegated Delayed::Job from display_name' do
|
|
510
|
+
adapter.enqueue_all([JobClass.new])
|
|
511
|
+
expect(enqueued_delayed_jobs.last.name).to eq('JobClass')
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
it 'copies the id from each delegated Delayed::Job onto the AJ input as provider_job_id' do
|
|
515
|
+
skip 'requires INSERT ... RETURNING support' unless Delayed::Job.connection.supports_insert_returning?
|
|
516
|
+
|
|
517
|
+
jobs = Array.new(3) { JobClass.new }
|
|
518
|
+
adapter.enqueue_all(jobs)
|
|
519
|
+
|
|
520
|
+
expect(jobs.map(&:provider_job_id)).to eq(enqueued_delayed_jobs.map(&:id))
|
|
521
|
+
expect(jobs.map(&:provider_job_id)).to all(be_a(Integer))
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
if ActiveJob.gem_version.release >= Gem::Version.new('7.1')
|
|
525
|
+
it 'marks each AJ input as successfully_enqueued' do
|
|
526
|
+
jobs = Array.new(2) { JobClass.new }
|
|
527
|
+
adapter.enqueue_all(jobs)
|
|
528
|
+
expect(jobs).to all(be_successfully_enqueued)
|
|
529
|
+
end
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
context 'when the database adapter does not support INSERT RETURNING (e.g. MySQL)' do
|
|
533
|
+
before do
|
|
534
|
+
allow(Delayed::Job.connection).to receive(:supports_insert_returning?).and_return(false)
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
it 'leaves provider_job_id nil on each AJ input' do
|
|
538
|
+
jobs = Array.new(2) { JobClass.new }
|
|
539
|
+
adapter.enqueue_all(jobs)
|
|
540
|
+
expect(jobs.map(&:provider_job_id)).to all(be_nil)
|
|
541
|
+
end
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
it 'does not fire ActiveJob before/around/after_enqueue callbacks' do
|
|
545
|
+
fires = []
|
|
546
|
+
JobClass.before_enqueue { fires << :before }
|
|
547
|
+
JobClass.around_enqueue do |_j, block|
|
|
548
|
+
fires << :around_before
|
|
549
|
+
block.call
|
|
550
|
+
fires << :around_after
|
|
551
|
+
end
|
|
552
|
+
JobClass.after_enqueue { fires << :after }
|
|
553
|
+
|
|
554
|
+
adapter.enqueue_all([JobClass.new, JobClass.new])
|
|
555
|
+
|
|
556
|
+
expect(fires).to be_empty
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
if ActiveJob.gem_version.release >= Gem::Version.new('7.2')
|
|
560
|
+
context 'when a job sets enqueue_after_transaction_commit to :always' do
|
|
561
|
+
before do
|
|
562
|
+
JobClass.include ActiveJob::EnqueueAfterTransactionCommit
|
|
563
|
+
JobClass.enqueue_after_transaction_commit = :always
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
it 'raises UnsafeEnqueueError and does not delegate to Delayed::Job.enqueue_all' do
|
|
567
|
+
ActiveJob.deprecator.silence do
|
|
568
|
+
expect { adapter.enqueue_all([JobClass.new]) }.to raise_error(Delayed::ActiveJobAdapter::UnsafeEnqueueError)
|
|
569
|
+
end
|
|
570
|
+
expect(enqueued_delayed_jobs).to be_empty
|
|
571
|
+
end
|
|
572
|
+
end
|
|
573
|
+
end
|
|
574
|
+
|
|
575
|
+
context 'when a job has a stale run_at and deny_stale_enqueues is enabled' do
|
|
576
|
+
around do |example|
|
|
577
|
+
was = Delayed::Worker.deny_stale_enqueues
|
|
578
|
+
Delayed::Worker.deny_stale_enqueues = true
|
|
579
|
+
example.run
|
|
580
|
+
ensure
|
|
581
|
+
Delayed::Worker.deny_stale_enqueues = was
|
|
582
|
+
end
|
|
583
|
+
|
|
584
|
+
it 'raises StaleEnqueueError and does not delegate to Delayed::Job.enqueue_all' do
|
|
585
|
+
job = JobClass.new
|
|
586
|
+
job.scheduled_at = Time.now.utc - 1.day
|
|
587
|
+
expect { adapter.enqueue_all([JobClass.new, job]) }.to raise_error(Delayed::StaleEnqueueError)
|
|
588
|
+
expect(enqueued_delayed_jobs).to be_empty
|
|
589
|
+
end
|
|
590
|
+
end
|
|
591
|
+
end
|
|
592
|
+
|
|
593
|
+
describe 'single-job perform_later routes through Delayed::Job.enqueue_all' do
|
|
594
|
+
it 'invokes Delayed::Job.enqueue_all (not Delayed::Job.enqueue or Delayed::Job.enqueue_job)' do
|
|
595
|
+
expect(Delayed::Job).not_to receive(:enqueue) # rubocop:disable RSpec/MessageSpies
|
|
596
|
+
expect(Delayed::Job).not_to receive(:enqueue_job) # rubocop:disable RSpec/MessageSpies
|
|
597
|
+
|
|
598
|
+
JobClass.perform_later
|
|
599
|
+
|
|
600
|
+
expect(Delayed::Job).to have_received(:enqueue_all).once
|
|
601
|
+
end
|
|
602
|
+
|
|
603
|
+
it 'delegates exactly one Delayed::Job' do
|
|
604
|
+
JobClass.perform_later
|
|
605
|
+
expect(enqueued_delayed_jobs.size).to eq(1)
|
|
606
|
+
end
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
if ActiveJob.gem_version.release >= Gem::Version.new('7.1')
|
|
610
|
+
describe 'ActiveJob.perform_all_later' do
|
|
611
|
+
it 'delegates all jobs to Delayed::Job.enqueue_all in a single call' do
|
|
612
|
+
ActiveJob.perform_all_later([JobClass.new, JobClass.new, JobClass.new])
|
|
613
|
+
|
|
614
|
+
expect(Delayed::Job).to have_received(:enqueue_all).once
|
|
615
|
+
expect(enqueued_delayed_jobs.size).to eq(3)
|
|
616
|
+
end
|
|
617
|
+
|
|
618
|
+
it 'returns nil' do
|
|
619
|
+
expect(ActiveJob.perform_all_later([JobClass.new])).to be_nil
|
|
620
|
+
end
|
|
621
|
+
end
|
|
622
|
+
end
|
|
384
623
|
end
|