rocketjob 3.5.2 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +63 -1
  3. data/bin/rocketjob +1 -0
  4. data/bin/rocketjob_batch_perf +11 -0
  5. data/lib/rocket_job/batch.rb +32 -0
  6. data/lib/rocket_job/batch/callbacks.rb +40 -0
  7. data/lib/rocket_job/batch/io.rb +154 -0
  8. data/lib/rocket_job/batch/logger.rb +57 -0
  9. data/lib/rocket_job/batch/lower_priority.rb +54 -0
  10. data/lib/rocket_job/batch/model.rb +157 -0
  11. data/lib/rocket_job/batch/performance.rb +99 -0
  12. data/lib/rocket_job/batch/result.rb +8 -0
  13. data/lib/rocket_job/batch/results.rb +9 -0
  14. data/lib/rocket_job/batch/state_machine.rb +102 -0
  15. data/lib/rocket_job/batch/statistics.rb +88 -0
  16. data/lib/rocket_job/batch/tabular.rb +56 -0
  17. data/lib/rocket_job/batch/tabular/input.rb +123 -0
  18. data/lib/rocket_job/batch/tabular/output.rb +59 -0
  19. data/lib/rocket_job/batch/throttle.rb +91 -0
  20. data/lib/rocket_job/batch/throttle_running_slices.rb +53 -0
  21. data/lib/rocket_job/batch/worker.rb +288 -0
  22. data/lib/rocket_job/cli.rb +29 -7
  23. data/lib/rocket_job/config.rb +1 -1
  24. data/lib/rocket_job/extensions/mongoid/clients/options.rb +37 -0
  25. data/lib/rocket_job/extensions/mongoid/contextual/mongo.rb +17 -0
  26. data/lib/rocket_job/extensions/mongoid/factory.rb +4 -4
  27. data/lib/rocket_job/extensions/mongoid_5/clients/options.rb +38 -0
  28. data/lib/rocket_job/extensions/mongoid_5/contextual/mongo.rb +64 -0
  29. data/lib/rocket_job/extensions/mongoid_5/factory.rb +13 -0
  30. data/lib/rocket_job/jobs/on_demand_batch_job.rb +127 -0
  31. data/lib/rocket_job/jobs/performance_job.rb +18 -0
  32. data/lib/rocket_job/jobs/upload_file_job.rb +2 -5
  33. data/lib/rocket_job/plugins/document.rb +2 -8
  34. data/lib/rocket_job/plugins/job/persistence.rb +6 -4
  35. data/lib/rocket_job/plugins/job/throttle.rb +3 -6
  36. data/lib/rocket_job/plugins/job/worker.rb +2 -2
  37. data/lib/rocket_job/server.rb +14 -3
  38. data/lib/rocket_job/sliced/input.rb +336 -0
  39. data/lib/rocket_job/sliced/output.rb +99 -0
  40. data/lib/rocket_job/sliced/slice.rb +166 -0
  41. data/lib/rocket_job/sliced/slices.rb +166 -0
  42. data/lib/rocket_job/sliced/writer/input.rb +60 -0
  43. data/lib/rocket_job/sliced/writer/output.rb +82 -0
  44. data/lib/rocket_job/version.rb +1 -1
  45. data/lib/rocket_job/worker.rb +2 -2
  46. data/lib/rocketjob.rb +28 -0
  47. metadata +51 -62
  48. data/test/config/database.yml +0 -5
  49. data/test/config/mongoid.yml +0 -88
  50. data/test/config_test.rb +0 -10
  51. data/test/dirmon_entry_test.rb +0 -313
  52. data/test/dirmon_job_test.rb +0 -216
  53. data/test/files/text.txt +0 -3
  54. data/test/job_test.rb +0 -71
  55. data/test/jobs/housekeeping_job_test.rb +0 -102
  56. data/test/jobs/on_demand_job_test.rb +0 -59
  57. data/test/jobs/upload_file_job_test.rb +0 -107
  58. data/test/plugins/cron_test.rb +0 -166
  59. data/test/plugins/job/callbacks_test.rb +0 -166
  60. data/test/plugins/job/defaults_test.rb +0 -53
  61. data/test/plugins/job/logger_test.rb +0 -56
  62. data/test/plugins/job/model_test.rb +0 -94
  63. data/test/plugins/job/persistence_test.rb +0 -94
  64. data/test/plugins/job/state_machine_test.rb +0 -116
  65. data/test/plugins/job/throttle_test.rb +0 -111
  66. data/test/plugins/job/worker_test.rb +0 -199
  67. data/test/plugins/processing_window_test.rb +0 -109
  68. data/test/plugins/restart_test.rb +0 -193
  69. data/test/plugins/retry_test.rb +0 -88
  70. data/test/plugins/singleton_test.rb +0 -92
  71. data/test/plugins/state_machine_event_callbacks_test.rb +0 -102
  72. data/test/plugins/state_machine_test.rb +0 -67
  73. data/test/plugins/transaction_test.rb +0 -84
  74. data/test/test_db.sqlite3 +0 -0
  75. data/test/test_helper.rb +0 -17
@@ -1,116 +0,0 @@
1
- require_relative '../../test_helper'
2
- module Plugins
3
- module Job
4
- # Unit Test for RocketJob::Job
5
- class StateMachineTest < Minitest::Test
6
- class StateMachineJob < RocketJob::Job
7
- def perform
8
- end
9
- end
10
-
11
- describe RocketJob::Plugins::Job::StateMachine do
12
- before do
13
- @job = StateMachineJob.new
14
- end
15
-
16
- after do
17
- @job.destroy if @job && !@job.new_record?
18
- end
19
-
20
- describe '#requeue!' do
21
- it 'requeue jobs from dead workers' do
22
- worker_name = 'server:12345'
23
- @job.worker_name = worker_name
24
- @job.start!
25
- assert @job.running?
26
-
27
- @job.requeue!(worker_name)
28
- @job.reload
29
-
30
- assert @job.queued?
31
- assert_nil @job.worker_name
32
- end
33
- end
34
-
35
- describe '#requeue' do
36
- it 'requeue jobs from dead workers' do
37
- worker_name = 'server:12345'
38
- @job.worker_name = worker_name
39
- assert @job.valid?, @job.errors.messages
40
- @job.start!
41
- assert @job.running?, @job.state
42
-
43
- @job.requeue(worker_name)
44
- assert @job.queued?
45
- assert_nil @job.worker_name
46
-
47
- @job.reload
48
- assert @job.running?
49
- assert_equal worker_name, @job.worker_name
50
- end
51
- end
52
-
53
- describe '#after_complete' do
54
- it 'destroy on complete' do
55
- @job.destroy_on_complete = true
56
- @job.perform_now
57
- assert @job.completed?, @job.state
58
- assert_equal 0, RocketJob::Job.where(id: @job.id).count
59
- end
60
- end
61
-
62
- describe '#fail!' do
63
- it 'fail with message' do
64
- @job.start!
65
- @job.fail!('myworker:2323', 'oh no')
66
- assert @job.failed?
67
- assert exc = @job.exception
68
- assert_equal 'RocketJob::JobException', exc.class_name
69
- assert_equal 'oh no', exc.message
70
- end
71
-
72
- it 'fail with no arguments' do
73
- @job.start!
74
- @job.fail!
75
- assert @job.failed?
76
- assert exc = @job.exception
77
- assert_equal 'RocketJob::JobException', exc.class_name
78
- assert_nil exc.message
79
- assert_nil exc.worker_name
80
- assert_equal [], exc.backtrace
81
- end
82
-
83
- it 'fail with exception' do
84
- @job.start!
85
- exception = RuntimeError.new('Oh no')
86
- @job.fail!('myworker:2323', exception)
87
- assert @job.failed?
88
- assert exc = @job.exception
89
- assert_equal exception.class.name, exc.class_name
90
- assert_equal exception.message, exc.message
91
- assert_equal [], exc.backtrace
92
- end
93
- end
94
-
95
- describe '#retry!' do
96
- it 'retry failed jobs' do
97
- worker_name = 'server:12345'
98
- @job.worker_name = worker_name
99
- @job.start!
100
- assert @job.running?
101
- assert_equal worker_name, @job.worker_name
102
-
103
- @job.fail!(worker_name, 'oh no')
104
- assert @job.failed?
105
- assert_equal 'oh no', @job.exception.message
106
-
107
- @job.retry!
108
- assert @job.queued?
109
- assert_nil @job.worker_name
110
- assert_nil @job.exception
111
- end
112
- end
113
- end
114
- end
115
- end
116
- end
@@ -1,111 +0,0 @@
1
- require_relative '../../test_helper'
2
-
3
- # Unit Test for RocketJob::Job
4
- module Plugins
5
- module Job
6
- class ThrottleTest < Minitest::Test
7
- class ThrottleJob < RocketJob::Job
8
- # Only allow one to be processed at a time
9
- self.throttle_running_jobs = 1
10
- self.pausable = true
11
-
12
- def perform
13
- 21
14
- end
15
- end
16
-
17
- describe RocketJob::Plugins::Job::Throttle do
18
- before do
19
- RocketJob::Job.delete_all
20
- end
21
-
22
- describe '.throttle?' do
23
- it 'defines the running jobs throttle' do
24
- assert ThrottleJob.throttle?(:throttle_running_jobs_exceeded?), ThrottleJob.rocket_job_throttles
25
- refute ThrottleJob.throttle?(:blah?), ThrottleJob.rocket_job_throttles
26
- end
27
- end
28
-
29
- describe '.undefine_throttle' do
30
- it 'undefines the running jobs throttle' do
31
- assert ThrottleJob.throttle?(:throttle_running_jobs_exceeded?), ThrottleJob.rocket_job_throttles
32
- ThrottleJob.undefine_throttle(:throttle_running_jobs_exceeded?)
33
- refute ThrottleJob.throttle?(:throttle_running_jobs_exceeded?), ThrottleJob.rocket_job_throttles
34
- ThrottleJob.define_throttle(:throttle_running_jobs_exceeded?)
35
- assert ThrottleJob.throttle?(:throttle_running_jobs_exceeded?), ThrottleJob.rocket_job_throttles
36
- end
37
- end
38
-
39
- describe '#throttle_running_jobs_exceeded??' do
40
- it 'does not exceed throttle when no other jobs are running' do
41
- ThrottleJob.create!
42
- job = ThrottleJob.new
43
- refute job.send(:throttle_running_jobs_exceeded?)
44
- end
45
-
46
- it 'exceeds throttle when other jobs are running' do
47
- job1 = ThrottleJob.new
48
- job1.start!
49
- job2 = ThrottleJob.new
50
- assert job2.send(:throttle_running_jobs_exceeded?)
51
- end
52
-
53
- it 'excludes paused jobs' do
54
- job1 = ThrottleJob.new
55
- job1.start
56
- job1.pause!
57
- job2 = ThrottleJob.new
58
- refute job2.send(:throttle_running_jobs_exceeded?)
59
- end
60
-
61
- it 'excludes failed jobs' do
62
- job1 = ThrottleJob.new
63
- job1.start
64
- job1.fail!
65
- job2 = ThrottleJob.new
66
- refute job2.send(:throttle_running_jobs_exceeded?)
67
- end
68
- end
69
-
70
- describe '.rocket_job_next_job' do
71
- before do
72
- @worker_name = 'worker:123'
73
- end
74
-
75
- after do
76
- @job.destroy if @job && !@job.new_record?
77
- end
78
-
79
- it 'return nil when no jobs available' do
80
- assert_nil RocketJob::Job.rocket_job_next_job(@worker_name)
81
- end
82
-
83
- it 'return the job when others are queued, paused, failed, or complete' do
84
- @job = ThrottleJob.create!
85
- ThrottleJob.create!(state: :failed)
86
- ThrottleJob.create!(state: :complete)
87
- ThrottleJob.create!(state: :paused)
88
- assert job = RocketJob::Job.rocket_job_next_job(@worker_name), -> { ThrottleJob.all.to_a.ai }
89
- assert_equal @job.id, job.id, -> { ThrottleJob.all.to_a.ai }
90
- end
91
-
92
- it 'return nil when other jobs are running' do
93
- ThrottleJob.create!
94
- @job = ThrottleJob.new
95
- @job.start!
96
- assert_nil RocketJob::Job.rocket_job_next_job(@worker_name), -> { ThrottleJob.all.to_a.ai }
97
- end
98
-
99
- it 'add job to filter when other jobs are running' do
100
- ThrottleJob.create!
101
- @job = ThrottleJob.new
102
- @job.start!
103
- filter = {}
104
- assert_nil RocketJob::Job.rocket_job_next_job(@worker_name, filter), -> { ThrottleJob.all.to_a.ai }
105
- assert_equal 1, filter.size
106
- end
107
- end
108
- end
109
- end
110
- end
111
- end
@@ -1,199 +0,0 @@
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
- self.destroy_on_complete = false
23
- self.collect_output = true
24
- self.priority = 51
25
-
26
- field :first, type: Integer
27
- field :second, type: Integer
28
-
29
- def perform
30
- first + second
31
- end
32
- end
33
-
34
- describe RocketJob::Plugins::Job::Worker do
35
- before do
36
- RocketJob::Job.delete_all
37
- RocketJob::Server.delete_all
38
- end
39
-
40
- after do
41
- @job.destroy if @job && !@job.new_record?
42
- end
43
-
44
- describe '.rocket_job_next_job' do
45
- before do
46
- @job = QuietJob.new
47
- @worker_name = 'worker:123'
48
- end
49
-
50
- it 'return nil when no jobs available' do
51
- assert_nil RocketJob::Job.rocket_job_next_job(@worker_name)
52
- end
53
-
54
- it 'return the first job' do
55
- @job.save!
56
- assert job = RocketJob::Job.rocket_job_next_job(@worker_name), 'Failed to find job'
57
- assert_equal @job.id, job.id
58
- end
59
-
60
- it 'Ignore future dated jobs' do
61
- @job.run_at = Time.now + 1.hour
62
- @job.save!
63
- assert_nil RocketJob::Job.rocket_job_next_job(@worker_name)
64
- end
65
-
66
- it 'Process future dated jobs when time is now' do
67
- @job.run_at = Time.now
68
- @job.save!
69
- assert job = RocketJob::Job.rocket_job_next_job(@worker_name), 'Failed to find future job'
70
- assert_equal @job.id, job.id
71
- end
72
-
73
- it 'Skip expired jobs' do
74
- count = RocketJob::Job.count
75
- @job.expires_at = Time.now - 100
76
- @job.save!
77
- assert_nil RocketJob::Job.rocket_job_next_job(@worker_name)
78
- assert_equal count, RocketJob::Job.count
79
- end
80
- end
81
-
82
- describe '#perform_now' do
83
- it 'calls perform method' do
84
- @job = SumJob.new(first: 10, second: 5)
85
- assert_equal 15, @job.perform_now['result']
86
- assert @job.completed?, @job.attributes.ai
87
- assert_equal 15, @job.result['result']
88
- end
89
-
90
- it 'converts type' do
91
- @job = SumJob.new(first: '10', second: 5)
92
- assert_equal 15, @job.perform_now['result']
93
- assert @job.completed?, @job.attributes.ai
94
- assert_equal 15, @job.result['result']
95
- end
96
-
97
- it 'silence logging when log_level is set' do
98
- @job = NoisyJob.new
99
- @job.log_level = :warn
100
- logged = false
101
- @job.logger.stub(:log_internal, ->(_level, _index, message, _payload, _exception) { logged = true if message.include?('some very noisy logging') }) do
102
- @job.perform_now
103
- end
104
- assert_equal false, logged
105
- end
106
-
107
- it 'raise logging when log_level is set' do
108
- @job = QuietJob.new
109
- @job.log_level = :trace
110
- logged = false
111
- # Raise global log level to :info
112
- SemanticLogger.stub(:default_level_index, 3) do
113
- @job.logger.stub(:log_internal, -> { logged = true }) do
114
- @job.perform_now
115
- end
116
- end
117
- assert_equal false, logged
118
- end
119
- end
120
-
121
- describe '.perform_later' do
122
- it 'queues the job for processing' do
123
- RocketJob::Config.stub(:inline_mode, false) do
124
- @job = SumJob.perform_later(first: 1, second: 23)
125
- end
126
- assert @job.queued?
127
-
128
- # Manually run the job
129
- @job.perform_now
130
- assert @job.completed?, @job.attributes.ai
131
- assert_equal 24, @job.result['result'], -> { @job.result.ai }
132
-
133
- assert_nil @job.worker_name
134
- assert @job.completed_at
135
- assert @job.created_at
136
- assert_equal false, @job.destroy_on_complete
137
- assert_nil @job.expires_at
138
- assert_equal 100, @job.percent_complete
139
- assert_equal 51, @job.priority
140
- assert_equal 0, @job.failure_count
141
- assert_nil @job.run_at
142
- assert @job.started_at
143
- end
144
-
145
- it 'runs the job immediately when inline_mode = true' do
146
- RocketJob::Config.stub(:inline_mode, true) do
147
- @job = SumJob.perform_later(first: 1, second: 23)
148
- end
149
-
150
- assert @job.completed?, @job.attributes.ai
151
- assert_equal 24, @job.result['result']
152
-
153
- assert_nil @job.worker_name
154
- assert @job.completed_at
155
- assert @job.created_at
156
- assert_equal false, @job.destroy_on_complete
157
- assert_nil @job.expires_at
158
- assert_equal 100, @job.percent_complete
159
- assert_equal 51, @job.priority
160
- assert_equal 0, @job.failure_count
161
- assert_nil @job.run_at
162
- assert @job.started_at
163
- end
164
- end
165
-
166
- describe '.perform_now' do
167
- it 'run the job immediately' do
168
- @job = SumJob.perform_now(first: 1, second: 5)
169
- assert_equal true, @job.completed?
170
- assert_equal 6, @job.result['result']
171
- end
172
- end
173
-
174
- describe '#rocket_job_active_workers' do
175
- before do
176
- @job = QuietJob.create!
177
- @worker_name = 'worker:123'
178
- end
179
-
180
- it 'should return empty hash for no active jobs' do
181
- assert_equal([], @job.rocket_job_active_workers)
182
- end
183
-
184
- it 'should return active servers' do
185
- assert job = RocketJob::Job.rocket_job_next_job(@worker_name)
186
- assert active = job.rocket_job_active_workers
187
- assert_equal 1, active.size
188
- assert active_worker = active.first
189
- assert_equal @job.id, active_worker.job.id
190
- assert_equal @worker_name, active_worker.name
191
- assert_equal job.started_at, active_worker.started_at
192
- assert active_worker.duration_s
193
- assert active_worker.duration
194
- end
195
- end
196
- end
197
- end
198
- end
199
- end
@@ -1,109 +0,0 @@
1
- require_relative '../test_helper'
2
-
3
- # Unit Test for RocketJob::Job
4
- module Plugins
5
- class ProcessingWindowTest < Minitest::Test
6
- class ProcessingWindowJob < RocketJob::Job
7
- include RocketJob::Plugins::ProcessingWindow
8
-
9
- def perform
10
- 'DONE'
11
- end
12
- end
13
-
14
- describe RocketJob::Plugins::ProcessingWindow do
15
- before do
16
- # destroy_all could create new instances
17
- ProcessingWindowJob.delete_all
18
- assert_equal 0, ProcessingWindowJob.count
19
- end
20
-
21
- after do
22
- @job.destroy if @job && !@job.new_record?
23
- ProcessingWindowJob.delete_all
24
- end
25
-
26
- describe '#create!' do
27
- it 'queues a new job' do
28
- @job = ProcessingWindowJob.create!(processing_schedule: '* 1 * * *', processing_duration: 1.hour)
29
- assert @job.valid?
30
- refute @job.new_record?
31
- end
32
-
33
- describe 'timezones are supported' do
34
- it 'handles UTC' do
35
- time = Time.parse('2015-12-09 17:50:05 UTC')
36
- Time.stub(:now, time) do
37
- @job = ProcessingWindowJob.create!(processing_schedule: '* 1 * * * UTC', processing_duration: 1.hour)
38
- end
39
- assert @job.valid?
40
- refute @job.new_record?
41
- assert_equal Time.parse('2015-12-10 01:00:00 UTC'), @job.run_at
42
- end
43
-
44
- it 'handles Eastern' do
45
- time = Time.parse('2015-12-09 17:50:05 UTC')
46
- Time.stub(:now, time) do
47
- @job = ProcessingWindowJob.create!(processing_schedule: '* 1 * * * America/New_York', processing_duration: 1.hour)
48
- end
49
- assert @job.valid?
50
- refute @job.new_record?
51
- assert_equal Time.parse('2015-12-10 06:00:00 UTC'), @job.run_at
52
- end
53
- end
54
- end
55
-
56
- describe '#rocket_job_processing_window_active?' do
57
- it 'returns true when in the processing window' do
58
- time = Time.parse('2015-12-09 17:50:05 UTC')
59
- @job = ProcessingWindowJob.new(processing_schedule: '* 17 * * * UTC', processing_duration: 1.hour)
60
- result = Time.stub(:now, time) do
61
- @job.rocket_job_processing_window_active?
62
- end
63
- assert result, @job.attributes.ai
64
- end
65
-
66
- it 'returns false when not in the processing window' do
67
- time = Time.parse('2015-12-09 16:50:05 UTC')
68
- @job = ProcessingWindowJob.new(processing_schedule: '* 17 * * * UTC', processing_duration: 1.hour)
69
- result = Time.stub(:now, time) do
70
- @job.rocket_job_processing_window_active?
71
- end
72
- refute result, @job.attributes.ai
73
- end
74
- end
75
-
76
- describe '#valid?' do
77
- it 'fails on missing processing_schedule' do
78
- @job = ProcessingWindowJob.new
79
- refute @job.valid?
80
- assert_equal "can't be blank", @job.errors.messages[:processing_schedule].first
81
- assert_equal 'not a string: nil', @job.errors.messages[:processing_schedule].second
82
- assert_equal "can't be blank", @job.errors.messages[:processing_duration].first
83
- end
84
-
85
- it 'fails on bad cron schedule' do
86
- @job = ProcessingWindowJob.new(processing_schedule: 'blah')
87
- refute @job.valid?
88
- assert_equal "not a valid cronline : 'blah'", @job.errors.messages[:processing_schedule].first
89
- end
90
-
91
- it 'passes on valid cron schedule' do
92
- @job = ProcessingWindowJob.new(processing_schedule: '* 1 * * *', processing_duration: 1.hour)
93
- assert @job.valid?
94
- end
95
- end
96
-
97
- describe 're-queue' do
98
- it 'if outside processing window' do
99
- time = Time.parse('2015-12-09 16:50:05 UTC')
100
- Time.stub(:now, time) do
101
- @job = ProcessingWindowJob.new(processing_schedule: '* 17 * * * UTC', processing_duration: 1.hour)
102
- @job.perform_now
103
- end
104
- assert @job.queued?, @job.attributes.ai
105
- end
106
- end
107
- end
108
- end
109
- end