inst-jobs 2.0.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/db/migrate/20101216224513_create_delayed_jobs.rb +9 -7
- data/db/migrate/20110531144916_cleanup_delayed_jobs_indexes.rb +8 -13
- data/db/migrate/20110610213249_optimize_delayed_jobs.rb +8 -8
- data/db/migrate/20110831210257_add_delayed_jobs_next_in_strand.rb +25 -25
- data/db/migrate/20120510004759_delayed_jobs_delete_trigger_lock_for_update.rb +4 -8
- data/db/migrate/20120531150712_drop_psql_jobs_pop_fn.rb +1 -3
- data/db/migrate/20120607164022_delayed_jobs_use_advisory_locks.rb +11 -15
- data/db/migrate/20120607181141_index_jobs_on_locked_by.rb +1 -1
- data/db/migrate/20120608191051_add_jobs_run_at_index.rb +2 -2
- data/db/migrate/20120927184213_change_delayed_jobs_handler_to_text.rb +1 -1
- data/db/migrate/20140505215510_copy_failed_jobs_original_id.rb +2 -3
- data/db/migrate/20150807133223_add_max_concurrent_to_jobs.rb +9 -13
- data/db/migrate/20151210162949_improve_max_concurrent.rb +4 -8
- data/db/migrate/20161206323555_add_back_default_string_limits_jobs.rb +3 -2
- data/db/migrate/20181217155351_speed_up_max_concurrent_triggers.rb +13 -17
- data/db/migrate/20200330230722_add_id_to_get_delayed_jobs_index.rb +8 -8
- data/db/migrate/20200824222232_speed_up_max_concurrent_delete_trigger.rb +72 -77
- data/db/migrate/20200825011002_add_strand_order_override.rb +93 -97
- data/db/migrate/20210809145804_add_n_strand_index.rb +12 -0
- data/db/migrate/20210812210128_add_singleton_column.rb +200 -0
- data/db/migrate/20210917232626_add_delete_conflicting_singletons_before_unlock_trigger.rb +27 -0
- data/db/migrate/20210928174754_fix_singleton_condition_in_before_insert.rb +56 -0
- data/db/migrate/20210929204903_update_conflicting_singleton_function_to_use_index.rb +27 -0
- data/exe/inst_jobs +3 -2
- data/lib/delayed/backend/active_record.rb +211 -168
- data/lib/delayed/backend/base.rb +110 -72
- data/lib/delayed/batch.rb +11 -9
- data/lib/delayed/cli.rb +98 -84
- data/lib/delayed/core_ext/kernel.rb +4 -2
- data/lib/delayed/daemon.rb +70 -74
- data/lib/delayed/job_tracking.rb +26 -25
- data/lib/delayed/lifecycle.rb +27 -23
- data/lib/delayed/log_tailer.rb +17 -17
- data/lib/delayed/logging.rb +13 -16
- data/lib/delayed/message_sending.rb +43 -52
- data/lib/delayed/performable_method.rb +6 -8
- data/lib/delayed/periodic.rb +72 -68
- data/lib/delayed/plugin.rb +2 -4
- data/lib/delayed/pool.rb +205 -168
- data/lib/delayed/server/helpers.rb +6 -6
- data/lib/delayed/server.rb +51 -54
- data/lib/delayed/settings.rb +94 -81
- data/lib/delayed/testing.rb +21 -22
- data/lib/delayed/version.rb +1 -1
- data/lib/delayed/work_queue/in_process.rb +21 -17
- data/lib/delayed/work_queue/parent_process/client.rb +55 -53
- data/lib/delayed/work_queue/parent_process/server.rb +245 -207
- data/lib/delayed/work_queue/parent_process.rb +52 -53
- data/lib/delayed/worker/consul_health_check.rb +32 -33
- data/lib/delayed/worker/health_check.rb +34 -26
- data/lib/delayed/worker/null_health_check.rb +3 -1
- data/lib/delayed/worker/process_helper.rb +8 -9
- data/lib/delayed/worker.rb +272 -241
- data/lib/delayed/yaml_extensions.rb +12 -10
- data/lib/delayed_job.rb +37 -37
- data/lib/inst-jobs.rb +1 -1
- data/spec/active_record_job_spec.rb +143 -139
- data/spec/delayed/cli_spec.rb +7 -7
- data/spec/delayed/daemon_spec.rb +10 -9
- data/spec/delayed/message_sending_spec.rb +16 -9
- data/spec/delayed/periodic_spec.rb +14 -21
- data/spec/delayed/server_spec.rb +38 -38
- data/spec/delayed/settings_spec.rb +26 -25
- data/spec/delayed/work_queue/in_process_spec.rb +7 -8
- data/spec/delayed/work_queue/parent_process/client_spec.rb +17 -12
- data/spec/delayed/work_queue/parent_process/server_spec.rb +117 -41
- data/spec/delayed/work_queue/parent_process_spec.rb +21 -23
- data/spec/delayed/worker/consul_health_check_spec.rb +37 -50
- data/spec/delayed/worker/health_check_spec.rb +60 -52
- data/spec/delayed/worker_spec.rb +44 -21
- data/spec/sample_jobs.rb +45 -15
- data/spec/shared/delayed_batch.rb +74 -67
- data/spec/shared/delayed_method.rb +143 -102
- data/spec/shared/performable_method.rb +39 -38
- data/spec/shared/shared_backend.rb +550 -437
- data/spec/shared/testing.rb +14 -14
- data/spec/shared/worker.rb +156 -148
- data/spec/shared_jobs_specs.rb +13 -13
- data/spec/spec_helper.rb +53 -55
- metadata +148 -82
- data/lib/delayed/backend/redis/bulk_update.lua +0 -50
- data/lib/delayed/backend/redis/destroy_job.lua +0 -2
- data/lib/delayed/backend/redis/enqueue.lua +0 -29
- data/lib/delayed/backend/redis/fail_job.lua +0 -5
- data/lib/delayed/backend/redis/find_available.lua +0 -3
- data/lib/delayed/backend/redis/functions.rb +0 -59
- data/lib/delayed/backend/redis/get_and_lock_next_available.lua +0 -17
- data/lib/delayed/backend/redis/includes/jobs_common.lua +0 -203
- data/lib/delayed/backend/redis/job.rb +0 -535
- data/lib/delayed/backend/redis/set_running.lua +0 -5
- data/lib/delayed/backend/redis/tickle_strand.lua +0 -2
- data/spec/gemfiles/42.gemfile +0 -7
- data/spec/gemfiles/50.gemfile +0 -7
- data/spec/gemfiles/51.gemfile +0 -7
- data/spec/gemfiles/52.gemfile +0 -7
- data/spec/gemfiles/60.gemfile +0 -7
- data/spec/redis_job_spec.rb +0 -148
data/spec/shared/testing.rb
CHANGED
@@ -1,28 +1,28 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
cattr_accessor :runs
|
3
|
+
class TestingWorker
|
4
|
+
cattr_accessor :runs
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
end
|
6
|
+
def self.run
|
7
|
+
self.runs += 1
|
10
8
|
end
|
9
|
+
end
|
11
10
|
|
11
|
+
shared_examples_for "Delayed::Testing" do
|
12
12
|
before do
|
13
13
|
TestingWorker.runs = 0
|
14
14
|
end
|
15
15
|
|
16
|
-
describe
|
17
|
-
it
|
16
|
+
describe ".run_job" do
|
17
|
+
it "runs a single queued job" do
|
18
18
|
job = TestingWorker.delay(ignore_transaction: true).run
|
19
19
|
Delayed::Testing.run_job(job)
|
20
20
|
expect(TestingWorker.runs).to eq 1
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
describe
|
25
|
-
it
|
24
|
+
describe ".drain" do
|
25
|
+
it "runs all queued jobs" do
|
26
26
|
3.times { TestingWorker.delay.run }
|
27
27
|
YAML.dump(TestingWorker)
|
28
28
|
Delayed::Testing.drain
|
@@ -30,8 +30,8 @@ shared_examples_for 'Delayed::Testing' do
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
describe
|
34
|
-
it
|
33
|
+
describe "track_created" do
|
34
|
+
it "returns the list of jobs created in the block" do
|
35
35
|
3.times { TestingWorker.delay.run }
|
36
36
|
jobs = Delayed::Testing.track_created { 2.times { TestingWorker.delay.run } }
|
37
37
|
expect(jobs.size).to eq 2
|
@@ -39,8 +39,8 @@ shared_examples_for 'Delayed::Testing' do
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
describe
|
43
|
-
it
|
42
|
+
describe "clear_all!" do
|
43
|
+
it "deletes all queued jobs" do
|
44
44
|
3.times { TestingWorker.delay.run }
|
45
45
|
Delayed::Testing.clear_all!
|
46
46
|
Delayed::Testing.drain
|
data/spec/shared/worker.rb
CHANGED
@@ -1,18 +1,30 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
class TestPlugin < ::Delayed::Plugin
|
4
|
+
cattr_accessor :runs
|
5
|
+
self.runs = 0
|
6
|
+
callbacks do |lifecycle|
|
7
|
+
lifecycle.around(:invoke_job) do |job, *args, &block|
|
8
|
+
TestPlugin.runs += 1
|
9
|
+
block.call(job, *args)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
shared_examples_for "Delayed::Worker" do
|
4
15
|
def job_create(opts = {})
|
5
|
-
Delayed::Job.create({:
|
16
|
+
Delayed::Job.create({ payload_object: SimpleJob.new, queue: Delayed::Settings.queue }.merge(opts))
|
6
17
|
end
|
18
|
+
|
7
19
|
def worker_create(opts = {})
|
8
|
-
Delayed::Worker.new(opts.merge(:
|
20
|
+
Delayed::Worker.new(opts.merge(max_priority: nil, min_priority: nil, quiet: true))
|
9
21
|
end
|
10
22
|
|
11
|
-
before
|
23
|
+
before do
|
12
24
|
@worker = worker_create
|
13
25
|
SimpleJob.runs = 0
|
14
26
|
Delayed::Worker.on_max_failures = nil
|
15
|
-
Delayed::Settings.sleep_delay = ->{ 0.01 }
|
27
|
+
Delayed::Settings.sleep_delay = -> { 0.01 }
|
16
28
|
end
|
17
29
|
|
18
30
|
after do
|
@@ -20,8 +32,8 @@ shared_examples_for 'Delayed::Worker' do
|
|
20
32
|
end
|
21
33
|
|
22
34
|
describe "running a job" do
|
23
|
-
it "
|
24
|
-
@job = "Some % Name here".delay(ignore_transaction: true).
|
35
|
+
it "does not fail when running a job with a % in the name" do
|
36
|
+
@job = "Some % Name here".delay(ignore_transaction: true).start_with?("Some % Name")
|
25
37
|
@worker.perform(@job)
|
26
38
|
end
|
27
39
|
end
|
@@ -37,91 +49,99 @@ shared_examples_for 'Delayed::Worker' do
|
|
37
49
|
Delayed::Worker.lifecycle.reset!
|
38
50
|
end
|
39
51
|
|
40
|
-
it "
|
52
|
+
it "runs each job in order" do
|
41
53
|
bar = +"bar"
|
42
54
|
expect(bar).to receive(:scan).with("b").ordered
|
43
55
|
expect(bar).to receive(:scan).with("a").ordered
|
44
56
|
expect(bar).to receive(:scan).with("r").ordered
|
45
57
|
batch = Delayed::Batch::PerformableBatch.new(:serial, [
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
58
|
+
{ payload_object: Delayed::PerformableMethod.new(bar, :scan,
|
59
|
+
args: ["b"]) },
|
60
|
+
{ payload_object: Delayed::PerformableMethod.new(bar, :scan,
|
61
|
+
args: ["a"]) },
|
62
|
+
{ payload_object: Delayed::PerformableMethod.new(bar, :scan,
|
63
|
+
args: ["r"]) }
|
64
|
+
])
|
65
|
+
|
66
|
+
batch_job = Delayed::Job.create payload_object: batch
|
67
|
+
expect(@worker.perform(batch_job)).to eq(3)
|
68
|
+
expect(@runs).to be 4 # batch, plus all jobs
|
54
69
|
end
|
55
70
|
|
56
|
-
it "
|
71
|
+
it "succeeds regardless of the success/failure of its component jobs" do
|
57
72
|
change_setting(Delayed::Settings, :max_attempts, 2) do
|
58
73
|
batch = Delayed::Batch::PerformableBatch.new(:serial, [
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
74
|
+
{ payload_object: Delayed::PerformableMethod.new("foo",
|
75
|
+
:reverse) },
|
76
|
+
{ payload_object: Delayed::PerformableMethod.new(1, :/,
|
77
|
+
args: [0]) },
|
78
|
+
{ payload_object: Delayed::PerformableMethod.new("bar", :scan,
|
79
|
+
args: ["r"]) }
|
80
|
+
])
|
81
|
+
batch_job = Delayed::Job.create payload_object: batch
|
82
|
+
|
83
|
+
expect(@worker.perform(batch_job)).to eq(3)
|
84
|
+
expect(@runs).to be 3 # batch, plus two successful jobs
|
67
85
|
|
68
86
|
to_retry = Delayed::Job.list_jobs(:future, 100)
|
69
|
-
to_retry.size.
|
70
|
-
to_retry[0].payload_object.method.
|
71
|
-
to_retry[0].last_error.
|
72
|
-
to_retry[0].attempts.
|
87
|
+
expect(to_retry.size).to be 1
|
88
|
+
expect(to_retry[0].payload_object.method).to be :/
|
89
|
+
expect(to_retry[0].last_error).to match(/divided by 0/)
|
90
|
+
expect(to_retry[0].attempts).to eq(1)
|
73
91
|
end
|
74
92
|
end
|
75
93
|
|
76
|
-
it "
|
94
|
+
it "retries a failed individual job" do
|
77
95
|
batch = Delayed::Batch::PerformableBatch.new(:serial, [
|
78
|
-
|
79
|
-
|
80
|
-
|
96
|
+
{ payload_object: Delayed::PerformableMethod.new(1,
|
97
|
+
:/,
|
98
|
+
args: [0]) }
|
99
|
+
])
|
100
|
+
batch_job = Delayed::Job.create payload_object: batch
|
81
101
|
|
82
102
|
expect_any_instance_of(Delayed::Job).to receive(:reschedule).once
|
83
|
-
@worker.perform(batch_job).
|
84
|
-
expect(@runs).to
|
103
|
+
expect(@worker.perform(batch_job)).to eq(1)
|
104
|
+
expect(@runs).to be 1 # just the batch
|
85
105
|
end
|
86
106
|
end
|
87
107
|
end
|
88
108
|
|
89
109
|
context "worker prioritization" do
|
90
|
-
before
|
91
|
-
@worker = Delayed::Worker.new(:
|
110
|
+
before do
|
111
|
+
@worker = Delayed::Worker.new(max_priority: 5, min_priority: 2, quiet: true)
|
92
112
|
end
|
93
113
|
|
94
|
-
it "
|
95
|
-
SimpleJob.runs.
|
114
|
+
it "onlies run jobs that are >= min_priority" do
|
115
|
+
expect(SimpleJob.runs).to eq(0)
|
96
116
|
|
97
|
-
job_create(:
|
98
|
-
job_create(:
|
117
|
+
job_create(priority: 1)
|
118
|
+
job_create(priority: 3)
|
99
119
|
@worker.run
|
100
120
|
|
101
|
-
SimpleJob.runs.
|
121
|
+
expect(SimpleJob.runs).to eq(1)
|
102
122
|
end
|
103
123
|
|
104
|
-
it "
|
105
|
-
SimpleJob.runs.
|
124
|
+
it "onlies run jobs that are <= max_priority" do
|
125
|
+
expect(SimpleJob.runs).to eq(0)
|
106
126
|
|
107
|
-
job_create(:
|
108
|
-
job_create(:
|
127
|
+
job_create(priority: 10)
|
128
|
+
job_create(priority: 4)
|
109
129
|
|
110
130
|
@worker.run
|
111
131
|
|
112
|
-
SimpleJob.runs.
|
132
|
+
expect(SimpleJob.runs).to eq(1)
|
113
133
|
end
|
114
134
|
end
|
115
135
|
|
116
136
|
context "while running with locked jobs" do
|
117
|
-
it "
|
118
|
-
job_create(:
|
119
|
-
|
137
|
+
it "does not run jobs locked by another worker" do
|
138
|
+
job_create(locked_by: "other_worker", locked_at: (Delayed::Job.db_time_now - 1.minute))
|
139
|
+
expect { @worker.run }.not_to(change(SimpleJob, :runs))
|
120
140
|
end
|
121
141
|
|
122
|
-
it "
|
142
|
+
it "runs open jobs" do
|
123
143
|
job_create
|
124
|
-
|
144
|
+
expect { @worker.run }.to change(SimpleJob, :runs).from(0).to(1)
|
125
145
|
end
|
126
146
|
end
|
127
147
|
|
@@ -132,74 +152,74 @@ shared_examples_for 'Delayed::Worker' do
|
|
132
152
|
@job = Delayed::Job.enqueue ErrorJob.new
|
133
153
|
end
|
134
154
|
|
135
|
-
it "
|
155
|
+
it "records last_error when destroy_failed_jobs = false, max_attempts = 1" do
|
136
156
|
Delayed::Worker.on_max_failures = proc { false }
|
137
157
|
@job.max_attempts = 1
|
138
158
|
@job.save!
|
139
|
-
(job = Delayed::Job.get_and_lock_next_available(
|
159
|
+
expect(job = Delayed::Job.get_and_lock_next_available("w1")).to eq(@job)
|
140
160
|
@worker.perform(job)
|
141
161
|
old_id = @job.id
|
142
162
|
@job = Delayed::Job.list_jobs(:failed, 1).first
|
143
|
-
@job.original_job_id.
|
144
|
-
@job.last_error.
|
145
|
-
@job.last_error.
|
146
|
-
@job.attempts.
|
147
|
-
@job.failed_at.
|
148
|
-
@job.run_at.
|
149
|
-
@job.run_at.
|
163
|
+
expect(@job.original_job_id).to eq(old_id)
|
164
|
+
expect(@job.last_error).to match(/did not work/)
|
165
|
+
expect(@job.last_error).to match(%r{shared/worker.rb})
|
166
|
+
expect(@job.attempts).to eq(1)
|
167
|
+
expect(@job.failed_at).not_to be_nil
|
168
|
+
expect(@job.run_at).to be > Delayed::Job.db_time_now - 10.minutes
|
169
|
+
expect(@job.run_at).to be < Delayed::Job.db_time_now + 10.minutes
|
150
170
|
# job stays locked after failing, for record keeping of time/worker
|
151
|
-
@job.
|
171
|
+
expect(@job).to be_locked
|
152
172
|
|
153
|
-
Delayed::Job.find_available(100, @job.queue).
|
173
|
+
expect(Delayed::Job.find_available(100, @job.queue)).to eq([])
|
154
174
|
end
|
155
175
|
|
156
|
-
it "
|
176
|
+
it "re-schedules jobs after failing" do
|
157
177
|
@worker.perform(@job)
|
158
178
|
@job = Delayed::Job.find(@job.id)
|
159
|
-
@job.last_error.
|
160
|
-
@job.last_error.
|
161
|
-
@job.attempts.
|
162
|
-
@job.run_at.
|
163
|
-
@job.run_at.
|
179
|
+
expect(@job.last_error).to match(/did not work/)
|
180
|
+
expect(@job.last_error).to match(/sample_jobs.rb:22:in `perform'/)
|
181
|
+
expect(@job.attempts).to eq(1)
|
182
|
+
expect(@job.run_at).to be > Delayed::Job.db_time_now - 10.minutes
|
183
|
+
expect(@job.run_at).to be < Delayed::Job.db_time_now + 10.minutes
|
164
184
|
end
|
165
185
|
|
166
|
-
it "
|
186
|
+
it "accepts :unlock return value from on_failure during reschedule and unlock the job" do
|
167
187
|
expect_any_instance_of(Delayed::Job).to receive(:unlock).once
|
168
188
|
@job = Delayed::Job.enqueue(UnlockJob.new(1))
|
169
189
|
@worker.perform(@job)
|
170
190
|
end
|
171
191
|
|
172
|
-
it "
|
192
|
+
it "notifies jobs on failure" do
|
173
193
|
ErrorJob.failure_runs = 0
|
174
194
|
@worker.perform(@job)
|
175
|
-
ErrorJob.failure_runs.
|
195
|
+
expect(ErrorJob.failure_runs).to eq(1)
|
176
196
|
end
|
177
197
|
|
178
|
-
it "
|
198
|
+
it "notifies jobs on permanent failure" do
|
179
199
|
(Delayed::Settings.max_attempts - 1).times { @job.reschedule }
|
180
200
|
ErrorJob.permanent_failure_runs = 0
|
181
201
|
@worker.perform(@job)
|
182
|
-
ErrorJob.permanent_failure_runs.
|
202
|
+
expect(ErrorJob.permanent_failure_runs).to eq(1)
|
183
203
|
end
|
184
204
|
end
|
185
205
|
|
186
206
|
context "reschedule" do
|
187
207
|
before do
|
188
|
-
@job = Delayed::Job.create :
|
208
|
+
@job = Delayed::Job.create payload_object: SimpleJob.new
|
189
209
|
end
|
190
210
|
|
191
211
|
context "and we want to destroy jobs" do
|
192
|
-
it "
|
212
|
+
it "is destroyed if it failed more than Settings.max_attempts times" do
|
193
213
|
expect(@job).to receive(:destroy)
|
194
214
|
Delayed::Settings.max_attempts.times { @job.reschedule }
|
195
215
|
end
|
196
216
|
|
197
|
-
it "
|
198
|
-
expect(@job).
|
217
|
+
it "is not destroyed if failed fewer than Settings.max_attempts times" do
|
218
|
+
expect(@job).not_to receive(:destroy)
|
199
219
|
(Delayed::Settings.max_attempts - 1).times { @job.reschedule }
|
200
220
|
end
|
201
221
|
|
202
|
-
it "
|
222
|
+
it "is destroyed if failed more than Job#max_attempts times" do
|
203
223
|
Delayed::Settings.max_attempts = 25
|
204
224
|
expect(@job).to receive(:destroy)
|
205
225
|
@job.max_attempts = 2
|
@@ -207,8 +227,8 @@ shared_examples_for 'Delayed::Worker' do
|
|
207
227
|
2.times { @job.reschedule }
|
208
228
|
end
|
209
229
|
|
210
|
-
it "
|
211
|
-
job = Delayed::Job.create :
|
230
|
+
it "is destroyed if it has expired" do
|
231
|
+
job = Delayed::Job.create payload_object: SimpleJob.new, expires_at: Delayed::Job.db_time_now - 1.day
|
212
232
|
expect(job).to receive(:destroy)
|
213
233
|
job.reschedule
|
214
234
|
end
|
@@ -223,38 +243,38 @@ shared_examples_for 'Delayed::Worker' do
|
|
223
243
|
Delayed::Worker.on_max_failures = nil
|
224
244
|
end
|
225
245
|
|
226
|
-
it "
|
227
|
-
@job.failed_at.
|
246
|
+
it "is failed if it failed more than Settings.max_attempts times" do
|
247
|
+
expect(@job.failed_at).to eq(nil)
|
228
248
|
Delayed::Settings.max_attempts.times { @job.reschedule }
|
229
|
-
Delayed::Job.list_jobs(:failed, 100).size.
|
249
|
+
expect(Delayed::Job.list_jobs(:failed, 100).size).to eq(1)
|
230
250
|
end
|
231
251
|
|
232
|
-
it "
|
252
|
+
it "is not failed if it failed fewer than Settings.max_attempts times" do
|
233
253
|
(Delayed::Settings.max_attempts - 1).times { @job.reschedule }
|
234
254
|
@job = Delayed::Job.find(@job.id)
|
235
|
-
@job.failed_at.
|
255
|
+
expect(@job.failed_at).to eq(nil)
|
236
256
|
end
|
237
257
|
|
238
|
-
it "
|
239
|
-
job = Delayed::Job.create :
|
258
|
+
it "is failed if it has expired" do
|
259
|
+
job = Delayed::Job.create payload_object: SimpleJob.new, expires_at: Delayed::Job.db_time_now - 1.day
|
240
260
|
expect(job).to receive(:fail!)
|
241
261
|
job.reschedule
|
242
262
|
end
|
243
263
|
end
|
244
264
|
|
245
265
|
context "and we give an on_max_failures callback" do
|
246
|
-
it "
|
247
|
-
Delayed::Worker.on_max_failures = proc do |job,
|
248
|
-
job.
|
266
|
+
it "is failed max_attempts times and cb is false" do
|
267
|
+
Delayed::Worker.on_max_failures = proc do |job, _ex|
|
268
|
+
expect(job).to eq(@job)
|
249
269
|
false
|
250
270
|
end
|
251
271
|
expect(@job).to receive(:fail!)
|
252
272
|
Delayed::Settings.max_attempts.times { @job.reschedule }
|
253
273
|
end
|
254
274
|
|
255
|
-
it "
|
256
|
-
Delayed::Worker.on_max_failures = proc do |job,
|
257
|
-
job.
|
275
|
+
it "is destroyed if it failed max_attempts times and cb is true" do
|
276
|
+
Delayed::Worker.on_max_failures = proc do |job, _ex|
|
277
|
+
expect(job).to eq(@job)
|
258
278
|
true
|
259
279
|
end
|
260
280
|
expect(@job).to receive(:destroy)
|
@@ -263,68 +283,56 @@ shared_examples_for 'Delayed::Worker' do
|
|
263
283
|
end
|
264
284
|
end
|
265
285
|
|
266
|
-
|
267
286
|
context "Queue workers" do
|
268
|
-
before
|
287
|
+
before do
|
269
288
|
Delayed::Settings.queue = "Queue workers test"
|
270
|
-
job_create(:
|
271
|
-
job_create(:
|
289
|
+
job_create(queue: "queue1")
|
290
|
+
job_create(queue: "queue2")
|
272
291
|
end
|
273
292
|
|
274
|
-
it "
|
275
|
-
worker = worker_create(:
|
276
|
-
SimpleJob.runs.
|
293
|
+
it "onlies work off jobs assigned to themselves" do
|
294
|
+
worker = worker_create(queue: "queue1")
|
295
|
+
expect(SimpleJob.runs).to eq(0)
|
277
296
|
worker.run
|
278
|
-
SimpleJob.runs.
|
297
|
+
expect(SimpleJob.runs).to eq(1)
|
279
298
|
|
280
299
|
SimpleJob.runs = 0
|
281
300
|
|
282
|
-
worker = worker_create(:
|
283
|
-
SimpleJob.runs.
|
301
|
+
worker = worker_create(queue: "queue2")
|
302
|
+
expect(SimpleJob.runs).to eq(0)
|
284
303
|
worker.run
|
285
|
-
SimpleJob.runs.
|
304
|
+
expect(SimpleJob.runs).to eq(1)
|
286
305
|
end
|
287
306
|
|
288
|
-
it "
|
289
|
-
worker = worker_create(:
|
307
|
+
it "does not work off jobs not assigned to themselves" do
|
308
|
+
worker = worker_create(queue: "queue3")
|
290
309
|
|
291
|
-
SimpleJob.runs.
|
310
|
+
expect(SimpleJob.runs).to eq(0)
|
292
311
|
worker.run
|
293
|
-
SimpleJob.runs.
|
312
|
+
expect(SimpleJob.runs).to eq(0)
|
294
313
|
end
|
295
314
|
|
296
|
-
it "
|
315
|
+
it "gets the default queue if none is set" do
|
297
316
|
queue_name = "default_queue"
|
298
317
|
Delayed::Settings.queue = queue_name
|
299
|
-
worker = worker_create(:
|
300
|
-
worker.queue_name.
|
318
|
+
worker = worker_create(queue: nil)
|
319
|
+
expect(worker.queue_name).to eq(queue_name)
|
301
320
|
end
|
302
321
|
|
303
|
-
it "
|
322
|
+
it "overrides default queue name if specified in initialize" do
|
304
323
|
queue_name = "my_queue"
|
305
324
|
Delayed::Settings.queue = "default_queue"
|
306
|
-
worker = worker_create(:
|
307
|
-
worker.queue_name.
|
325
|
+
worker = worker_create(queue: queue_name)
|
326
|
+
expect(worker.queue_name).to eq(queue_name)
|
308
327
|
end
|
309
328
|
end
|
310
329
|
|
311
330
|
context "plugins" do
|
312
|
-
|
313
|
-
cattr_accessor :runs
|
314
|
-
self.runs = 0
|
315
|
-
callbacks do |lifecycle|
|
316
|
-
lifecycle.around(:invoke_job) do |job, *args, &block|
|
317
|
-
TestPlugin.runs += 1
|
318
|
-
block.call(job, *args)
|
319
|
-
end
|
320
|
-
end
|
321
|
-
end
|
322
|
-
|
323
|
-
it "should create and call the plugin callbacks" do
|
331
|
+
it "creates and call the plugin callbacks" do
|
324
332
|
TestPlugin.runs = 0
|
325
333
|
Delayed::Worker.plugins << TestPlugin
|
326
334
|
job_create
|
327
|
-
@worker = Delayed::Worker.new(:
|
335
|
+
@worker = Delayed::Worker.new(quiet: true)
|
328
336
|
@worker.run
|
329
337
|
expect(TestPlugin.runs).to eq(1)
|
330
338
|
expect(SimpleJob.runs).to eq(1)
|
@@ -332,52 +340,52 @@ shared_examples_for 'Delayed::Worker' do
|
|
332
340
|
end
|
333
341
|
|
334
342
|
describe "expires_at" do
|
335
|
-
it "
|
336
|
-
Delayed::Job.enqueue SimpleJob.new, :
|
337
|
-
expect { @worker.run }.to change
|
343
|
+
it "runs non-expired jobs" do
|
344
|
+
Delayed::Job.enqueue SimpleJob.new, expires_at: Delayed::Job.db_time_now + 1.day
|
345
|
+
expect { @worker.run }.to change(SimpleJob, :runs).by(1)
|
338
346
|
end
|
339
347
|
|
340
|
-
it "
|
341
|
-
Delayed::Job.enqueue SimpleJob.new, :
|
342
|
-
expect { @worker.run }.to change
|
348
|
+
it "does not run expired jobs" do
|
349
|
+
Delayed::Job.enqueue SimpleJob.new, expires_at: Delayed::Job.db_time_now - 1.day
|
350
|
+
expect { @worker.run }.to change(SimpleJob, :runs).by(0)
|
343
351
|
end
|
344
352
|
|
345
|
-
it "
|
353
|
+
it "reports a permanent failure when an expired job is dequeued" do
|
346
354
|
ErrorJob.last_error = nil
|
347
|
-
Delayed::Job.enqueue ErrorJob.new, :
|
348
|
-
expect { @worker.run }.to change
|
355
|
+
Delayed::Job.enqueue ErrorJob.new, expires_at: Delayed::Job.db_time_now - 1.day
|
356
|
+
expect { @worker.run }.to change(ErrorJob, :permanent_failure_runs).by(1)
|
349
357
|
expect(ErrorJob.last_error).to be_a Delayed::Backend::JobExpired
|
350
358
|
end
|
351
359
|
end
|
352
360
|
|
353
361
|
describe "delay failure callbacks" do
|
354
|
-
it "
|
362
|
+
it "calls the on_failure callback" do
|
355
363
|
ErrorJob.last_error = nil
|
356
364
|
ErrorJob.new.delay(max_attempts: 2, on_failure: :on_failure).perform
|
357
|
-
expect { @worker.run }.to change
|
358
|
-
expect(ErrorJob.last_error.to_s).to eq
|
365
|
+
expect { @worker.run }.to change(ErrorJob, :failure_runs).by(1)
|
366
|
+
expect(ErrorJob.last_error.to_s).to eq "did not work"
|
359
367
|
end
|
360
368
|
|
361
|
-
it "
|
369
|
+
it "calls the on_permanent_failure callback" do
|
362
370
|
ErrorJob.last_error = nil
|
363
371
|
ErrorJob.new.delay(max_attempts: 1, on_permanent_failure: :on_failure).perform
|
364
|
-
expect { @worker.run }.to change
|
365
|
-
expect(ErrorJob.last_error.to_s).to eq
|
372
|
+
expect { @worker.run }.to change(ErrorJob, :failure_runs).by(1)
|
373
|
+
expect(ErrorJob.last_error.to_s).to eq "did not work"
|
366
374
|
end
|
367
375
|
end
|
368
376
|
|
369
377
|
describe "custom deserialization errors" do
|
370
|
-
it "
|
371
|
-
job = Delayed::Job.create({:
|
378
|
+
it "reschedules with more attempts left" do
|
379
|
+
job = Delayed::Job.create({ payload_object: DeserializeErrorJob.new, max_attempts: 2 })
|
372
380
|
job.instance_variable_set("@payload_object", nil)
|
373
|
-
worker = Delayed::Worker.new(:
|
381
|
+
worker = Delayed::Worker.new(max_priority: nil, min_priority: nil, quiet: true)
|
374
382
|
expect { worker.perform(job) }.not_to raise_error
|
375
383
|
end
|
376
384
|
|
377
385
|
it "run permanent failure code on last attempt" do
|
378
|
-
job = Delayed::Job.create({:
|
386
|
+
job = Delayed::Job.create({ payload_object: DeserializeErrorJob.new, max_attempts: 1 })
|
379
387
|
job.instance_variable_set("@payload_object", nil)
|
380
|
-
worker = Delayed::Worker.new(:
|
388
|
+
worker = Delayed::Worker.new(max_priority: nil, min_priority: nil, quiet: true)
|
381
389
|
expect { worker.perform(job) }.not_to raise_error
|
382
390
|
end
|
383
391
|
end
|
data/spec/shared_jobs_specs.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
3
|
+
require_relative "shared/delayed_batch"
|
4
|
+
require_relative "shared/delayed_method"
|
5
|
+
require_relative "shared/performable_method"
|
6
|
+
require_relative "shared/shared_backend"
|
7
|
+
require_relative "shared/testing"
|
8
|
+
require_relative "shared/worker"
|
9
9
|
|
10
|
-
shared_examples_for
|
11
|
-
include_examples
|
12
|
-
include_examples
|
13
|
-
include_examples
|
14
|
-
include_examples
|
15
|
-
include_examples
|
16
|
-
include_examples
|
10
|
+
shared_examples_for "a delayed_jobs implementation" do
|
11
|
+
include_examples "a backend"
|
12
|
+
include_examples "Delayed::Batch"
|
13
|
+
include_examples "random ruby objects"
|
14
|
+
include_examples "Delayed::PerformableMethod"
|
15
|
+
include_examples "Delayed::Worker"
|
16
|
+
include_examples "Delayed::Testing"
|
17
17
|
end
|