rocketjob 1.3.0 → 2.0.0.rc1
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/LICENSE.txt +201 -0
- data/README.md +15 -10
- data/bin/rocketjob +3 -1
- data/bin/rocketjob_perf +92 -0
- data/lib/rocket_job/cli.rb +71 -31
- data/lib/rocket_job/config.rb +21 -23
- data/lib/rocket_job/dirmon_entry.rb +63 -45
- data/lib/rocket_job/extensions/aasm.rb +56 -0
- data/lib/rocket_job/extensions/mongo.rb +23 -0
- data/lib/rocket_job/job.rb +9 -433
- data/lib/rocket_job/jobs/dirmon_job.rb +20 -20
- data/lib/rocket_job/jobs/simple_job.rb +12 -0
- data/lib/rocket_job/plugins/document.rb +69 -0
- data/lib/rocket_job/plugins/job/callbacks.rb +92 -0
- data/lib/rocket_job/plugins/job/defaults.rb +40 -0
- data/lib/rocket_job/plugins/job/logger.rb +36 -0
- data/lib/rocket_job/plugins/job/model.rb +288 -0
- data/lib/rocket_job/plugins/job/persistence.rb +167 -0
- data/lib/rocket_job/plugins/job/state_machine.rb +166 -0
- data/lib/rocket_job/plugins/job/worker.rb +167 -0
- data/lib/rocket_job/plugins/restart.rb +54 -0
- data/lib/rocket_job/plugins/singleton.rb +26 -0
- data/lib/rocket_job/plugins/state_machine.rb +105 -0
- data/lib/rocket_job/version.rb +1 -1
- data/lib/rocket_job/worker.rb +150 -119
- data/lib/rocketjob.rb +43 -21
- data/test/config_test.rb +12 -0
- data/test/dirmon_entry_test.rb +81 -85
- data/test/dirmon_job_test.rb +40 -28
- data/test/job_test.rb +14 -257
- data/test/plugins/job/callbacks_test.rb +163 -0
- data/test/plugins/job/defaults_test.rb +52 -0
- data/test/plugins/job/logger_test.rb +58 -0
- data/test/plugins/job/model_test.rb +97 -0
- data/test/plugins/job/persistence_test.rb +81 -0
- data/test/plugins/job/state_machine_test.rb +118 -0
- data/test/plugins/job/worker_test.rb +183 -0
- data/test/plugins/restart_test.rb +185 -0
- data/test/plugins/singleton_test.rb +94 -0
- data/test/plugins/state_machine_event_callbacks_test.rb +101 -0
- data/test/plugins/state_machine_test.rb +64 -0
- data/test/test_helper.rb +3 -36
- metadata +64 -19
- data/lib/rocket_job/concerns/singleton.rb +0 -33
- data/lib/rocket_job/concerns/worker.rb +0 -214
- data/test/files/_archive/archived.txt +0 -3
- data/test/job_worker_test.rb +0 -86
- data/test/jobs/test_job.rb +0 -46
- data/test/worker_test.rb +0 -97
@@ -0,0 +1,81 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
module Plugins
|
4
|
+
module Job
|
5
|
+
# Unit Test for RocketJob::Job
|
6
|
+
class PersistenceTest < Minitest::Test
|
7
|
+
|
8
|
+
class PersistJob < RocketJob::Job
|
9
|
+
rocket_job do |job|
|
10
|
+
job.priority = 53
|
11
|
+
end
|
12
|
+
|
13
|
+
def perform(hash)
|
14
|
+
hash
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe RocketJob::Plugins::Job::Persistence do
|
19
|
+
before do
|
20
|
+
@description = 'Hello World'
|
21
|
+
@arguments = [{key: 'value'}]
|
22
|
+
@job = PersistJob.new(
|
23
|
+
description: @description,
|
24
|
+
arguments: [{key: 'value'}],
|
25
|
+
destroy_on_complete: false
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
after do
|
30
|
+
@job.destroy if @job && !@job.new_record?
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '.config' do
|
34
|
+
it 'support multiple databases' do
|
35
|
+
assert_equal 'test_rocketjob', RocketJob::Job.collection.db.name
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '.rocket_job' do
|
40
|
+
it 'sets defaults after initialize' do
|
41
|
+
assert_equal 53, @job.priority
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '#reload' do
|
46
|
+
it 'handle hash' do
|
47
|
+
assert_equal 'value', @job.arguments.first[:key]
|
48
|
+
@job.worker_name = nil
|
49
|
+
@job.save!
|
50
|
+
@job.worker_name = '123'
|
51
|
+
@job.reload
|
52
|
+
assert @job.arguments.first.is_a?(ActiveSupport::HashWithIndifferentAccess), @job.arguments.first.class.ai
|
53
|
+
assert_equal 'value', @job.arguments.first['key']
|
54
|
+
assert_equal 'value', @job.arguments.first[:key]
|
55
|
+
assert_equal nil, @job.worker_name
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#save!' do
|
60
|
+
it 'save a blank job' do
|
61
|
+
@job.save!
|
62
|
+
assert_nil @job.worker_name
|
63
|
+
assert_nil @job.completed_at
|
64
|
+
assert @job.created_at
|
65
|
+
assert_equal @description, @job.description
|
66
|
+
assert_equal false, @job.destroy_on_complete
|
67
|
+
assert_nil @job.expires_at
|
68
|
+
assert_equal @arguments, @job.arguments
|
69
|
+
assert_equal 0, @job.percent_complete
|
70
|
+
assert_equal 53, @job.priority
|
71
|
+
assert_equal 0, @job.failure_count
|
72
|
+
assert_nil @job.run_at
|
73
|
+
assert_nil @job.started_at
|
74
|
+
assert_equal :queued, @job.state
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
module Plugins
|
3
|
+
module Job
|
4
|
+
# Unit Test for RocketJob::Job
|
5
|
+
class StateMachineTest < Minitest::Test
|
6
|
+
|
7
|
+
class StateMachineJob < RocketJob::Job
|
8
|
+
def perform
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe RocketJob::Plugins::Job::StateMachine do
|
13
|
+
before do
|
14
|
+
@job = StateMachineJob.new
|
15
|
+
end
|
16
|
+
|
17
|
+
after do
|
18
|
+
@job.destroy if @job && !@job.new_record?
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#requeue!' do
|
22
|
+
it 'requeue jobs from dead workers' do
|
23
|
+
worker_name = 'server:12345'
|
24
|
+
@job.worker_name = worker_name
|
25
|
+
@job.start!
|
26
|
+
assert @job.running?
|
27
|
+
|
28
|
+
@job.requeue!(worker_name)
|
29
|
+
@job.reload
|
30
|
+
|
31
|
+
assert @job.queued?
|
32
|
+
assert_equal nil, @job.worker_name
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#requeue' do
|
37
|
+
it 'requeue jobs from dead workers' do
|
38
|
+
worker_name = 'server:12345'
|
39
|
+
@job.worker_name = worker_name
|
40
|
+
assert @job.valid?, @job.errors.messages
|
41
|
+
@job.start!
|
42
|
+
assert @job.running?, @job.state
|
43
|
+
|
44
|
+
@job.requeue(worker_name)
|
45
|
+
assert @job.queued?
|
46
|
+
assert_equal nil, @job.worker_name
|
47
|
+
|
48
|
+
@job.reload
|
49
|
+
assert @job.running?
|
50
|
+
assert_equal worker_name, @job.worker_name
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#after_complete' do
|
55
|
+
it 'destroy on complete' do
|
56
|
+
@job.destroy_on_complete = true
|
57
|
+
@job.perform_now
|
58
|
+
assert @job.completed?, @job.state
|
59
|
+
assert_equal 0, RocketJob::Job.where(id: @job.id).count
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '#fail!' do
|
64
|
+
it 'fail with message' do
|
65
|
+
@job.start!
|
66
|
+
@job.fail!('myworker:2323', 'oh no')
|
67
|
+
assert @job.failed?
|
68
|
+
assert exc = @job.exception
|
69
|
+
assert_equal 'RocketJob::JobException', exc.class_name
|
70
|
+
assert_equal 'oh no', exc.message
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'fail with no arguments' do
|
74
|
+
@job.start!
|
75
|
+
@job.fail!
|
76
|
+
assert @job.failed?
|
77
|
+
assert exc = @job.exception
|
78
|
+
assert_equal 'RocketJob::JobException', exc.class_name
|
79
|
+
assert_equal nil, exc.message
|
80
|
+
assert_equal nil, exc.worker_name
|
81
|
+
assert_equal [], exc.backtrace
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'fail with exception' do
|
85
|
+
@job.start!
|
86
|
+
exception = RuntimeError.new('Oh no')
|
87
|
+
@job.fail!('myworker:2323', exception)
|
88
|
+
assert @job.failed?
|
89
|
+
assert exc = @job.exception
|
90
|
+
assert_equal exception.class.name, exc.class_name
|
91
|
+
assert_equal exception.message, exc.message
|
92
|
+
assert_equal [], exc.backtrace
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '#retry!' do
|
97
|
+
it 'retry failed jobs' do
|
98
|
+
worker_name = 'server:12345'
|
99
|
+
@job.worker_name = worker_name
|
100
|
+
@job.start!
|
101
|
+
assert @job.running?
|
102
|
+
assert_equal worker_name, @job.worker_name
|
103
|
+
|
104
|
+
@job.fail!(worker_name, 'oh no')
|
105
|
+
assert @job.failed?
|
106
|
+
assert_equal 'oh no', @job.exception.message
|
107
|
+
|
108
|
+
@job.retry!
|
109
|
+
assert @job.queued?
|
110
|
+
assert_equal nil, @job.worker_name
|
111
|
+
assert_equal nil, @job.exception
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
module Plugins
|
4
|
+
module Job
|
5
|
+
# Unit Test for RocketJob::Job
|
6
|
+
class WorkerTest < Minitest::Test
|
7
|
+
class QuietJob < RocketJob::Job
|
8
|
+
# Test increasing log level for debugging purposes
|
9
|
+
def perform
|
10
|
+
logger.trace 'enable tracing level for just the job instance'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class NoisyJob < RocketJob::Job
|
15
|
+
# Test silencing noisy logging
|
16
|
+
def perform
|
17
|
+
logger.info 'some very noisy logging'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class SumJob < RocketJob::Job
|
22
|
+
rocket_job do |job|
|
23
|
+
job.destroy_on_complete = false
|
24
|
+
job.collect_output = true
|
25
|
+
job.priority = 51
|
26
|
+
end
|
27
|
+
|
28
|
+
def perform(first, second)
|
29
|
+
first + second
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe RocketJob::Plugins::Job::Worker do
|
34
|
+
before do
|
35
|
+
RocketJob::Job.destroy_all
|
36
|
+
end
|
37
|
+
|
38
|
+
after do
|
39
|
+
@job.destroy if @job && !@job.new_record?
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '.rocket_job_next_job' do
|
43
|
+
before do
|
44
|
+
@job = QuietJob.new
|
45
|
+
@worker = RocketJob::Worker.new(name: 'worker:123')
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'return nil when no jobs available' do
|
49
|
+
assert_equal nil, RocketJob::Job.rocket_job_next_job(@worker.name)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'return the first job' do
|
53
|
+
@job.save!
|
54
|
+
assert job = RocketJob::Job.rocket_job_next_job(@worker.name), 'Failed to find job'
|
55
|
+
assert_equal @job.id, job.id
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'Ignore future dated jobs' do
|
59
|
+
@job.run_at = Time.now + 1.hour
|
60
|
+
@job.save!
|
61
|
+
assert_equal nil, RocketJob::Job.rocket_job_next_job(@worker.name)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'Process future dated jobs when time is now' do
|
65
|
+
@job.run_at = Time.now
|
66
|
+
@job.save!
|
67
|
+
assert job = RocketJob::Job.rocket_job_next_job(@worker.name), 'Failed to find future job'
|
68
|
+
assert_equal @job.id, job.id
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'Skip expired jobs' do
|
72
|
+
count = RocketJob::Job.count
|
73
|
+
@job.expires_at = Time.now - 100
|
74
|
+
@job.save!
|
75
|
+
assert_equal nil, RocketJob::Job.rocket_job_next_job(@worker.name)
|
76
|
+
assert_equal count, RocketJob::Job.count
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe '#perform_now' do
|
81
|
+
it 'calls perform method' do
|
82
|
+
@job = SumJob.new(arguments: [10, 5])
|
83
|
+
assert_equal 15, @job.perform_now['result']
|
84
|
+
assert @job.completed?, @job.attributes.ai
|
85
|
+
assert_equal 15, @job.result['result']
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'saves exception' do
|
89
|
+
@job = SumJob.new(arguments: ['10', 5])
|
90
|
+
assert_raises TypeError do
|
91
|
+
@job.perform_now
|
92
|
+
end
|
93
|
+
assert @job.exception.backtrace
|
94
|
+
assert_equal 'TypeError', @job.exception.class_name
|
95
|
+
if RUBY_VERSION.to_f < 2.0
|
96
|
+
assert_equal "can't convert Fixnum into String", @job.exception.message
|
97
|
+
else
|
98
|
+
assert_equal 'no implicit conversion of Fixnum into String', @job.exception.message
|
99
|
+
end
|
100
|
+
assert_equal 'inline', @job.exception.worker_name
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'silence logging when log_level is set' do
|
104
|
+
@job = NoisyJob.new
|
105
|
+
@job.log_level = :warn
|
106
|
+
logged = false
|
107
|
+
@job.logger.stub(:log_internal, -> level, index, message, payload, exception { logged = true if message.include?('some very noisy logging') }) do
|
108
|
+
@job.perform_now
|
109
|
+
end
|
110
|
+
assert_equal false, logged
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'raise logging when log_level is set' do
|
114
|
+
@job = QuietJob.new
|
115
|
+
@job.log_level = :trace
|
116
|
+
logged = false
|
117
|
+
# Raise global log level to :info
|
118
|
+
SemanticLogger.stub(:default_level_index, 3) do
|
119
|
+
@job.logger.stub(:log_internal, -> { logged = true }) do
|
120
|
+
@job.perform_now
|
121
|
+
end
|
122
|
+
end
|
123
|
+
assert_equal false, logged
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe '.perform_later' do
|
128
|
+
it 'queues the job for processing' do
|
129
|
+
RocketJob::Config.stub(:inline_mode, false) do
|
130
|
+
@job = SumJob.perform_later(1, 23)
|
131
|
+
end
|
132
|
+
assert @job.queued?
|
133
|
+
|
134
|
+
# Manually run the job
|
135
|
+
@job.perform_now
|
136
|
+
assert @job.completed?, @job.attributes.ai
|
137
|
+
assert_equal 24, @job.result['result']
|
138
|
+
|
139
|
+
assert_nil @job.worker_name
|
140
|
+
assert @job.completed_at
|
141
|
+
assert @job.created_at
|
142
|
+
assert_equal false, @job.destroy_on_complete
|
143
|
+
assert_nil @job.expires_at
|
144
|
+
assert_equal 100, @job.percent_complete
|
145
|
+
assert_equal 51, @job.priority
|
146
|
+
assert_equal 0, @job.failure_count
|
147
|
+
assert_nil @job.run_at
|
148
|
+
assert @job.started_at
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'runs the job immediately when inline_mode = true' do
|
152
|
+
RocketJob::Config.stub(:inline_mode, true) do
|
153
|
+
@job = SumJob.perform_later(1, 23)
|
154
|
+
end
|
155
|
+
|
156
|
+
assert @job.completed?, @job.attributes.ai
|
157
|
+
assert_equal 24, @job.result['result']
|
158
|
+
|
159
|
+
assert_nil @job.worker_name
|
160
|
+
assert @job.completed_at
|
161
|
+
assert @job.created_at
|
162
|
+
assert_equal false, @job.destroy_on_complete
|
163
|
+
assert_nil @job.expires_at
|
164
|
+
assert_equal 100, @job.percent_complete
|
165
|
+
assert_equal 51, @job.priority
|
166
|
+
assert_equal 0, @job.failure_count
|
167
|
+
assert_nil @job.run_at
|
168
|
+
assert @job.started_at
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
describe '.perform_now' do
|
173
|
+
it 'run the job immediately' do
|
174
|
+
@job = SumJob.perform_now(1, 5)
|
175
|
+
assert_equal true, @job.completed?
|
176
|
+
assert_equal 6, @job.result['result']
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
# Unit Test for RocketJob::Job
|
4
|
+
module Plugins
|
5
|
+
class RestartTest < Minitest::Test
|
6
|
+
class RestartableJob < RocketJob::Job
|
7
|
+
include RocketJob::Plugins::Restart
|
8
|
+
|
9
|
+
def perform
|
10
|
+
'DONE'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe RocketJob::Plugins::Restart do
|
15
|
+
before do
|
16
|
+
# destroy_all could create new instances
|
17
|
+
RestartableJob.delete_all
|
18
|
+
assert_equal 0, RestartableJob.count
|
19
|
+
end
|
20
|
+
|
21
|
+
after do
|
22
|
+
@job.delete if @job && !@job.new_record?
|
23
|
+
RestartableJob.delete_all
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#create!' do
|
27
|
+
it 'queues a new job' do
|
28
|
+
@job = RestartableJob.create!
|
29
|
+
assert @job.valid?
|
30
|
+
refute @job.new_record?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#save!' do
|
35
|
+
it 'queues a new job' do
|
36
|
+
@job = RestartableJob.new
|
37
|
+
@job.save!
|
38
|
+
assert @job.valid?
|
39
|
+
refute @job.new_record?
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#abort!' do
|
44
|
+
it 'queues a new job on abort' do
|
45
|
+
@job = RestartableJob.create!
|
46
|
+
@job.abort!
|
47
|
+
assert_equal 2, RestartableJob.count
|
48
|
+
assert other = RestartableJob.where(id: {'$ne' => @job.id}).first
|
49
|
+
refute_equal @job.id, other.id
|
50
|
+
assert other.queued?
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'does not queue a new job when expired' do
|
54
|
+
@job = RestartableJob.create!(expires_at: Time.now - 1.day)
|
55
|
+
assert @job.expired?
|
56
|
+
@job.abort!
|
57
|
+
assert_equal 1, RestartableJob.count
|
58
|
+
assert_equal nil, RestartableJob.where(id: {'$ne' => @job.id}).first
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#complete' do
|
63
|
+
it 'queues a new job when destroy_on_complete' do
|
64
|
+
assert_equal 0, RestartableJob.count
|
65
|
+
@job = RestartableJob.create!(destroy_on_complete: true)
|
66
|
+
@job.perform_now
|
67
|
+
assert @job.completed?, @job.attributes.ai
|
68
|
+
assert_equal 1, RestartableJob.count, RestartableJob.all.to_a.ai
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'queues a new job when not destroy_on_complete' do
|
72
|
+
@job = RestartableJob.create!(destroy_on_complete: false)
|
73
|
+
@job.perform_now
|
74
|
+
assert @job.completed?
|
75
|
+
assert_equal 2, RestartableJob.count
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'does not queue a new job when expired' do
|
79
|
+
@job = RestartableJob.create!(expires_at: Time.now - 1.day)
|
80
|
+
@job.perform_now
|
81
|
+
assert @job.expired?
|
82
|
+
assert @job.completed?
|
83
|
+
assert_equal 0, RestartableJob.count
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '#pause' do
|
88
|
+
it 'does not enqueues a new job when paused' do
|
89
|
+
@job = RestartableJob.new
|
90
|
+
@job.start
|
91
|
+
@job.pause!
|
92
|
+
assert @job.paused?
|
93
|
+
assert_equal 1, RestartableJob.count
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe '#fail' do
|
98
|
+
it 'aborts from queued' do
|
99
|
+
@job = RestartableJob.new
|
100
|
+
assert @job.queued?
|
101
|
+
@job.fail
|
102
|
+
assert @job.aborted?
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'aborts from running' do
|
106
|
+
@job = RestartableJob.new
|
107
|
+
@job.start
|
108
|
+
assert @job.running?
|
109
|
+
@job.fail
|
110
|
+
assert @job.aborted?
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'aborts from paused' do
|
114
|
+
@job = RestartableJob.new
|
115
|
+
@job.start
|
116
|
+
@job.pause
|
117
|
+
assert @job.paused?
|
118
|
+
@job.fail
|
119
|
+
assert @job.aborted?
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'does not queue a new job when expired' do
|
123
|
+
@job = RestartableJob.new(expires_at: Time.now - 1.day)
|
124
|
+
@job.start!
|
125
|
+
assert @job.running?
|
126
|
+
assert @job.expired?
|
127
|
+
assert_equal 1, RestartableJob.count
|
128
|
+
assert_equal nil, RestartableJob.where(id: {'$ne' => @job.id}).first
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe '#create_new_instance' do
|
133
|
+
it 'sets job back to queued state' do
|
134
|
+
@job = RestartableJob.create!(destroy_on_complete: true)
|
135
|
+
@job.perform_now
|
136
|
+
assert_equal 1, RestartableJob.count
|
137
|
+
assert job2 = RestartableJob.where(id: {'$ne' => @job.id}).first
|
138
|
+
assert job2.queued?, job2.attributes.ai
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'excludes attributes related to running jobs' do
|
142
|
+
@job = RestartableJob.create!(destroy_on_complete: true, expires_at: Time.now + 1.day)
|
143
|
+
refute @job.expired?
|
144
|
+
@job.perform_now
|
145
|
+
assert_equal 1, RestartableJob.count
|
146
|
+
assert job2 = RestartableJob.where(id: {'$ne' => @job.id}).first
|
147
|
+
assert job2.queued?, job2.attributes.ai
|
148
|
+
|
149
|
+
# Copy across all attributes, except
|
150
|
+
@job.attributes.each_pair do |key, value|
|
151
|
+
next if RocketJob::Plugins::Restart::RESTART_EXCLUDES.include?(key)
|
152
|
+
assert_equal value, job2[key], "Attributes are supposed to be copied across. For #{key}"
|
153
|
+
end
|
154
|
+
|
155
|
+
assert_equal :queued, job2.state
|
156
|
+
assert job2.created_at
|
157
|
+
assert_equal nil, job2.started_at
|
158
|
+
assert_equal nil, job2.completed_at
|
159
|
+
assert_equal 0, job2.failure_count
|
160
|
+
assert_equal nil, job2.worker_name
|
161
|
+
assert_equal 0, job2.percent_complete
|
162
|
+
assert_equal nil, job2.exception
|
163
|
+
assert_equal({}, job2.result)
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'copies run_at when it is in the future' do
|
167
|
+
@job = RestartableJob.create!(run_at: Time.now + 1.day, destroy_on_complete: true)
|
168
|
+
@job.perform_now
|
169
|
+
assert_equal 1, RestartableJob.count
|
170
|
+
assert job2 = RestartableJob.where(id: {'$ne' => @job.id}).first
|
171
|
+
assert job2.run_at, job2.attributes.ai
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'does not copy run_at when it is in the past' do
|
175
|
+
@job = RestartableJob.create!(run_at: Time.now - 1.day, destroy_on_complete: true)
|
176
|
+
@job.perform_now
|
177
|
+
assert_equal 1, RestartableJob.count
|
178
|
+
assert job2 = RestartableJob.where(id: {'$ne' => @job.id}).first
|
179
|
+
assert_equal nil, job2.run_at
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
module Plugins
|
4
|
+
# Unit Test for RocketJob::Job
|
5
|
+
class SingletonTest < Minitest::Test
|
6
|
+
|
7
|
+
class SingletonJob < RocketJob::Job
|
8
|
+
include RocketJob::Plugins::Singleton
|
9
|
+
|
10
|
+
def perform
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe RocketJob::Plugins::Singleton do
|
15
|
+
before do
|
16
|
+
SingletonJob.delete_all
|
17
|
+
end
|
18
|
+
|
19
|
+
after do
|
20
|
+
@job.destroy if @job && !@job.new_record?
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#rocket_job_singleton_active?' do
|
24
|
+
it 'returns false if no jobs of this class are active' do
|
25
|
+
@job = SingletonJob.new
|
26
|
+
assert_equal false, @job.rocket_job_singleton_active?
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'excludes self when queued from check' do
|
30
|
+
@job = SingletonJob.create
|
31
|
+
assert @job.queued?
|
32
|
+
assert_equal false, @job.rocket_job_singleton_active?
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'excludes self when started from check' do
|
36
|
+
@job = SingletonJob.new
|
37
|
+
@job.start!
|
38
|
+
assert @job.running?
|
39
|
+
assert_equal false, @job.rocket_job_singleton_active?
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'returns true when other jobs of this class are queued' do
|
43
|
+
@job = SingletonJob.create!
|
44
|
+
job2 = SingletonJob.new
|
45
|
+
assert_equal true, job2.rocket_job_singleton_active?
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'returns true when other jobs of this class are running' do
|
49
|
+
@job = SingletonJob.new
|
50
|
+
@job.start!
|
51
|
+
job2 = SingletonJob.new
|
52
|
+
assert_equal true, job2.rocket_job_singleton_active?
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'returns false when other jobs of this class are not active' do
|
56
|
+
@job = SingletonJob.new
|
57
|
+
@job.perform_now
|
58
|
+
@job.save!
|
59
|
+
assert @job.completed?
|
60
|
+
job2 = SingletonJob.new
|
61
|
+
assert_equal false, job2.rocket_job_singleton_active?
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe 'validation' do
|
66
|
+
it 'passes if another job is not active' do
|
67
|
+
@job = SingletonJob.new
|
68
|
+
@job.perform_now
|
69
|
+
@job.save!
|
70
|
+
job2 = SingletonJob.new
|
71
|
+
assert_equal true, job2.valid?
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'fails if another job is active' do
|
75
|
+
@job = SingletonJob.new
|
76
|
+
@job.start!
|
77
|
+
job2 = SingletonJob.new
|
78
|
+
refute job2.valid?
|
79
|
+
assert_equal ['Another instance of Plugins::SingletonTest::SingletonJob is already queued or running'], job2.errors.messages[:state]
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'passes if another job is active, but this job is not' do
|
83
|
+
@job = SingletonJob.new
|
84
|
+
@job.start!
|
85
|
+
job2 = SingletonJob.new
|
86
|
+
job2.abort
|
87
|
+
assert job2.valid?
|
88
|
+
job2.save!
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|