inst-jobs 2.3.3 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (95) hide show
  1. checksums.yaml +4 -4
  2. data/db/migrate/20101216224513_create_delayed_jobs.rb +9 -7
  3. data/db/migrate/20110531144916_cleanup_delayed_jobs_indexes.rb +8 -13
  4. data/db/migrate/20110610213249_optimize_delayed_jobs.rb +8 -8
  5. data/db/migrate/20110831210257_add_delayed_jobs_next_in_strand.rb +25 -25
  6. data/db/migrate/20120510004759_delayed_jobs_delete_trigger_lock_for_update.rb +4 -8
  7. data/db/migrate/20120531150712_drop_psql_jobs_pop_fn.rb +1 -3
  8. data/db/migrate/20120607164022_delayed_jobs_use_advisory_locks.rb +11 -15
  9. data/db/migrate/20120607181141_index_jobs_on_locked_by.rb +1 -1
  10. data/db/migrate/20120608191051_add_jobs_run_at_index.rb +2 -2
  11. data/db/migrate/20120927184213_change_delayed_jobs_handler_to_text.rb +1 -1
  12. data/db/migrate/20140505215510_copy_failed_jobs_original_id.rb +2 -3
  13. data/db/migrate/20150807133223_add_max_concurrent_to_jobs.rb +9 -13
  14. data/db/migrate/20151210162949_improve_max_concurrent.rb +4 -8
  15. data/db/migrate/20161206323555_add_back_default_string_limits_jobs.rb +3 -2
  16. data/db/migrate/20181217155351_speed_up_max_concurrent_triggers.rb +13 -17
  17. data/db/migrate/20200330230722_add_id_to_get_delayed_jobs_index.rb +8 -8
  18. data/db/migrate/20200824222232_speed_up_max_concurrent_delete_trigger.rb +72 -77
  19. data/db/migrate/20200825011002_add_strand_order_override.rb +93 -97
  20. data/db/migrate/20210809145804_add_n_strand_index.rb +3 -3
  21. data/db/migrate/20210812210128_add_singleton_column.rb +203 -0
  22. data/exe/inst_jobs +3 -2
  23. data/lib/delayed/backend/active_record.rb +182 -148
  24. data/lib/delayed/backend/base.rb +79 -74
  25. data/lib/delayed/batch.rb +11 -9
  26. data/lib/delayed/cli.rb +98 -84
  27. data/lib/delayed/core_ext/kernel.rb +4 -2
  28. data/lib/delayed/daemon.rb +70 -74
  29. data/lib/delayed/job_tracking.rb +26 -25
  30. data/lib/delayed/lifecycle.rb +27 -24
  31. data/lib/delayed/log_tailer.rb +17 -17
  32. data/lib/delayed/logging.rb +13 -16
  33. data/lib/delayed/message_sending.rb +42 -51
  34. data/lib/delayed/performable_method.rb +5 -7
  35. data/lib/delayed/periodic.rb +66 -65
  36. data/lib/delayed/plugin.rb +2 -4
  37. data/lib/delayed/pool.rb +198 -193
  38. data/lib/delayed/server/helpers.rb +6 -6
  39. data/lib/delayed/server.rb +51 -54
  40. data/lib/delayed/settings.rb +93 -81
  41. data/lib/delayed/testing.rb +21 -22
  42. data/lib/delayed/version.rb +1 -1
  43. data/lib/delayed/work_queue/in_process.rb +21 -18
  44. data/lib/delayed/work_queue/parent_process/client.rb +54 -55
  45. data/lib/delayed/work_queue/parent_process/server.rb +215 -209
  46. data/lib/delayed/work_queue/parent_process.rb +52 -53
  47. data/lib/delayed/worker/consul_health_check.rb +21 -19
  48. data/lib/delayed/worker/health_check.rb +21 -12
  49. data/lib/delayed/worker/null_health_check.rb +3 -1
  50. data/lib/delayed/worker/process_helper.rb +8 -9
  51. data/lib/delayed/worker.rb +271 -265
  52. data/lib/delayed/yaml_extensions.rb +12 -10
  53. data/lib/delayed_job.rb +37 -38
  54. data/lib/inst-jobs.rb +1 -1
  55. data/spec/active_record_job_spec.rb +128 -135
  56. data/spec/delayed/cli_spec.rb +7 -7
  57. data/spec/delayed/daemon_spec.rb +8 -8
  58. data/spec/delayed/message_sending_spec.rb +8 -9
  59. data/spec/delayed/periodic_spec.rb +13 -12
  60. data/spec/delayed/server_spec.rb +38 -38
  61. data/spec/delayed/settings_spec.rb +26 -25
  62. data/spec/delayed/work_queue/in_process_spec.rb +7 -7
  63. data/spec/delayed/work_queue/parent_process/client_spec.rb +15 -11
  64. data/spec/delayed/work_queue/parent_process/server_spec.rb +43 -40
  65. data/spec/delayed/work_queue/parent_process_spec.rb +21 -21
  66. data/spec/delayed/worker/consul_health_check_spec.rb +22 -22
  67. data/spec/delayed/worker/health_check_spec.rb +51 -49
  68. data/spec/delayed/worker_spec.rb +28 -25
  69. data/spec/gemfiles/52.gemfile +5 -3
  70. data/spec/gemfiles/52.gemfile.lock +240 -0
  71. data/spec/gemfiles/60.gemfile +5 -3
  72. data/spec/gemfiles/60.gemfile.lock +1 -1
  73. data/spec/gemfiles/61.gemfile +5 -3
  74. data/spec/sample_jobs.rb +45 -15
  75. data/spec/shared/delayed_batch.rb +74 -67
  76. data/spec/shared/delayed_method.rb +143 -102
  77. data/spec/shared/performable_method.rb +39 -38
  78. data/spec/shared/shared_backend.rb +517 -441
  79. data/spec/shared/testing.rb +14 -14
  80. data/spec/shared/worker.rb +155 -147
  81. data/spec/shared_jobs_specs.rb +13 -13
  82. data/spec/spec_helper.rb +43 -40
  83. metadata +74 -56
  84. data/lib/delayed/backend/redis/bulk_update.lua +0 -50
  85. data/lib/delayed/backend/redis/destroy_job.lua +0 -2
  86. data/lib/delayed/backend/redis/enqueue.lua +0 -29
  87. data/lib/delayed/backend/redis/fail_job.lua +0 -5
  88. data/lib/delayed/backend/redis/find_available.lua +0 -3
  89. data/lib/delayed/backend/redis/functions.rb +0 -59
  90. data/lib/delayed/backend/redis/get_and_lock_next_available.lua +0 -17
  91. data/lib/delayed/backend/redis/includes/jobs_common.lua +0 -203
  92. data/lib/delayed/backend/redis/job.rb +0 -528
  93. data/lib/delayed/backend/redis/set_running.lua +0 -5
  94. data/lib/delayed/backend/redis/tickle_strand.lua +0 -2
  95. data/spec/redis_job_spec.rb +0 -148
@@ -2,36 +2,37 @@
2
2
 
3
3
  # New definitions for YAML to aid in serialization and deserialization of delayed jobs.
4
4
 
5
- require 'yaml'
5
+ require "yaml"
6
6
 
7
7
  # These two added domain types are for backwards compatibility with jobs created
8
8
  # using the old syck tags, as syck didn't have built-in module/class dumping. We
9
9
  # now use Psych's built-in tags, which are `!ruby/module` and `!ruby/class`. At
10
10
  # some point we can remove these, once there are no more jobs in any queues with
11
11
  # these tags.
12
- Psych.add_domain_type("ruby/object", "Module") do |type, val|
12
+ Psych.add_domain_type("ruby/object", "Module") do |_type, val|
13
13
  val.constantize
14
14
  end
15
- Psych.add_domain_type("ruby/object", "Class") do |type, val|
15
+ Psych.add_domain_type("ruby/object", "Class") do |_type, val|
16
16
  val.constantize
17
17
  end
18
18
 
19
19
  # Tell YAML how to intelligently load ActiveRecord objects, using the
20
20
  # database rather than just serializing their attributes to the YAML. This
21
21
  # ensures the object is up to date when we use it in the job.
22
- class ActiveRecord::Base
23
- def encode_with(coder)
24
- if id.nil?
25
- raise("Can't serialize unsaved ActiveRecord object for delayed job: #{self.inspect}")
22
+ module ActiveRecord
23
+ class Base
24
+ def encode_with(coder)
25
+ raise("Can't serialize unsaved ActiveRecord object for delayed job: #{inspect}") if id.nil?
26
+
27
+ coder.scalar("!ruby/ActiveRecord:#{self.class.name}", id.to_s)
26
28
  end
27
- coder.scalar("!ruby/ActiveRecord:#{self.class.name}", id.to_s)
28
29
  end
29
30
  end
30
31
 
31
32
  module Delayed
32
33
  module PsychExt
33
34
  module ToRuby
34
- def visit_Psych_Nodes_Scalar(object)
35
+ def visit_Psych_Nodes_Scalar(object) # rubocop:disable Naming/MethodName
35
36
  case object.tag
36
37
  when %r{^!ruby/ActiveRecord:(.+)$}
37
38
  begin
@@ -50,7 +51,8 @@ module Delayed
50
51
  end
51
52
 
52
53
  def resolve_class(klass_name)
53
- return nil if !klass_name || klass_name.empty?
54
+ return nil if klass_name.blank?
55
+
54
56
  klass_name.constantize
55
57
  rescue
56
58
  super
data/lib/delayed_job.rb CHANGED
@@ -14,44 +14,43 @@ module Delayed
14
14
  end
15
15
  end
16
16
 
17
- require 'rails'
18
- require 'active_support/core_ext/module/attribute_accessors'
19
- require 'active_record'
20
- require 'after_transaction_commit'
21
- require 'debug_inspector'
22
-
23
- require 'delayed/core_ext/kernel'
24
-
25
- require 'delayed/settings'
26
- require 'delayed/yaml_extensions'
27
-
28
- require 'delayed/backend/base'
29
- require 'delayed/backend/active_record'
30
- require 'delayed/backend/redis/job'
31
- require 'delayed/batch'
32
- require 'delayed/cli'
33
- require 'delayed/daemon'
34
- require 'delayed/job_tracking'
35
- require 'delayed/lifecycle'
36
- require 'delayed/log_tailer'
37
- require 'delayed/logging'
38
- require 'delayed/message_sending'
39
- require 'delayed/performable_method'
40
- require 'delayed/periodic'
41
- require 'delayed/plugin'
42
- require 'delayed/pool'
43
- require 'delayed/worker'
44
-
45
- require 'delayed/worker/health_check'
46
- require 'delayed/worker/consul_health_check'
47
- require 'delayed/worker/null_health_check'
48
-
49
- require 'delayed/work_queue/in_process'
50
- require 'delayed/work_queue/parent_process'
51
-
52
- require 'delayed/engine'
17
+ require "rails"
18
+ require "active_support/core_ext/module/attribute_accessors"
19
+ require "active_record"
20
+ require "after_transaction_commit"
21
+ require "debug_inspector"
22
+
23
+ require "delayed/core_ext/kernel"
24
+
25
+ require "delayed/settings"
26
+ require "delayed/yaml_extensions"
27
+
28
+ require "delayed/backend/base"
29
+ require "delayed/backend/active_record"
30
+ require "delayed/batch"
31
+ require "delayed/cli"
32
+ require "delayed/daemon"
33
+ require "delayed/job_tracking"
34
+ require "delayed/lifecycle"
35
+ require "delayed/log_tailer"
36
+ require "delayed/logging"
37
+ require "delayed/message_sending"
38
+ require "delayed/performable_method"
39
+ require "delayed/periodic"
40
+ require "delayed/plugin"
41
+ require "delayed/pool"
42
+ require "delayed/worker"
43
+
44
+ require "delayed/worker/health_check"
45
+ require "delayed/worker/consul_health_check"
46
+ require "delayed/worker/null_health_check"
47
+
48
+ require "delayed/work_queue/in_process"
49
+ require "delayed/work_queue/parent_process"
50
+
51
+ require "delayed/engine"
53
52
 
54
53
  Delayed.select_backend(Delayed::Backend::ActiveRecord::Job)
55
54
 
56
- Object.send(:include, Delayed::MessageSending)
57
- Module.send(:include, Delayed::MessageSending::ClassMethods)
55
+ Object.include Delayed::MessageSending
56
+ Module.include Delayed::MessageSending::ClassMethods
data/lib/inst-jobs.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'delayed_job'
3
+ require "delayed_job"
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require File.expand_path("../spec_helper", __FILE__)
4
-
5
- describe 'Delayed::Backed::ActiveRecord::Job' do
3
+ describe "Delayed::Backed::ActiveRecord::Job" do
6
4
  before :all do
7
5
  Delayed.select_backend(Delayed::Backend::ActiveRecord::Job)
8
6
  end
@@ -11,207 +9,202 @@ describe 'Delayed::Backed::ActiveRecord::Job' do
11
9
  Delayed::Testing.clear_all!
12
10
  end
13
11
 
14
- include_examples 'a delayed_jobs implementation'
12
+ include_examples "a delayed_jobs implementation"
15
13
 
16
- it "should recover as well as possible from a failure failing a job" do
14
+ it "recovers as well as possible from a failure failing a job" do
17
15
  allow(Delayed::Job::Failed).to receive(:create).and_raise(RuntimeError)
18
16
  job = "test".delay(ignore_transaction: true).reverse
19
17
  job_id = job.id
20
- proc { job.fail! }.should raise_error(RuntimeError)
21
- proc { Delayed::Job.find(job_id) }.should raise_error(ActiveRecord::RecordNotFound)
22
- Delayed::Job.count.should == 0
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)
23
21
  end
24
22
 
25
23
  context "when another worker has worked on a task since the job was found to be available, it" do
26
- before :each do
27
- @job = Delayed::Job.create :payload_object => SimpleJob.new
28
- @job_copy_for_worker_2 = Delayed::Job.find(@job.id)
24
+ before do
25
+ @job = Delayed::Job.create payload_object: SimpleJob.new
26
+ @job_copy_for_worker2 = Delayed::Job.find(@job.id)
29
27
  end
30
28
 
31
- it "should not allow a second worker to get exclusive access if already successfully processed by worker1" do
29
+ it "does not allow a second worker to get exclusive access if already successfully processed by worker1" do
32
30
  @job.destroy
33
- @job_copy_for_worker_2.send(:lock_exclusively!, 'worker2').should == false
31
+ expect(@job_copy_for_worker2.send(:lock_exclusively!, "worker2")).to eq(false)
34
32
  end
35
33
 
36
- it "should not allow a second worker to get exclusive access if failed to be processed by worker1 and run_at time is now in future (due to backing off behaviour)" do
37
- @job.update(:attempts => 1, :run_at => 1.day.from_now)
38
- @job_copy_for_worker_2.send(:lock_exclusively!, 'worker2').should == false
34
+ it "doesn't allow a second worker to get exclusive access if failed to be processed by worker1 and
35
+ 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)
39
38
  end
40
39
 
41
- it "should select the next job at random if enabled" do
42
- begin
43
- Delayed::Settings.select_random_from_batch = true
44
- 15.times { "test".delay.length }
45
- founds = []
46
- 15.times do
47
- job = Delayed::Job.get_and_lock_next_available('tester')
48
- founds << job
49
- job.unlock
50
- job.save!
51
- end
52
- founds.uniq.size.should > 1
53
- ensure
54
- Delayed::Settings.select_random_from_batch = false
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!
55
49
  end
50
+ expect(founds.uniq.size).to be > 1
51
+ ensure
52
+ Delayed::Settings.select_random_from_batch = false
56
53
  end
57
54
  end
58
55
 
59
- it "should unlock a successfully locked job and persist the job's unlocked state" do
60
- job = Delayed::Job.create :payload_object => SimpleJob.new
61
- job.send(:lock_exclusively!, 'worker1').should == true
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)
62
59
  job.reload
63
60
  job.unlock
64
61
  job.save!
65
62
  job.reload
66
- job.locked_by.should == nil
67
- job.locked_at.should == nil
63
+ expect(job.locked_by).to eq(nil)
64
+ expect(job.locked_at).to eq(nil)
68
65
  end
69
66
 
70
67
  describe "bulk_update failed jobs" do
71
68
  context "holding/unholding failed jobs" do
72
- before :each do
73
- @job = Delayed::Job.create :payload_object => SimpleJob.new
74
- Delayed::Job.get_and_lock_next_available('worker1').should == @job
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)
75
72
  @job.fail!
76
73
  end
77
74
 
78
- it "should raise error when holding failed jobs" do
79
- expect { Delayed::Job.bulk_update('hold', :flavor => 'failed', :query => @query) }.to raise_error(RuntimeError)
75
+ it "raises error when holding failed jobs" do
76
+ expect { Delayed::Job.bulk_update("hold", flavor: "failed", query: @query) }.to raise_error(RuntimeError)
80
77
  end
81
78
 
82
- it "should raise error unholding failed jobs" do
83
- expect { Delayed::Job.bulk_update('unhold', :flavor => 'failed', :query => @query) }.to raise_error(RuntimeError)
79
+ it "raises error unholding failed jobs" do
80
+ expect { Delayed::Job.bulk_update("unhold", flavor: "failed", query: @query) }.to raise_error(RuntimeError)
84
81
  end
85
82
  end
86
83
 
87
84
  context "deleting failed jobs" do
88
- before :each do
89
- 2.times {
90
- j = Delayed::Job.create(:payload_object => SimpleJob.new)
91
- j.send(:lock_exclusively!, 'worker1').should == true
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)
92
89
  j.fail!
93
- }
90
+ end
94
91
  end
95
92
 
96
- it "should delete failed jobs by id" do
97
- target_ids = Delayed::Job::Failed.all[0..2].map { |j| j.id }
98
- Delayed::Job.bulk_update('destroy', :ids => target_ids, :flavor => 'failed', :query => @query).should == target_ids.length
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)
99
97
  end
100
98
 
101
- it "should delete all failed jobs" do
99
+ it "deletes all failed jobs" do
102
100
  failed_count = Delayed::Job::Failed.count
103
- Delayed::Job.bulk_update('destroy', :flavor => 'failed', :query => @query).should == failed_count
101
+ expect(Delayed::Job.bulk_update("destroy", flavor: "failed", query: @query)).to eq(failed_count)
104
102
  end
105
103
  end
106
104
  end
107
105
 
108
- context 'n_strand' do
109
- it "should default to 1" do
110
- expect(Delayed::Job).to receive(:rand).never
111
- job = Delayed::Job.enqueue(SimpleJob.new, :n_strand => 'njobs')
112
- job.strand.should == "njobs"
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")
113
111
  end
114
112
 
115
- it "should set max_concurrent based on num_strands" do
116
- change_setting(Delayed::Settings, :num_strands, ->(strand_name) { expect(strand_name).to eql "njobs"; "3" }) do
117
- job = Delayed::Job.enqueue(SimpleJob.new, :n_strand => 'njobs')
118
- job.strand.should == "njobs"
119
- job.max_concurrent.should == 3
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)
120
121
  end
121
122
  end
122
123
 
123
124
  context "with two parameters" do
124
- it "should use the first param as the setting to read" do
125
- job = Delayed::Job.enqueue(SimpleJob.new, n_strand: ["njobs", "123"])
126
- job.strand.should == "njobs/123"
127
- change_setting(Delayed::Settings, :num_strands, ->(strand_name) {
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|
128
129
  case strand_name
129
- when "njobs"; 3
130
- else nil
130
+ when "njobs" then 3
131
131
  end
132
132
  }) do
133
- job = Delayed::Job.enqueue(SimpleJob.new, n_strand: ["njobs", "123"])
134
- job.strand.should == "njobs/123"
135
- job.max_concurrent.should == 3
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
136
  end
137
137
  end
138
138
 
139
- it "should allow overridding the setting based on the second param" do
140
- change_setting(Delayed::Settings, :num_strands, ->(strand_name) {
139
+ it "allows overridding the setting based on the second param" do
140
+ change_setting(Delayed::Settings, :num_strands, lambda { |strand_name|
141
141
  case strand_name
142
- when "njobs/123"; 5
143
- else nil
142
+ when "njobs/123" then 5
144
143
  end
145
144
  }) do
146
- job = Delayed::Job.enqueue(SimpleJob.new, n_strand: ["njobs", "123"])
147
- job.strand.should == "njobs/123"
148
- job.max_concurrent.should == 5
149
- job = Delayed::Job.enqueue(SimpleJob.new, n_strand: ["njobs", "456"])
150
- job.strand.should == "njobs/456"
151
- job.max_concurrent.should == 1
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)
152
151
  end
153
152
 
154
- change_setting(Delayed::Settings, :num_strands, ->(strand_name) {
153
+ change_setting(Delayed::Settings, :num_strands, lambda { |strand_name|
155
154
  case strand_name
156
- when "njobs/123"; 5
157
- when "njobs"; 3
158
- else nil
155
+ when "njobs/123" then 5
156
+ when "njobs" then 3
159
157
  end
160
158
  }) do
161
- job = Delayed::Job.enqueue(SimpleJob.new, n_strand: ["njobs", "123"])
162
- job.strand.should == "njobs/123"
163
- job.max_concurrent.should == 5
164
- job = Delayed::Job.enqueue(SimpleJob.new, n_strand: ["njobs", "456"])
165
- job.strand.should == "njobs/456"
166
- job.max_concurrent.should == 3
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)
167
165
  end
168
166
  end
169
167
  end
170
168
 
171
169
  context "max_concurrent triggers" do
172
- before do
173
- skip("postgres specific") unless ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
174
- end
175
-
176
- it "should set one job as next_in_strand at a time with max_concurrent of 1" do
170
+ it "sets one job as next_in_strand at a time with max_concurrent of 1" do
177
171
  job1 = Delayed::Job.enqueue(SimpleJob.new, n_strand: ["njobs"])
178
172
  job1.reload
179
- job1.next_in_strand.should == true
173
+ expect(job1.next_in_strand).to eq(true)
180
174
  job2 = Delayed::Job.enqueue(SimpleJob.new, n_strand: ["njobs"])
181
175
  job2.reload
182
- job2.next_in_strand.should == false
176
+ expect(job2.next_in_strand).to eq(false)
183
177
  run_job(job1)
184
178
  job2.reload
185
- job2.next_in_strand.should == true
179
+ expect(job2.next_in_strand).to eq(true)
186
180
  end
187
181
 
188
- it "should set multiple jobs as next_in_strand at a time based on max_concurrent" do
189
- change_setting(Delayed::Settings, :num_strands, ->(strand_name) {
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|
190
184
  case strand_name
191
- when "njobs"; 2
192
- else nil
185
+ when "njobs" then 2
193
186
  end
194
187
  }) do
195
188
  job1 = Delayed::Job.enqueue(SimpleJob.new, n_strand: ["njobs"])
196
189
  job1.reload
197
- job1.next_in_strand.should == true
190
+ expect(job1.next_in_strand).to eq(true)
198
191
  job2 = Delayed::Job.enqueue(SimpleJob.new, n_strand: ["njobs"])
199
192
  job2.reload
200
- job2.next_in_strand.should == true
193
+ expect(job2.next_in_strand).to eq(true)
201
194
  job3 = Delayed::Job.enqueue(SimpleJob.new, n_strand: ["njobs"])
202
195
  job3.reload
203
- job3.next_in_strand.should == false
196
+ expect(job3.next_in_strand).to eq(false)
204
197
  run_job(job1)
205
198
  job3.reload
206
- job3.next_in_strand.should == true
199
+ expect(job3.next_in_strand).to eq(true)
207
200
  end
208
201
  end
209
202
  end
210
203
  end
211
204
 
212
205
  it "unlocks orphaned prefetched_jobs" do
213
- job1 = Delayed::Job.new(:tag => 'tag')
214
- job2 = Delayed::Job.new(:tag => 'tag')
206
+ job1 = Delayed::Job.new(tag: "tag")
207
+ job2 = Delayed::Job.new(tag: "tag")
215
208
 
216
209
  job1.create_and_lock!("prefetch:a")
217
210
  job1.locked_at = Delayed::Job.db_time_now - 15 * 60
@@ -222,49 +215,49 @@ describe 'Delayed::Backed::ActiveRecord::Job' do
222
215
  expect(Delayed::Job.unlock_orphaned_prefetched_jobs).to eq 0
223
216
 
224
217
  expect(Delayed::Job.find(job1.id).locked_by).to be_nil
225
- expect(Delayed::Job.find(job2.id).locked_by).to eq 'prefetch:a'
218
+ expect(Delayed::Job.find(job2.id).locked_by).to eq "prefetch:a"
226
219
  end
227
220
 
228
221
  it "gets process ids from locked_by" do
229
- 3.times.map { Delayed::Job.create :payload_object => SimpleJob.new }
230
- locked_jobs = Delayed::Job.get_and_lock_next_available(['job42:2', 'job42:9001'])
231
- expect(Delayed::Job.processes_locked_locally(name: 'job42').sort).to eq [2, 9001]
232
- expect(Delayed::Job.processes_locked_locally(name: 'jobnotme')).to be_empty
222
+ 3.times.map { 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
233
226
  end
234
227
 
235
228
  it "allows fetching multiple jobs at once" do
236
- jobs = 3.times.map { Delayed::Job.create :payload_object => SimpleJob.new }
237
- locked_jobs = Delayed::Job.get_and_lock_next_available(['worker1', 'worker2'])
238
- locked_jobs.length.should == 2
239
- locked_jobs.keys.should == ['worker1', 'worker2']
240
- locked_jobs.values.should == jobs[0..1]
241
- jobs.map(&:reload).map(&:locked_by).should == ['worker1', 'worker2', nil]
229
+ jobs = 3.times.map { 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])
242
235
  end
243
236
 
244
237
  it "allows fetching extra jobs" do
245
- jobs = 5.times.map { Delayed::Job.create :payload_object => SimpleJob.new }
246
- locked_jobs = Delayed::Job.get_and_lock_next_available(['worker1'],
238
+ jobs = 5.times.map { Delayed::Job.create payload_object: SimpleJob.new }
239
+ locked_jobs = Delayed::Job.get_and_lock_next_available(["worker1"],
247
240
  prefetch: 2,
248
- prefetch_owner: 'work_queue')
241
+ prefetch_owner: "work_queue")
249
242
  expect(locked_jobs.length).to eq 2
250
- expect(locked_jobs.keys).to eq ['worker1', 'work_queue']
251
- expect(locked_jobs['worker1']).to eq jobs[0]
252
- expect(locked_jobs['work_queue']).to eq jobs[1..2]
253
- jobs.map(&:reload).map(&:locked_by).should == ['worker1', 'work_queue', 'work_queue', nil, nil]
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])
254
247
  end
255
248
 
256
-
257
- it "should not find jobs scheduled for now when we have forced latency" do
249
+ it "does not find jobs scheduled for now when we have forced latency" do
258
250
  job = create_job
259
- Delayed::Job.get_and_lock_next_available('worker', forced_latency: 60.0).should be_nil
260
- Delayed::Job.get_and_lock_next_available('worker').should eq 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
261
253
  end
262
254
 
263
255
  context "non-transactional", non_transactional: true do
264
256
  it "creates a stranded job in a single statement" do
265
257
  allow(Delayed::Job.connection).to receive(:prepared_statements).and_return(false)
266
- allow(Delayed::Job.connection).to receive(:execute).with(be_include("pg_advisory_xact_lock"), anything).and_call_original.once
267
- allow(Delayed::Job.connection).to receive(:insert).never
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)
268
261
  j = create_job(strand: "test1")
269
262
  allow(Delayed::Job.connection).to receive(:execute).and_call_original
270
263
  expect(Delayed::Job.find(j.id)).to eq j
@@ -277,7 +270,7 @@ describe 'Delayed::Backed::ActiveRecord::Job' do
277
270
  call_count += 1
278
271
  m.call(arg1, arg2)
279
272
  end
280
- allow(Delayed::Job.connection).to receive(:insert).never
273
+ expect(Delayed::Job.connection).not_to receive(:insert)
281
274
  j = create_job(strand: "test1")
282
275
  expect(call_count).to eq 1
283
276
  expect(Delayed::Job.find(j.id)).to eq j
@@ -293,7 +286,7 @@ describe 'Delayed::Backed::ActiveRecord::Job' do
293
286
  expect(args.first).not_to include("pg_advisory_xact_lock")
294
287
  original.call(*args)
295
288
  end
296
- allow(Delayed::Job.connection).to receive(:insert).never
289
+ expect(Delayed::Job.connection).not_to receive(:insert)
297
290
  j.fail!
298
291
  allow(Delayed::Job.connection).to receive(:execute).and_call_original
299
292
  end