delayed_job 4.0.2 → 4.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/CHANGELOG.md +7 -0
- data/README.md +12 -7
- data/Rakefile +6 -1
- data/delayed_job.gemspec +5 -5
- data/lib/delayed/backend/base.rb +18 -20
- data/lib/delayed/backend/shared_spec.rb +139 -138
- data/lib/delayed/command.rb +75 -40
- data/lib/delayed/exceptions.rb +2 -1
- data/lib/delayed/lifecycle.rb +12 -11
- data/lib/delayed/message_sending.rb +9 -10
- data/lib/delayed/performable_mailer.rb +2 -2
- data/lib/delayed/performable_method.rb +2 -2
- data/lib/delayed/psych_ext.rb +29 -93
- data/lib/delayed/recipes.rb +5 -5
- data/lib/delayed/serialization/active_record.rb +11 -9
- data/lib/delayed/syck_ext.rb +3 -3
- data/lib/delayed/tasks.rb +5 -5
- data/lib/delayed/worker.rb +42 -42
- data/lib/generators/delayed_job/delayed_job_generator.rb +2 -3
- data/spec/delayed/backend/test.rb +22 -17
- data/spec/delayed/command_spec.rb +57 -0
- data/spec/helper.rb +25 -12
- data/spec/lifecycle_spec.rb +23 -15
- data/spec/message_sending_spec.rb +34 -34
- data/spec/performable_mailer_spec.rb +11 -11
- data/spec/performable_method_spec.rb +24 -26
- data/spec/psych_ext_spec.rb +12 -0
- data/spec/sample_jobs.rb +46 -18
- data/spec/test_backend_spec.rb +3 -3
- data/spec/worker_spec.rb +27 -27
- data/spec/yaml_ext_spec.rb +16 -16
- metadata +12 -8
data/lib/delayed/recipes.rb
CHANGED
@@ -25,7 +25,7 @@ Capistrano::Configuration.instance.load do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def args
|
28
|
-
fetch(:delayed_job_args,
|
28
|
+
fetch(:delayed_job_args, '')
|
29
29
|
end
|
30
30
|
|
31
31
|
def roles
|
@@ -33,20 +33,20 @@ Capistrano::Configuration.instance.load do
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def delayed_job_command
|
36
|
-
fetch(:delayed_job_command,
|
36
|
+
fetch(:delayed_job_command, 'script/delayed_job')
|
37
37
|
end
|
38
38
|
|
39
|
-
desc
|
39
|
+
desc 'Stop the delayed_job process'
|
40
40
|
task :stop, :roles => lambda { roles } do
|
41
41
|
run "cd #{current_path};#{rails_env} #{delayed_job_command} stop"
|
42
42
|
end
|
43
43
|
|
44
|
-
desc
|
44
|
+
desc 'Start the delayed_job process'
|
45
45
|
task :start, :roles => lambda { roles } do
|
46
46
|
run "cd #{current_path};#{rails_env} #{delayed_job_command} start #{args}"
|
47
47
|
end
|
48
48
|
|
49
|
-
desc
|
49
|
+
desc 'Restart the delayed_job process'
|
50
50
|
task :restart, :roles => lambda { roles } do
|
51
51
|
run "cd #{current_path};#{rails_env} #{delayed_job_command} restart #{args}"
|
52
52
|
end
|
@@ -1,15 +1,17 @@
|
|
1
1
|
if defined?(ActiveRecord)
|
2
|
-
|
3
|
-
|
2
|
+
module ActiveRecord
|
3
|
+
class Base
|
4
|
+
yaml_as 'tag:ruby.yaml.org,2002:ActiveRecord'
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
def self.yaml_new(klass, _tag, val)
|
7
|
+
klass.unscoped.find(val['attributes'][klass.primary_key])
|
8
|
+
rescue ActiveRecord::RecordNotFound
|
9
|
+
raise Delayed::DeserializationError, "ActiveRecord::RecordNotFound, class: #{klass} , primary key: #{val['attributes'][klass.primary_key]}"
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
-
|
12
|
+
def to_yaml_properties
|
13
|
+
['@attributes']
|
14
|
+
end
|
13
15
|
end
|
14
16
|
end
|
15
17
|
end
|
data/lib/delayed/syck_ext.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
class Module
|
2
|
-
yaml_as
|
2
|
+
yaml_as 'tag:ruby.yaml.org,2002:module'
|
3
3
|
|
4
|
-
def self.yaml_new(
|
4
|
+
def self.yaml_new(_klass, _tag, val)
|
5
5
|
val.constantize
|
6
6
|
end
|
7
7
|
|
@@ -20,7 +20,7 @@ class Module
|
|
20
20
|
end
|
21
21
|
|
22
22
|
class Class
|
23
|
-
yaml_as
|
23
|
+
yaml_as 'tag:ruby.yaml.org,2002:class'
|
24
24
|
remove_method :to_yaml if respond_to?(:to_yaml) && method(:to_yaml).owner == Class # use Module's to_yaml
|
25
25
|
end
|
26
26
|
|
data/lib/delayed/tasks.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
namespace :jobs do
|
2
|
-
desc
|
2
|
+
desc 'Clear the delayed_job queue.'
|
3
3
|
task :clear => :environment do
|
4
4
|
Delayed::Job.delete_all
|
5
5
|
end
|
6
6
|
|
7
|
-
desc
|
7
|
+
desc 'Start a delayed_job worker.'
|
8
8
|
task :work => :environment_options do
|
9
9
|
Delayed::Worker.new(@worker_options).start
|
10
10
|
end
|
11
11
|
|
12
|
-
desc
|
12
|
+
desc 'Start a delayed_job worker and exit when all available jobs are complete.'
|
13
13
|
task :workoff => :environment_options do
|
14
|
-
Delayed::Worker.new(@worker_options.merge(
|
14
|
+
Delayed::Worker.new(@worker_options.merge(:exit_on_complete => true)).start
|
15
15
|
end
|
16
16
|
|
17
17
|
task :environment_options => :environment do
|
@@ -30,7 +30,7 @@ namespace :jobs do
|
|
30
30
|
unprocessed_jobs = Delayed::Job.where('attempts = 0 AND created_at < ?', Time.now - args[:max_age].to_i).count
|
31
31
|
|
32
32
|
if unprocessed_jobs > 0
|
33
|
-
|
33
|
+
raise "#{unprocessed_jobs} jobs older than #{args[:max_age]} seconds have not been processed yet"
|
34
34
|
end
|
35
35
|
|
36
36
|
end
|
data/lib/delayed/worker.rb
CHANGED
@@ -7,8 +7,7 @@ require 'logger'
|
|
7
7
|
require 'benchmark'
|
8
8
|
|
9
9
|
module Delayed
|
10
|
-
|
11
|
-
class Worker
|
10
|
+
class Worker # rubocop:disable ClassLength
|
12
11
|
DEFAULT_LOG_LEVEL = 'info'
|
13
12
|
DEFAULT_SLEEP_DELAY = 5
|
14
13
|
DEFAULT_MAX_ATTEMPTS = 25
|
@@ -19,8 +18,8 @@ module Delayed
|
|
19
18
|
DEFAULT_READ_AHEAD = 5
|
20
19
|
|
21
20
|
cattr_accessor :min_priority, :max_priority, :max_attempts, :max_run_time,
|
22
|
-
|
23
|
-
|
21
|
+
:default_priority, :sleep_delay, :logger, :delay_jobs, :queues,
|
22
|
+
:read_ahead, :plugins, :destroy_failed_jobs, :exit_on_complete
|
24
23
|
|
25
24
|
# Named queue into which jobs are enqueued by default
|
26
25
|
cattr_accessor :default_queue_name
|
@@ -70,12 +69,12 @@ module Delayed
|
|
70
69
|
require "delayed/backend/#{backend}"
|
71
70
|
backend = "Delayed::Backend::#{backend.to_s.classify}::Job".constantize
|
72
71
|
end
|
73
|
-
@@backend = backend
|
72
|
+
@@backend = backend # rubocop:disable ClassVars
|
74
73
|
silence_warnings { ::Delayed.const_set(:Job, backend) }
|
75
74
|
end
|
76
75
|
|
77
76
|
def self.guess_backend
|
78
|
-
warn
|
77
|
+
warn '[DEPRECATION] guess_backend is deprecated. Please remove it from your code.'
|
79
78
|
end
|
80
79
|
|
81
80
|
def self.before_fork
|
@@ -93,12 +92,11 @@ module Delayed
|
|
93
92
|
# Re-open file handles
|
94
93
|
@files_to_reopen.each do |file|
|
95
94
|
begin
|
96
|
-
file.reopen file.path,
|
95
|
+
file.reopen file.path, 'a+'
|
97
96
|
file.sync = true
|
98
|
-
rescue ::Exception
|
97
|
+
rescue ::Exception # rubocop:disable HandleExceptions, RescueException
|
99
98
|
end
|
100
99
|
end
|
101
|
-
|
102
100
|
backend.after_fork
|
103
101
|
end
|
104
102
|
|
@@ -106,15 +104,15 @@ module Delayed
|
|
106
104
|
@lifecycle ||= Delayed::Lifecycle.new
|
107
105
|
end
|
108
106
|
|
109
|
-
def initialize(options={})
|
110
|
-
@quiet = options.
|
107
|
+
def initialize(options = {})
|
108
|
+
@quiet = options.key?(:quiet) ? options[:quiet] : true
|
111
109
|
@failed_reserve_count = 0
|
112
110
|
|
113
111
|
[:min_priority, :max_priority, :sleep_delay, :read_ahead, :queues, :exit_on_complete].each do |option|
|
114
|
-
self.class.send("#{option}=", options[option]) if options.
|
112
|
+
self.class.send("#{option}=", options[option]) if options.key?(option)
|
115
113
|
end
|
116
114
|
|
117
|
-
|
115
|
+
plugins.each { |klass| klass.new }
|
118
116
|
end
|
119
117
|
|
120
118
|
# Every worker has a unique name which by default is the pid of the process. There are some
|
@@ -123,29 +121,27 @@ module Delayed
|
|
123
121
|
# it crashed before.
|
124
122
|
def name
|
125
123
|
return @name unless @name.nil?
|
126
|
-
"#{@name_prefix}host:#{Socket.gethostname} pid:#{Process.pid}" rescue "#{@name_prefix}pid:#{Process.pid}"
|
124
|
+
"#{@name_prefix}host:#{Socket.gethostname} pid:#{Process.pid}" rescue "#{@name_prefix}pid:#{Process.pid}" # rubocop:disable RescueModifier
|
127
125
|
end
|
128
126
|
|
129
127
|
# Sets the name of the worker.
|
130
128
|
# Setting the name to nil will reset the default worker name
|
131
|
-
|
132
|
-
@name = val
|
133
|
-
end
|
129
|
+
attr_writer :name
|
134
130
|
|
135
|
-
def start
|
131
|
+
def start # rubocop:disable CyclomaticComplexity, PerceivedComplexity
|
136
132
|
trap('TERM') do
|
137
133
|
say 'Exiting...'
|
138
134
|
stop
|
139
|
-
raise SignalException
|
135
|
+
raise SignalException, 'TERM' if self.class.raise_signal_exceptions
|
140
136
|
end
|
141
137
|
|
142
138
|
trap('INT') do
|
143
139
|
say 'Exiting...'
|
144
140
|
stop
|
145
|
-
raise SignalException
|
141
|
+
raise SignalException, 'INT' if self.class.raise_signal_exceptions && self.class.raise_signal_exceptions != :term
|
146
142
|
end
|
147
143
|
|
148
|
-
say
|
144
|
+
say 'Starting job worker'
|
149
145
|
|
150
146
|
self.class.lifecycle.run_callbacks(:execute, self) do
|
151
147
|
loop do
|
@@ -159,13 +155,13 @@ module Delayed
|
|
159
155
|
|
160
156
|
if count.zero?
|
161
157
|
if self.class.exit_on_complete
|
162
|
-
say
|
158
|
+
say 'No more jobs available. Exiting'
|
163
159
|
break
|
164
|
-
|
165
|
-
sleep(self.class.sleep_delay)
|
160
|
+
elsif !stop?
|
161
|
+
sleep(self.class.sleep_delay)
|
166
162
|
end
|
167
163
|
else
|
168
|
-
say "#{count} jobs processed at %.4f j/s, %d failed"
|
164
|
+
say format("#{count} jobs processed at %.4f j/s, %d failed", count / @realtime, @result.last)
|
169
165
|
end
|
170
166
|
|
171
167
|
break if stop?
|
@@ -189,16 +185,16 @@ module Delayed
|
|
189
185
|
num.times do
|
190
186
|
case reserve_and_run_one_job
|
191
187
|
when true
|
192
|
-
|
188
|
+
success += 1
|
193
189
|
when false
|
194
|
-
|
190
|
+
failure += 1
|
195
191
|
else
|
196
192
|
break # leave if no work could be done
|
197
193
|
end
|
198
194
|
break if stop? # leave if we're exiting
|
199
195
|
end
|
200
196
|
|
201
|
-
|
197
|
+
[success, failure]
|
202
198
|
end
|
203
199
|
|
204
200
|
def run(job)
|
@@ -207,13 +203,13 @@ module Delayed
|
|
207
203
|
Timeout.timeout(self.class.max_run_time.to_i, WorkerTimeout) { job.invoke_job }
|
208
204
|
job.destroy
|
209
205
|
end
|
210
|
-
job_say job, 'COMPLETED after %.4f'
|
206
|
+
job_say job, format('COMPLETED after %.4f', runtime)
|
211
207
|
return true # did work
|
212
208
|
rescue DeserializationError => error
|
213
209
|
job.last_error = "#{error.message}\n#{error.backtrace.join("\n")}"
|
214
210
|
failed(job)
|
215
|
-
rescue
|
216
|
-
self.class.lifecycle.run_callbacks(:error, self, job){ handle_failed_job(job, error) }
|
211
|
+
rescue => error
|
212
|
+
self.class.lifecycle.run_callbacks(:error, self, job) { handle_failed_job(job, error) }
|
217
213
|
return false # work failed
|
218
214
|
end
|
219
215
|
|
@@ -233,8 +229,14 @@ module Delayed
|
|
233
229
|
|
234
230
|
def failed(job)
|
235
231
|
self.class.lifecycle.run_callbacks(:failure, self, job) do
|
236
|
-
|
237
|
-
|
232
|
+
begin
|
233
|
+
job.hook(:failure)
|
234
|
+
rescue => error
|
235
|
+
say "Error when running failure callback: #{error}", 'error'
|
236
|
+
say error.backtrace.join("\n"), 'error'
|
237
|
+
ensure
|
238
|
+
self.class.destroy_failed_jobs ? job.destroy : job.fail!
|
239
|
+
end
|
238
240
|
end
|
239
241
|
end
|
240
242
|
|
@@ -246,13 +248,12 @@ module Delayed
|
|
246
248
|
def say(text, level = DEFAULT_LOG_LEVEL)
|
247
249
|
text = "[Worker(#{name})] #{text}"
|
248
250
|
puts text unless @quiet
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
end
|
254
|
-
logger.send(level, "#{Time.now.strftime('%FT%T%z')}: #{text}")
|
251
|
+
return unless logger
|
252
|
+
# TODO: Deprecate use of Fixnum log levels
|
253
|
+
unless level.is_a?(String)
|
254
|
+
level = Logger::Severity.constants.detect { |i| Logger::Severity.const_get(i) == level }.to_s.downcase
|
255
255
|
end
|
256
|
+
logger.send(level, "#{Time.now.strftime('%FT%T%z')}: #{text}")
|
256
257
|
end
|
257
258
|
|
258
259
|
def max_attempts(job)
|
@@ -271,14 +272,14 @@ module Delayed
|
|
271
272
|
# If no jobs are left we return nil
|
272
273
|
def reserve_and_run_one_job
|
273
274
|
job = reserve_job
|
274
|
-
self.class.lifecycle.run_callbacks(:perform, self, job){ run(job) } if job
|
275
|
+
self.class.lifecycle.run_callbacks(:perform, self, job) { run(job) } if job
|
275
276
|
end
|
276
277
|
|
277
278
|
def reserve_job
|
278
279
|
job = Delayed::Job.reserve(self)
|
279
280
|
@failed_reserve_count = 0
|
280
281
|
job
|
281
|
-
rescue Exception => error
|
282
|
+
rescue ::Exception => error # rubocop:disable RescueException
|
282
283
|
say "Error while reserving job: #{error}"
|
283
284
|
Delayed::Job.recover_from(error)
|
284
285
|
@failed_reserve_count += 1
|
@@ -286,5 +287,4 @@ module Delayed
|
|
286
287
|
nil
|
287
288
|
end
|
288
289
|
end
|
289
|
-
|
290
290
|
end
|
@@ -2,11 +2,10 @@ require 'rails/generators'
|
|
2
2
|
require 'delayed/compatibility'
|
3
3
|
|
4
4
|
class DelayedJobGenerator < Rails::Generators::Base
|
5
|
-
|
6
|
-
self.source_paths << File.join(File.dirname(__FILE__), 'templates')
|
5
|
+
source_paths << File.join(File.dirname(__FILE__), 'templates')
|
7
6
|
|
8
7
|
def create_executable_file
|
9
|
-
template
|
8
|
+
template 'script', "#{Delayed::Compatibility.executable_prefix}/delayed_job"
|
10
9
|
chmod "#{Delayed::Compatibility.executable_prefix}/delayed_job", 0755
|
11
10
|
end
|
12
11
|
end
|
@@ -25,12 +25,11 @@ module Delayed
|
|
25
25
|
self.attempts = 0
|
26
26
|
self.priority = 0
|
27
27
|
self.id = (self.class.id += 1)
|
28
|
-
hash.each{|k,v| send(:"#{k}=", v)}
|
28
|
+
hash.each { |k, v| send(:"#{k}=", v) }
|
29
29
|
end
|
30
30
|
|
31
|
-
@jobs = []
|
32
31
|
def self.all
|
33
|
-
@jobs
|
32
|
+
@jobs ||= []
|
34
33
|
end
|
35
34
|
|
36
35
|
def self.count
|
@@ -47,29 +46,33 @@ module Delayed
|
|
47
46
|
end
|
48
47
|
end
|
49
48
|
|
50
|
-
def self.create!(*args)
|
49
|
+
def self.create!(*args)
|
50
|
+
create(*args)
|
51
|
+
end
|
51
52
|
|
52
53
|
def self.clear_locks!(worker_name)
|
53
|
-
all.select{|j| j.locked_by == worker_name}.each
|
54
|
+
all.select { |j| j.locked_by == worker_name }.each do |j|
|
55
|
+
j.locked_by = nil
|
56
|
+
j.locked_at = nil
|
57
|
+
end
|
54
58
|
end
|
55
59
|
|
56
60
|
# Find a few candidate jobs to run (in case some immediately get locked by others).
|
57
|
-
def self.find_available(worker_name, limit = 5, max_run_time = Worker.max_run_time)
|
61
|
+
def self.find_available(worker_name, limit = 5, max_run_time = Worker.max_run_time) # rubocop:disable CyclomaticComplexity, PerceivedComplexity
|
58
62
|
jobs = all.select do |j|
|
59
63
|
j.run_at <= db_time_now &&
|
60
|
-
|
61
|
-
|
64
|
+
(j.locked_at.nil? || j.locked_at < db_time_now - max_run_time || j.locked_by == worker_name) &&
|
65
|
+
!j.failed?
|
62
66
|
end
|
63
|
-
|
64
|
-
jobs
|
65
|
-
jobs
|
66
|
-
jobs
|
67
|
-
jobs.sort_by{|j| [j.priority, j.run_at]}[0..limit-1]
|
67
|
+
jobs.select! { |j| j.priority <= Worker.max_priority } if Worker.max_priority
|
68
|
+
jobs.select! { |j| j.priority >= Worker.min_priority } if Worker.min_priority
|
69
|
+
jobs.select! { |j| Worker.queues.include?(j.queue) } if Worker.queues.any?
|
70
|
+
jobs.sort_by! { |j| [j.priority, j.run_at] }[0..limit - 1]
|
68
71
|
end
|
69
72
|
|
70
73
|
# Lock this job for this worker.
|
71
74
|
# Returns true if we have the lock, false otherwise.
|
72
|
-
def lock_exclusively!(
|
75
|
+
def lock_exclusively!(_max_run_time, worker)
|
73
76
|
now = self.class.db_time_now
|
74
77
|
if locked_by != worker
|
75
78
|
# We don't own this job so we will update the locked_by name and the locked_at
|
@@ -77,7 +80,7 @@ module Delayed
|
|
77
80
|
self.locked_by = worker
|
78
81
|
end
|
79
82
|
|
80
|
-
|
83
|
+
true
|
81
84
|
end
|
82
85
|
|
83
86
|
def self.db_time_now
|
@@ -85,7 +88,7 @@ module Delayed
|
|
85
88
|
end
|
86
89
|
|
87
90
|
def update_attributes(attrs = {})
|
88
|
-
attrs.each{|k,v| send(:"#{k}=", v)}
|
91
|
+
attrs.each { |k, v| send(:"#{k}=", v) }
|
89
92
|
save
|
90
93
|
end
|
91
94
|
|
@@ -100,7 +103,9 @@ module Delayed
|
|
100
103
|
true
|
101
104
|
end
|
102
105
|
|
103
|
-
def save
|
106
|
+
def save!
|
107
|
+
save
|
108
|
+
end
|
104
109
|
|
105
110
|
def reload
|
106
111
|
reset
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'delayed/command'
|
3
|
+
|
4
|
+
describe Delayed::Command do
|
5
|
+
describe 'parsing --pool argument' do
|
6
|
+
it 'should parse --pool correctly' do
|
7
|
+
command = Delayed::Command.new(['--pool=*:1', '--pool=test_queue:4', '--pool=mailers,misc:2'])
|
8
|
+
|
9
|
+
expect(command.worker_pools).to eq [
|
10
|
+
[[], 1],
|
11
|
+
[['test_queue'], 4],
|
12
|
+
[%w[mailers misc], 2]
|
13
|
+
]
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should allow * or blank to specify any pools' do
|
17
|
+
command = Delayed::Command.new(['--pool=*:4'])
|
18
|
+
expect(command.worker_pools).to eq [
|
19
|
+
[[], 4],
|
20
|
+
]
|
21
|
+
|
22
|
+
command = Delayed::Command.new(['--pool=:4'])
|
23
|
+
expect(command.worker_pools).to eq [
|
24
|
+
[[], 4],
|
25
|
+
]
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should default to one worker if not specified' do
|
29
|
+
command = Delayed::Command.new(['--pool=mailers'])
|
30
|
+
expect(command.worker_pools).to eq [
|
31
|
+
[['mailers'], 1],
|
32
|
+
]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe 'running worker pools defined by multiple --pool arguments' do
|
37
|
+
it 'should run the correct worker processes' do
|
38
|
+
command = Delayed::Command.new(['--pool=*:1', '--pool=test_queue:4', '--pool=mailers,misc:2'])
|
39
|
+
|
40
|
+
expect(Dir).to receive(:mkdir).with('./tmp/pids').once
|
41
|
+
|
42
|
+
[
|
43
|
+
['delayed_job.0', {:quiet => true, :pid_dir => './tmp/pids', :queues => []}],
|
44
|
+
['delayed_job.1', {:quiet => true, :pid_dir => './tmp/pids', :queues => ['test_queue']}],
|
45
|
+
['delayed_job.2', {:quiet => true, :pid_dir => './tmp/pids', :queues => ['test_queue']}],
|
46
|
+
['delayed_job.3', {:quiet => true, :pid_dir => './tmp/pids', :queues => ['test_queue']}],
|
47
|
+
['delayed_job.4', {:quiet => true, :pid_dir => './tmp/pids', :queues => ['test_queue']}],
|
48
|
+
['delayed_job.5', {:quiet => true, :pid_dir => './tmp/pids', :queues => %w[mailers misc]}],
|
49
|
+
['delayed_job.6', {:quiet => true, :pid_dir => './tmp/pids', :queues => %w[mailers misc]}]
|
50
|
+
].each do |args|
|
51
|
+
expect(command).to receive(:run_process).with(*args).once
|
52
|
+
end
|
53
|
+
|
54
|
+
command.daemonize
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|