inst-jobs 3.0.8 → 3.1.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/db/migrate/20200330230722_add_id_to_get_delayed_jobs_index.rb +4 -2
  3. data/db/migrate/20200825011002_add_strand_order_override.rb +2 -1
  4. data/db/migrate/20210809145804_add_n_strand_index.rb +2 -1
  5. data/db/migrate/20220328152900_add_failed_jobs_indicies.rb +12 -0
  6. data/db/migrate/20220519204546_add_requeued_job_id_to_failed_jobs.rb +7 -0
  7. data/lib/delayed/backend/active_record.rb +63 -6
  8. data/lib/delayed/backend/base.rb +28 -10
  9. data/lib/delayed/batch.rb +1 -1
  10. data/lib/delayed/cli.rb +3 -2
  11. data/lib/delayed/lifecycle.rb +9 -2
  12. data/lib/delayed/log_tailer.rb +2 -2
  13. data/lib/delayed/message_sending.rb +8 -5
  14. data/lib/delayed/performable_method.rb +22 -16
  15. data/lib/delayed/periodic.rb +2 -2
  16. data/lib/delayed/pool.rb +12 -2
  17. data/lib/delayed/server.rb +8 -2
  18. data/lib/delayed/settings.rb +5 -1
  19. data/lib/delayed/version.rb +1 -1
  20. data/lib/delayed/work_queue/parent_process/server.rb +7 -3
  21. data/lib/delayed/worker/health_check.rb +1 -1
  22. data/lib/delayed/worker/process_helper.rb +4 -4
  23. data/lib/delayed/worker.rb +8 -8
  24. metadata +16 -89
  25. data/spec/active_record_job_spec.rb +0 -294
  26. data/spec/delayed/cli_spec.rb +0 -25
  27. data/spec/delayed/daemon_spec.rb +0 -38
  28. data/spec/delayed/message_sending_spec.rb +0 -108
  29. data/spec/delayed/periodic_spec.rb +0 -32
  30. data/spec/delayed/server_spec.rb +0 -103
  31. data/spec/delayed/settings_spec.rb +0 -48
  32. data/spec/delayed/work_queue/in_process_spec.rb +0 -31
  33. data/spec/delayed/work_queue/parent_process/client_spec.rb +0 -87
  34. data/spec/delayed/work_queue/parent_process/server_spec.rb +0 -280
  35. data/spec/delayed/work_queue/parent_process_spec.rb +0 -60
  36. data/spec/delayed/worker/consul_health_check_spec.rb +0 -63
  37. data/spec/delayed/worker/health_check_spec.rb +0 -134
  38. data/spec/delayed/worker_spec.rb +0 -105
  39. data/spec/migrate/20140924140513_add_story_table.rb +0 -9
  40. data/spec/sample_jobs.rb +0 -79
  41. data/spec/shared/delayed_batch.rb +0 -105
  42. data/spec/shared/delayed_method.rb +0 -287
  43. data/spec/shared/performable_method.rb +0 -75
  44. data/spec/shared/shared_backend.rb +0 -1221
  45. data/spec/shared/testing.rb +0 -50
  46. data/spec/shared/worker.rb +0 -413
  47. data/spec/shared_jobs_specs.rb +0 -17
  48. data/spec/spec_helper.rb +0 -136
@@ -9,9 +9,9 @@ module Delayed
9
9
  ALIVE_CHECK_LINUX = '[ -d "/proc/$WORKER_PID" ]'
10
10
  ALIVE_CHECK_MAC = "ps -p $WORKER_PID > /dev/null"
11
11
  ALIVE_CHECK = RUBY_PLATFORM.include?("darwin") ? ALIVE_CHECK_MAC : ALIVE_CHECK_LINUX
12
- SCRIPT_TEMPLATE = <<-BASH
13
- WORKER_PID="%<pid>d" # an example, filled from ruby when the check is created
14
- ORIGINAL_MTIME="%<mtime>s" # an example, filled from ruby when the check is created
12
+ SCRIPT_TEMPLATE = <<~SH
13
+ WORKER_PID="%{pid}" # an example, filled from ruby when the check is created
14
+ ORIGINAL_MTIME="%{mtime}" # an example, filled from ruby when the check is created
15
15
 
16
16
  if #{ALIVE_CHECK}; then
17
17
  CURRENT_MTIME=$(#{STAT})
@@ -26,7 +26,7 @@ module Delayed
26
26
  else
27
27
  exit 255 # The process is no more, trigger a "critical" state.
28
28
  fi
29
- BASH
29
+ SH
30
30
 
31
31
  def self.mtime(pid)
32
32
  if RUBY_PLATFORM.include?("darwin")
@@ -77,7 +77,7 @@ module Delayed
77
77
  end
78
78
 
79
79
  def name
80
- @name ||= "#{Socket.gethostname rescue 'X'}:#{id}"
80
+ @name ||= "#{Socket.gethostname rescue "X"}:#{id}"
81
81
  end
82
82
 
83
83
  def process_name=(new_name)
@@ -100,7 +100,7 @@ module Delayed
100
100
  def start
101
101
  logger.info "Starting worker"
102
102
  self.process_name =
103
- "start:#{Settings.worker_procname_prefix}#{@queue_name}:#{min_priority || 0}:#{max_priority || 'max'}"
103
+ "start:#{Settings.worker_procname_prefix}#{@queue_name}:#{min_priority || 0}:#{max_priority || "max"}"
104
104
  @self_pipe = IO.pipe
105
105
  work_queue.init
106
106
 
@@ -170,7 +170,7 @@ module Delayed
170
170
 
171
171
  self.class.lifecycle.run_callbacks(:loop, self) do
172
172
  self.process_name =
173
- "pop:#{Settings.worker_procname_prefix}#{@queue_name}:#{min_priority || 0}:#{max_priority || 'max'}"
173
+ "pop:#{Settings.worker_procname_prefix}#{@queue_name}:#{min_priority || 0}:#{max_priority || "max"}"
174
174
  job = self.class.lifecycle.run_callbacks(:pop, self) do
175
175
  work_queue.get_and_lock_next_available(name, config)
176
176
  end
@@ -196,7 +196,7 @@ module Delayed
196
196
  end
197
197
  else
198
198
  self.process_name =
199
- "wait:#{Settings.worker_procname_prefix}#{@queue_name}:#{min_priority || 0}:#{max_priority || 'max'}"
199
+ "wait:#{Settings.worker_procname_prefix}#{@queue_name}:#{min_priority || 0}:#{max_priority || "max"}"
200
200
  sleep(Settings.sleep_delay + (rand * Settings.sleep_delay_stagger)) unless exit?
201
201
  end
202
202
  end
@@ -220,7 +220,7 @@ module Delayed
220
220
  end
221
221
  job.destroy
222
222
  end
223
- logger.info("Completed #{log_job(job)} #{format('%.0fms', (runtime * 1000))}")
223
+ logger.info("Completed #{log_job(job, :short)} #{format("%.0fms", (runtime * 1000))}")
224
224
  end
225
225
  rescue ::Delayed::RetriableError => e
226
226
  can_retry = job.attempts + 1 < job.inferred_max_attempts
@@ -269,17 +269,17 @@ module Delayed
269
269
  when :long
270
270
  "#{job.full_name} #{Settings.job_detailed_log_format.call(job)}"
271
271
  else
272
- job.full_name
272
+ "#{job.full_name} #{Settings.job_short_log_format.call(job)}".strip
273
273
  end
274
274
  end
275
275
 
276
276
  # set up the session context information, so that it gets logged with the job log lines
277
277
  # also set up a unique tmpdir, which will get removed at the end of the job.
278
278
  def configure_for_job(job)
279
- previous_tmpdir = ENV["TMPDIR"]
279
+ previous_tmpdir = ENV.fetch("TMPDIR", nil)
280
280
 
281
281
  self.class.running_job(job) do
282
- dir = Dir.mktmpdir("job-#{job.id}-#{name.gsub(/[^\w.]/, '.')}-")
282
+ dir = Dir.mktmpdir("job-#{job.id}-#{name.gsub(/[^\w.]/, ".")}-")
283
283
  begin
284
284
  ENV["TMPDIR"] = dir
285
285
  yield
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inst-jobs
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.8
4
+ version: 3.1.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cody Cutrer
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2022-02-03 00:00:00.000000000 Z
13
+ date: 2023-08-25 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
@@ -32,14 +32,14 @@ dependencies:
32
32
  requirements:
33
33
  - - "~>"
34
34
  - !ruby/object:Gem::Version
35
- version: '0.4'
35
+ version: 0.4.4
36
36
  type: :runtime
37
37
  prerelease: false
38
38
  version_requirements: !ruby/object:Gem::Requirement
39
39
  requirements:
40
40
  - - "~>"
41
41
  - !ruby/object:Gem::Version
42
- version: '0.4'
42
+ version: 0.4.4
43
43
  - !ruby/object:Gem::Dependency
44
44
  name: activesupport
45
45
  requirement: !ruby/object:Gem::Requirement
@@ -192,14 +192,14 @@ dependencies:
192
192
  requirements:
193
193
  - - "~>"
194
194
  - !ruby/object:Gem::Version
195
- version: 2.5.1
195
+ version: 2.6.3
196
196
  type: :development
197
197
  prerelease: false
198
198
  version_requirements: !ruby/object:Gem::Requirement
199
199
  requirements:
200
200
  - - "~>"
201
201
  - !ruby/object:Gem::Version
202
- version: 2.5.1
202
+ version: 2.6.3
203
203
  - !ruby/object:Gem::Dependency
204
204
  name: pg
205
205
  requirement: !ruby/object:Gem::Requirement
@@ -285,33 +285,19 @@ dependencies:
285
285
  - !ruby/object:Gem::Version
286
286
  version: '3.10'
287
287
  - !ruby/object:Gem::Dependency
288
- name: rubocop
288
+ name: rubocop-inst
289
289
  requirement: !ruby/object:Gem::Requirement
290
290
  requirements:
291
291
  - - "~>"
292
292
  - !ruby/object:Gem::Version
293
- version: '1.19'
293
+ version: '1'
294
294
  type: :development
295
295
  prerelease: false
296
296
  version_requirements: !ruby/object:Gem::Requirement
297
297
  requirements:
298
298
  - - "~>"
299
299
  - !ruby/object:Gem::Version
300
- version: '1.19'
301
- - !ruby/object:Gem::Dependency
302
- name: rubocop-performance
303
- requirement: !ruby/object:Gem::Requirement
304
- requirements:
305
- - - "~>"
306
- - !ruby/object:Gem::Version
307
- version: 1.12.0
308
- type: :development
309
- prerelease: false
310
- version_requirements: !ruby/object:Gem::Requirement
311
- requirements:
312
- - - "~>"
313
- - !ruby/object:Gem::Version
314
- version: 1.12.0
300
+ version: '1'
315
301
  - !ruby/object:Gem::Dependency
316
302
  name: rubocop-rails
317
303
  requirement: !ruby/object:Gem::Requirement
@@ -410,20 +396,6 @@ dependencies:
410
396
  - - ">="
411
397
  - !ruby/object:Gem::Version
412
398
  version: '0'
413
- - !ruby/object:Gem::Dependency
414
- name: wwtd
415
- requirement: !ruby/object:Gem::Requirement
416
- requirements:
417
- - - "~>"
418
- - !ruby/object:Gem::Version
419
- version: 1.4.0
420
- type: :development
421
- prerelease: false
422
- version_requirements: !ruby/object:Gem::Requirement
423
- requirements:
424
- - - "~>"
425
- - !ruby/object:Gem::Version
426
- version: 1.4.0
427
399
  description:
428
400
  email:
429
401
  - cody@instructure.com
@@ -473,6 +445,8 @@ files:
473
445
  - db/migrate/20220128084800_update_insert_trigger_for_singleton_unique_constraint_change.rb
474
446
  - db/migrate/20220128084900_update_delete_trigger_for_singleton_unique_constraint_change.rb
475
447
  - db/migrate/20220203063200_remove_old_singleton_index.rb
448
+ - db/migrate/20220328152900_add_failed_jobs_indicies.rb
449
+ - db/migrate/20220519204546_add_requeued_job_id_to_failed_jobs.rb
476
450
  - exe/inst_jobs
477
451
  - lib/delayed/backend/active_record.rb
478
452
  - lib/delayed/backend/base.rb
@@ -512,33 +486,10 @@ files:
512
486
  - lib/delayed/yaml_extensions.rb
513
487
  - lib/delayed_job.rb
514
488
  - lib/inst-jobs.rb
515
- - spec/active_record_job_spec.rb
516
- - spec/delayed/cli_spec.rb
517
- - spec/delayed/daemon_spec.rb
518
- - spec/delayed/message_sending_spec.rb
519
- - spec/delayed/periodic_spec.rb
520
- - spec/delayed/server_spec.rb
521
- - spec/delayed/settings_spec.rb
522
- - spec/delayed/work_queue/in_process_spec.rb
523
- - spec/delayed/work_queue/parent_process/client_spec.rb
524
- - spec/delayed/work_queue/parent_process/server_spec.rb
525
- - spec/delayed/work_queue/parent_process_spec.rb
526
- - spec/delayed/worker/consul_health_check_spec.rb
527
- - spec/delayed/worker/health_check_spec.rb
528
- - spec/delayed/worker_spec.rb
529
- - spec/migrate/20140924140513_add_story_table.rb
530
- - spec/sample_jobs.rb
531
- - spec/shared/delayed_batch.rb
532
- - spec/shared/delayed_method.rb
533
- - spec/shared/performable_method.rb
534
- - spec/shared/shared_backend.rb
535
- - spec/shared/testing.rb
536
- - spec/shared/worker.rb
537
- - spec/shared_jobs_specs.rb
538
- - spec/spec_helper.rb
539
489
  homepage: https://github.com/instructure/inst-jobs
540
490
  licenses: []
541
- metadata: {}
491
+ metadata:
492
+ rubygems_mfa_required: 'true'
542
493
  post_install_message:
543
494
  rdoc_options: []
544
495
  require_paths:
@@ -547,39 +498,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
547
498
  requirements:
548
499
  - - ">="
549
500
  - !ruby/object:Gem::Version
550
- version: '2.6'
501
+ version: '2.7'
551
502
  required_rubygems_version: !ruby/object:Gem::Requirement
552
503
  requirements:
553
504
  - - ">="
554
505
  - !ruby/object:Gem::Version
555
506
  version: '0'
556
507
  requirements: []
557
- rubygems_version: 3.1.4
508
+ rubygems_version: 3.1.6
558
509
  signing_key:
559
510
  specification_version: 4
560
511
  summary: Instructure-maintained fork of delayed_job
561
- test_files:
562
- - spec/active_record_job_spec.rb
563
- - spec/delayed/cli_spec.rb
564
- - spec/delayed/daemon_spec.rb
565
- - spec/delayed/message_sending_spec.rb
566
- - spec/delayed/periodic_spec.rb
567
- - spec/delayed/server_spec.rb
568
- - spec/delayed/settings_spec.rb
569
- - spec/delayed/work_queue/in_process_spec.rb
570
- - spec/delayed/work_queue/parent_process/client_spec.rb
571
- - spec/delayed/work_queue/parent_process/server_spec.rb
572
- - spec/delayed/work_queue/parent_process_spec.rb
573
- - spec/delayed/worker/consul_health_check_spec.rb
574
- - spec/delayed/worker/health_check_spec.rb
575
- - spec/delayed/worker_spec.rb
576
- - spec/migrate/20140924140513_add_story_table.rb
577
- - spec/sample_jobs.rb
578
- - spec/shared/delayed_batch.rb
579
- - spec/shared/delayed_method.rb
580
- - spec/shared/performable_method.rb
581
- - spec/shared/shared_backend.rb
582
- - spec/shared/testing.rb
583
- - spec/shared/worker.rb
584
- - spec/shared_jobs_specs.rb
585
- - spec/spec_helper.rb
512
+ test_files: []
@@ -1,294 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- describe "Delayed::Backed::ActiveRecord::Job" do
4
- before :all do
5
- Delayed.select_backend(Delayed::Backend::ActiveRecord::Job)
6
- end
7
-
8
- before do
9
- Delayed::Testing.clear_all!
10
- end
11
-
12
- include_examples "a delayed_jobs implementation"
13
-
14
- it "recovers as well as possible from a failure failing a job" do
15
- allow(Delayed::Job::Failed).to receive(:create).and_raise(RuntimeError)
16
- job = "test".delay(ignore_transaction: true).reverse
17
- job_id = job.id
18
- expect { job.fail! }.to raise_error(RuntimeError)
19
- expect { Delayed::Job.find(job_id) }.to raise_error(ActiveRecord::RecordNotFound)
20
- expect(Delayed::Job.count).to eq(0)
21
- end
22
-
23
- context "when another worker has worked on a task since the job was found to be available, it" do
24
- before do
25
- @job = Delayed::Job.create payload_object: SimpleJob.new
26
- @job_copy_for_worker2 = Delayed::Job.find(@job.id)
27
- end
28
-
29
- it "does not allow a second worker to get exclusive access if already successfully processed by worker1" do
30
- @job.destroy
31
- expect(@job_copy_for_worker2.send(:lock_exclusively!, "worker2")).to eq(false)
32
- end
33
-
34
- it "doesn't allow a second worker to get exclusive access if failed to be " \
35
- "processed by worker1 and run_at time is now in future (due to backing off behaviour)" do
36
- @job.update(attempts: 1, run_at: 1.day.from_now)
37
- expect(@job_copy_for_worker2.send(:lock_exclusively!, "worker2")).to eq(false)
38
- end
39
-
40
- it "selects the next job at random if enabled" do
41
- Delayed::Settings.select_random_from_batch = true
42
- 15.times { "test".delay.length }
43
- founds = []
44
- 15.times do
45
- job = Delayed::Job.get_and_lock_next_available("tester")
46
- founds << job
47
- job.unlock
48
- job.save!
49
- end
50
- expect(founds.uniq.size).to be > 1
51
- ensure
52
- Delayed::Settings.select_random_from_batch = false
53
- end
54
- end
55
-
56
- it "unlocks a successfully locked job and persist the job's unlocked state" do
57
- job = Delayed::Job.create payload_object: SimpleJob.new
58
- expect(job.send(:lock_exclusively!, "worker1")).to eq(true)
59
- job.reload
60
- job.unlock
61
- job.save!
62
- job.reload
63
- expect(job.locked_by).to eq(nil)
64
- expect(job.locked_at).to eq(nil)
65
- end
66
-
67
- describe "bulk_update failed jobs" do
68
- context "holding/unholding failed jobs" do
69
- before do
70
- @job = Delayed::Job.create payload_object: SimpleJob.new
71
- expect(Delayed::Job.get_and_lock_next_available("worker1")).to eq(@job)
72
- @job.fail!
73
- end
74
-
75
- it "raises error when holding failed jobs" do
76
- expect { Delayed::Job.bulk_update("hold", flavor: "failed", query: @query) }.to raise_error(RuntimeError)
77
- end
78
-
79
- it "raises error unholding failed jobs" do
80
- expect { Delayed::Job.bulk_update("unhold", flavor: "failed", query: @query) }.to raise_error(RuntimeError)
81
- end
82
- end
83
-
84
- context "deleting failed jobs" do
85
- before do
86
- 2.times do
87
- j = Delayed::Job.create(payload_object: SimpleJob.new)
88
- expect(j.send(:lock_exclusively!, "worker1")).to eq(true)
89
- j.fail!
90
- end
91
- end
92
-
93
- it "deletes failed jobs by id" do
94
- target_ids = Delayed::Job::Failed.all[0..2].map(&:id)
95
- expect(Delayed::Job.bulk_update("destroy", ids: target_ids, flavor: "failed",
96
- query: @query)).to eq(target_ids.length)
97
- end
98
-
99
- it "deletes all failed jobs" do
100
- failed_count = Delayed::Job::Failed.count
101
- expect(Delayed::Job.bulk_update("destroy", flavor: "failed", query: @query)).to eq(failed_count)
102
- end
103
- end
104
- end
105
-
106
- context "n_strand" do
107
- it "defaults to 1" do
108
- expect(Delayed::Job).not_to receive(:rand)
109
- job = Delayed::Job.enqueue(SimpleJob.new, n_strand: "njobs")
110
- expect(job.strand).to eq("njobs")
111
- end
112
-
113
- it "sets max_concurrent based on num_strands" do
114
- change_setting(Delayed::Settings, :num_strands, lambda { |strand_name|
115
- expect(strand_name).to eql "njobs"
116
- "3"
117
- }) do
118
- job = Delayed::Job.enqueue(SimpleJob.new, n_strand: "njobs")
119
- expect(job.strand).to eq("njobs")
120
- expect(job.max_concurrent).to eq(3)
121
- end
122
- end
123
-
124
- context "with two parameters" do
125
- it "uses the first param as the setting to read" do
126
- job = Delayed::Job.enqueue(SimpleJob.new, n_strand: %w[njobs 123])
127
- expect(job.strand).to eq("njobs/123")
128
- change_setting(Delayed::Settings, :num_strands, lambda { |strand_name|
129
- case strand_name
130
- when "njobs" then 3
131
- end
132
- }) do
133
- job = Delayed::Job.enqueue(SimpleJob.new, n_strand: %w[njobs 123])
134
- expect(job.strand).to eq("njobs/123")
135
- expect(job.max_concurrent).to eq(3)
136
- end
137
- end
138
-
139
- it "allows overridding the setting based on the second param" do
140
- change_setting(Delayed::Settings, :num_strands, lambda { |strand_name|
141
- case strand_name
142
- when "njobs/123" then 5
143
- end
144
- }) do
145
- job = Delayed::Job.enqueue(SimpleJob.new, n_strand: %w[njobs 123])
146
- expect(job.strand).to eq("njobs/123")
147
- expect(job.max_concurrent).to eq(5)
148
- job = Delayed::Job.enqueue(SimpleJob.new, n_strand: %w[njobs 456])
149
- expect(job.strand).to eq("njobs/456")
150
- expect(job.max_concurrent).to eq(1)
151
- end
152
-
153
- change_setting(Delayed::Settings, :num_strands, lambda { |strand_name|
154
- case strand_name
155
- when "njobs/123" then 5
156
- when "njobs" then 3
157
- end
158
- }) do
159
- job = Delayed::Job.enqueue(SimpleJob.new, n_strand: %w[njobs 123])
160
- expect(job.strand).to eq("njobs/123")
161
- expect(job.max_concurrent).to eq(5)
162
- job = Delayed::Job.enqueue(SimpleJob.new, n_strand: %w[njobs 456])
163
- expect(job.strand).to eq("njobs/456")
164
- expect(job.max_concurrent).to eq(3)
165
- end
166
- end
167
- end
168
-
169
- context "max_concurrent triggers" do
170
- it "sets one job as next_in_strand at a time with max_concurrent of 1" do
171
- job1 = Delayed::Job.enqueue(SimpleJob.new, n_strand: ["njobs"])
172
- job1.reload
173
- expect(job1.next_in_strand).to eq(true)
174
- job2 = Delayed::Job.enqueue(SimpleJob.new, n_strand: ["njobs"])
175
- job2.reload
176
- expect(job2.next_in_strand).to eq(false)
177
- run_job(job1)
178
- job2.reload
179
- expect(job2.next_in_strand).to eq(true)
180
- end
181
-
182
- it "sets multiple jobs as next_in_strand at a time based on max_concurrent" do
183
- change_setting(Delayed::Settings, :num_strands, lambda { |strand_name|
184
- case strand_name
185
- when "njobs" then 2
186
- end
187
- }) do
188
- job1 = Delayed::Job.enqueue(SimpleJob.new, n_strand: ["njobs"])
189
- job1.reload
190
- expect(job1.next_in_strand).to eq(true)
191
- job2 = Delayed::Job.enqueue(SimpleJob.new, n_strand: ["njobs"])
192
- job2.reload
193
- expect(job2.next_in_strand).to eq(true)
194
- job3 = Delayed::Job.enqueue(SimpleJob.new, n_strand: ["njobs"])
195
- job3.reload
196
- expect(job3.next_in_strand).to eq(false)
197
- run_job(job1)
198
- job3.reload
199
- expect(job3.next_in_strand).to eq(true)
200
- end
201
- end
202
- end
203
- end
204
-
205
- it "unlocks orphaned prefetched_jobs" do
206
- job1 = Delayed::Job.new(tag: "tag")
207
- job2 = Delayed::Job.new(tag: "tag")
208
-
209
- job1.create_and_lock!("prefetch:a")
210
- job1.locked_at = Delayed::Job.db_time_now - (15 * 60)
211
- job1.save!
212
- job2.create_and_lock!("prefetch:a")
213
-
214
- expect(Delayed::Job.unlock_orphaned_prefetched_jobs).to eq 1
215
- expect(Delayed::Job.unlock_orphaned_prefetched_jobs).to eq 0
216
-
217
- expect(Delayed::Job.find(job1.id).locked_by).to be_nil
218
- expect(Delayed::Job.find(job2.id).locked_by).to eq "prefetch:a"
219
- end
220
-
221
- it "gets process ids from locked_by" do
222
- Array.new(3) { Delayed::Job.create payload_object: SimpleJob.new }
223
- Delayed::Job.get_and_lock_next_available(["job42:2", "job42:9001"])
224
- expect(Delayed::Job.processes_locked_locally(name: "job42").sort).to eq [2, 9001]
225
- expect(Delayed::Job.processes_locked_locally(name: "jobnotme")).to be_empty
226
- end
227
-
228
- it "allows fetching multiple jobs at once" do
229
- jobs = Array.new(3) { Delayed::Job.create payload_object: SimpleJob.new }
230
- locked_jobs = Delayed::Job.get_and_lock_next_available(%w[worker1 worker2])
231
- expect(locked_jobs.length).to eq(2)
232
- expect(locked_jobs.keys).to eq(%w[worker1 worker2])
233
- expect(locked_jobs.values).to eq(jobs[0..1])
234
- expect(jobs.map(&:reload).map(&:locked_by)).to eq(["worker1", "worker2", nil])
235
- end
236
-
237
- it "allows fetching extra jobs" do
238
- jobs = Array.new(5) { Delayed::Job.create payload_object: SimpleJob.new }
239
- locked_jobs = Delayed::Job.get_and_lock_next_available(["worker1"],
240
- prefetch: 2,
241
- prefetch_owner: "work_queue")
242
- expect(locked_jobs.length).to eq 2
243
- expect(locked_jobs.keys).to eq %w[worker1 work_queue]
244
- expect(locked_jobs["worker1"]).to eq jobs[0]
245
- expect(locked_jobs["work_queue"]).to eq jobs[1..2]
246
- expect(jobs.map(&:reload).map(&:locked_by)).to eq(["worker1", "work_queue", "work_queue", nil, nil])
247
- end
248
-
249
- it "does not find jobs scheduled for now when we have forced latency" do
250
- job = create_job
251
- expect(Delayed::Job.get_and_lock_next_available("worker", forced_latency: 60.0)).to be_nil
252
- expect(Delayed::Job.get_and_lock_next_available("worker")).to eq job
253
- end
254
-
255
- context "non-transactional", non_transactional: true do
256
- it "creates a stranded job in a single statement" do
257
- allow(Delayed::Job.connection).to receive(:prepared_statements).and_return(false)
258
- allow(Delayed::Job.connection).to receive(:execute).with(be_include("pg_advisory_xact_lock"),
259
- anything).and_call_original.once
260
- expect(Delayed::Job.connection).not_to receive(:insert)
261
- j = create_job(strand: "test1")
262
- allow(Delayed::Job.connection).to receive(:execute).and_call_original
263
- expect(Delayed::Job.find(j.id)).to eq j
264
- end
265
-
266
- it "creates a non-stranded job in a single statement" do
267
- allow(Delayed::Job.connection).to receive(:prepared_statements).and_return(false)
268
- call_count = 0
269
- allow(Delayed::Job.connection).to receive(:execute).and_wrap_original do |m, (arg1, arg2)|
270
- call_count += 1
271
- m.call(arg1, arg2)
272
- end
273
- expect(Delayed::Job.connection).not_to receive(:insert)
274
- j = create_job(strand: "test1")
275
- expect(call_count).to eq 1
276
- expect(Delayed::Job.find(j.id)).to eq j
277
- end
278
-
279
- it "does not lock a stranded failed job creation" do
280
- j = create_job(strand: "test1")
281
- # query for metadata to ensure it's loaded before we start mucking with the connection
282
- Delayed::Backend::ActiveRecord::Job::Failed.new
283
-
284
- allow(Delayed::Job.connection).to receive(:prepared_statements).and_return(false)
285
- allow(Delayed::Job.connection).to receive(:execute).and_wrap_original do |original, *args|
286
- expect(args.first).not_to include("pg_advisory_xact_lock")
287
- original.call(*args)
288
- end
289
- expect(Delayed::Job.connection).not_to receive(:insert)
290
- j.fail!
291
- allow(Delayed::Job.connection).to receive(:execute).and_call_original
292
- end
293
- end
294
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe Delayed::CLI do
6
- describe "#parse_cli_options!" do
7
- it "correctly parses the --config option" do
8
- cli = described_class.new(%w[run --config /path/to/some/file.yml])
9
- options = cli.parse_cli_options!
10
- expect(options).to include config_file: "/path/to/some/file.yml"
11
- end
12
- end
13
-
14
- describe "#run" do
15
- before do
16
- expect(Delayed::Settings).to receive(:worker_config).and_return({})
17
- end
18
-
19
- it "prints help when no command is given" do
20
- cli = described_class.new([])
21
- expect(cli).to receive(:puts).with(/Usage/)
22
- cli.run
23
- end
24
- end
25
- end
@@ -1,38 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- RSpec.describe Delayed::Daemon do
6
- subject { described_class.new(pid_folder) }
7
-
8
- let(:pid_folder) { "/test/pid/folder" }
9
- let(:pid) { 9999 }
10
-
11
- before do
12
- allow(subject).to receive(:pid).and_return(pid)
13
- end
14
-
15
- describe "#stop" do
16
- it "prints status if not running" do
17
- expect(subject).to receive(:status).with(print: false, pid: pid).and_return(false)
18
- expect(subject).to receive(:status).with(no_args)
19
- expect(Process).not_to receive(:kill)
20
- subject.stop
21
- end
22
-
23
- it "prints status if draining" do
24
- expect(subject).to receive(:status).with(print: false, pid: pid).and_return(:draining)
25
- expect(subject).to receive(:status).with(no_args)
26
- expect(Process).not_to receive(:kill)
27
- subject.stop
28
- end
29
-
30
- it "sends QUIT by default" do
31
- expect(subject).to receive(:status).with(print: false, pid: pid).and_return(:running)
32
- expect(subject).to receive(:puts).with(/Stopping pool/)
33
- expect(Process).to receive(:kill).with("QUIT", pid)
34
- expect(subject).to receive(:wait).with(false)
35
- subject.stop
36
- end
37
- end
38
- end