rocketjob 2.1.3 → 3.0.0.alpha

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +36 -0
  3. data/lib/rocket_job/active_server.rb +48 -0
  4. data/lib/rocket_job/cli.rb +29 -17
  5. data/lib/rocket_job/config.rb +19 -31
  6. data/lib/rocket_job/dirmon_entry.rb +15 -45
  7. data/lib/rocket_job/extensions/mongo/logging.rb +26 -0
  8. data/lib/rocket_job/extensions/rocket_job_adapter.rb +3 -5
  9. data/lib/rocket_job/heartbeat.rb +18 -23
  10. data/lib/rocket_job/job.rb +0 -1
  11. data/lib/rocket_job/job_exception.rb +11 -13
  12. data/lib/rocket_job/jobs/dirmon_job.rb +8 -8
  13. data/lib/rocket_job/jobs/housekeeping_job.rb +13 -15
  14. data/lib/rocket_job/performance.rb +5 -5
  15. data/lib/rocket_job/plugins/cron.rb +3 -10
  16. data/lib/rocket_job/plugins/document.rb +58 -33
  17. data/lib/rocket_job/plugins/job/model.rb +43 -71
  18. data/lib/rocket_job/plugins/job/persistence.rb +7 -63
  19. data/lib/rocket_job/plugins/job/worker.rb +24 -26
  20. data/lib/rocket_job/plugins/processing_window.rb +6 -9
  21. data/lib/rocket_job/plugins/retry.rb +3 -8
  22. data/lib/rocket_job/plugins/singleton.rb +1 -1
  23. data/lib/rocket_job/plugins/state_machine.rb +1 -7
  24. data/lib/rocket_job/server.rb +352 -0
  25. data/lib/rocket_job/version.rb +1 -1
  26. data/lib/rocket_job/worker.rb +46 -336
  27. data/lib/rocketjob.rb +5 -4
  28. data/test/config/mongoid.yml +88 -0
  29. data/test/config_test.rb +1 -1
  30. data/test/dirmon_entry_test.rb +15 -79
  31. data/test/dirmon_job_test.rb +6 -6
  32. data/test/job_test.rb +2 -2
  33. data/test/plugins/job/callbacks_test.rb +40 -32
  34. data/test/plugins/job/defaults_test.rb +10 -8
  35. data/test/plugins/job/model_test.rb +1 -3
  36. data/test/plugins/job/persistence_test.rb +11 -13
  37. data/test/plugins/job/worker_test.rb +45 -26
  38. data/test/plugins/processing_window_test.rb +4 -4
  39. data/test/plugins/restart_test.rb +11 -12
  40. data/test/plugins/state_machine_event_callbacks_test.rb +20 -18
  41. data/test/plugins/state_machine_test.rb +5 -5
  42. data/test/test_helper.rb +4 -1
  43. metadata +15 -29
  44. data/lib/rocket_job/extensions/mongo.rb +0 -23
  45. data/lib/rocket_job/extensions/mongo_mapper.rb +0 -30
  46. data/lib/rocket_job/plugins/job/defaults.rb +0 -40
  47. data/test/config/mongo.yml +0 -46
@@ -0,0 +1,88 @@
1
+ # See: https://docs.mongodb.com/ruby-driver/master/tutorials/5.1.0/mongoid-installation/
2
+ client_options: &client_options
3
+ read:
4
+ mode: :primary
5
+ write:
6
+ w: 0
7
+ max_pool_size: 50
8
+ min_pool_size: 10
9
+ connect_timeout: 5
10
+ socket_timeout: 300
11
+ wait_queue_timeout: 5
12
+
13
+ mongoid_options: &mongoid_options
14
+ # Includes the root model name in json serialization. (default: false)
15
+ # include_root_in_json: false
16
+
17
+ # Include the _type field in serialization. (default: false)
18
+ # include_type_for_serialization: false
19
+
20
+ # Preload all models in development, needed when models use
21
+ # inheritance. (default: false)
22
+ preload_models: true
23
+
24
+ # Raise an error when performing a #find and the document is not found.
25
+ # (default: true)
26
+ # raise_not_found_error: true
27
+
28
+ # Raise an error when defining a scope with the same name as an
29
+ # existing method. (default: false)
30
+ scope_overwrite_exception: true
31
+
32
+ # Use Active Support's time zone in conversions. (default: true)
33
+ # use_activesupport_time_zone: true
34
+
35
+ # Ensure all times are UTC in the app side. (default: false)
36
+ use_utc: true
37
+
38
+ development:
39
+ clients:
40
+ default: &default_development
41
+ uri: mongodb://localhost:27017/rocketjob_development
42
+ options:
43
+ <<: *client_options
44
+ write:
45
+ w: 0
46
+ max_pool_size: 5
47
+ min_pool_size: 1
48
+ rocketjob:
49
+ <<: *default_development
50
+ rocketjob_slices:
51
+ <<: *default_development
52
+ options:
53
+ <<: *mongoid_options
54
+
55
+ test:
56
+ clients:
57
+ default: &default_test
58
+ uri: mongodb://localhost:27017/rocketjob_test
59
+ options:
60
+ <<: *client_options
61
+ write:
62
+ w: 1
63
+ max_pool_size: 5
64
+ min_pool_size: 1
65
+ rocketjob:
66
+ <<: *default_test
67
+ rocketjob_slices:
68
+ <<: *default_test
69
+ options:
70
+ <<: *mongoid_options
71
+
72
+ production:
73
+ clients:
74
+ default: &default_production
75
+ uri: mongodb://user:secret@server.example.org:27017,server2.example.org:27017/rocketjob_production
76
+ options:
77
+ <<: *client_options
78
+ write:
79
+ w: 0
80
+ rocketjob:
81
+ <<: *default_production
82
+ rocketjob_slices:
83
+ <<: *default_production
84
+ # Optionally Specify a different database or even server to store slices on
85
+ # uri: mongodb://user:secret@server3.example.org:27017/slices_production
86
+ options:
87
+ <<: *mongoid_options
88
+
data/test/config_test.rb CHANGED
@@ -4,7 +4,7 @@ class ConfigTest < Minitest::Test
4
4
 
5
5
  describe '.config' do
6
6
  it 'support multiple databases' do
7
- assert_equal 'test_rocketjob', RocketJob::Job.collection.db.name
7
+ assert_equal 'rocketjob_test', RocketJob::Job.collection.database.name
8
8
  end
9
9
  end
10
10
 
@@ -3,14 +3,9 @@ require_relative 'test_helper'
3
3
  # Unit Test for RocketJob::Job
4
4
  class DirmonEntryTest < Minitest::Test
5
5
 
6
- class OneArgumentJob < RocketJob::Job
7
- def perform(arg)
8
- end
9
- end
10
-
11
6
  class WithFullFileNameJob < RocketJob::Job
12
7
  # Dirmon will store the filename in this property when starting the job
13
- key :upload_file_name, String
8
+ field :upload_file_name, type: String
14
9
 
15
10
  def perform
16
11
  # Do something with the file name stored in :upload_file_name
@@ -33,7 +28,7 @@ class DirmonEntryTest < Minitest::Test
33
28
  describe RocketJob::DirmonEntry do
34
29
  describe '.config' do
35
30
  it 'support multiple databases' do
36
- assert_equal 'test_rocketjob', RocketJob::DirmonEntry.collection.db.name
31
+ assert_equal 'rocketjob_test', RocketJob::DirmonEntry.collection.database.name
37
32
  end
38
33
  end
39
34
 
@@ -56,7 +51,6 @@ class DirmonEntryTest < Minitest::Test
56
51
  it 'return job class' do
57
52
  entry = RocketJob::DirmonEntry.new(job_class_name: 'RocketJob::Job')
58
53
  assert_equal(RocketJob::Job, entry.job_class)
59
- assert_equal 0, entry.arguments.size
60
54
  assert_equal 0, entry.properties.size
61
55
  end
62
56
  end
@@ -90,7 +84,7 @@ class DirmonEntryTest < Minitest::Test
90
84
 
91
85
  describe '#fail!' do
92
86
  before do
93
- @dirmon_entry = RocketJob::DirmonEntry.new(job_class_name: 'DirmonEntryTest::OneArgumentJob', pattern: 'test/files/**', arguments: [1])
87
+ @dirmon_entry = RocketJob::DirmonEntry.new(job_class_name: 'DirmonEntryTest::WithFullFileNameJob', pattern: 'test/files/**')
94
88
  @dirmon_entry.enable!
95
89
  assert @dirmon_entry.valid?, @dirmon_entry.errors.messages.ai
96
90
  end
@@ -123,7 +117,7 @@ class DirmonEntryTest < Minitest::Test
123
117
 
124
118
  describe '#validate' do
125
119
  it 'existance' do
126
- assert entry = RocketJob::DirmonEntry.new(job_class_name: 'DirmonEntryTest::OneArgumentJob')
120
+ assert entry = RocketJob::DirmonEntry.new(job_class_name: 'DirmonEntryTest::WithFullFileNameJob')
127
121
  assert_equal false, entry.valid?
128
122
  assert_equal ["can't be blank"], entry.errors[:pattern], entry.errors.messages.ai
129
123
  end
@@ -135,52 +129,6 @@ class DirmonEntryTest < Minitest::Test
135
129
  assert_equal ["can't be blank", 'job_class_name must be defined and must be derived from RocketJob::Job'], entry.errors[:job_class_name], entry.errors.messages.ai
136
130
  end
137
131
  end
138
-
139
- describe 'arguments' do
140
- it 'allow no arguments' do
141
- assert entry = RocketJob::DirmonEntry.new(
142
- job_class_name: 'DirmonEntryTest::WithFullFileNameJob',
143
- pattern: 'test/files/**'
144
- )
145
- assert entry.valid?, entry.errors.messages.ai
146
- end
147
-
148
- it 'ensure correct number of arguments' do
149
- assert entry = RocketJob::DirmonEntry.new(
150
- job_class_name: 'DirmonEntryTest::OneArgumentJob',
151
- pattern: 'test/files/**'
152
- )
153
- refute entry.valid?
154
- assert_equal ['There must be 1 argument(s)'], entry.errors[:arguments], entry.errors.messages.ai
155
- end
156
-
157
- it 'fail if the job name is bad' do
158
- assert entry = RocketJob::DirmonEntry.new(
159
- job_class_name: 'Jobs::Tests::Names::Things',
160
- pattern: 'test/files/**'
161
- )
162
- refute entry.valid?
163
- assert_equal [], entry.errors[:arguments], entry.errors.messages.ai
164
- end
165
- end
166
-
167
- it 'invalid without 2 arguments' do
168
- assert entry = RocketJob::DirmonEntry.new(
169
- job_class_name: 'DirmonEntryTest::SumJob',
170
- pattern: 'test/files/**'
171
- )
172
- refute entry.valid?
173
- assert_equal ['There must be 2 argument(s)'], entry.errors[:arguments], entry.errors.messages.ai
174
- end
175
-
176
- it 'valid with 2 arguments' do
177
- assert entry = RocketJob::DirmonEntry.new(
178
- job_class_name: 'DirmonEntryTest::SumJob',
179
- pattern: 'test/files/**',
180
- arguments: [1, 2]
181
- )
182
- assert entry.valid?, entry.errors.messages.ai
183
- end
184
132
  end
185
133
 
186
134
  describe 'with valid entry' do
@@ -193,15 +141,11 @@ class DirmonEntryTest < Minitest::Test
193
141
  @entry = RocketJob::DirmonEntry.new(
194
142
  pattern: 'test/files/**/*',
195
143
  job_class_name: 'RocketJob::Jobs::DirmonJob',
196
- arguments: [{}],
197
144
  properties: {priority: 23},
198
145
  archive_directory: @archive_directory
199
146
  )
200
- @job = DirmonEntryTest::OneArgumentJob.new(
201
- @entry.properties.merge(
202
- arguments: @entry.arguments,
203
- properties: @entry.properties
204
- )
147
+ @job = DirmonEntryTest::WithFullFileNameJob.new(
148
+ @entry.properties
205
149
  )
206
150
  @file = Tempfile.new('archive')
207
151
  @file_name = @file.path
@@ -235,11 +179,6 @@ class DirmonEntryTest < Minitest::Test
235
179
  end
236
180
 
237
181
  describe '#upload_default' do
238
- it 'sets full_file_name in Hash argument' do
239
- @entry.send(:upload_default, @job, @pathname)
240
- assert_equal @archive_real_name, @job.arguments.first[:full_file_name], @job.arguments
241
- end
242
-
243
182
  it 'sets upload_file_name property' do
244
183
  @entry = RocketJob::DirmonEntry.new(
245
184
  pattern: 'test/files/**/*',
@@ -250,14 +189,7 @@ class DirmonEntryTest < Minitest::Test
250
189
  job = @entry.job_class.new
251
190
  @entry.send(:upload_default, job, @pathname)
252
191
  archive_real_name = @archive_path.join("#{job.id}_#{File.basename(@file_name)}").to_s
253
- assert_equal archive_real_name, job.upload_file_name, job.arguments
254
- end
255
-
256
- it 'handles non hash argument and missing property' do
257
- @job.arguments = [1]
258
- assert_raises ArgumentError do
259
- @entry.send(:upload_default, @job, @pathname)
260
- end
192
+ assert_equal archive_real_name, job.upload_file_name
261
193
  end
262
194
  end
263
195
 
@@ -273,14 +205,18 @@ class DirmonEntryTest < Minitest::Test
273
205
 
274
206
  describe '#later' do
275
207
  it 'enqueues job' do
276
- @entry.arguments = [{}]
277
- job = @entry.later(@pathname)
278
- assert_equal Pathname.new(@archive_directory).join("#{job.id}_#{File.basename(@file_name)}").realdirpath.to_s, job.arguments.first[:full_file_name]
208
+ @entry = RocketJob::DirmonEntry.new(
209
+ pattern: 'test/files/**/*',
210
+ job_class_name: 'DirmonEntryTest::WithFullFileNameJob',
211
+ archive_directory: @archive_directory
212
+ )
213
+ job = @entry.later(@pathname)
214
+ assert_equal Pathname.new(@archive_directory).join("#{job.id}_#{File.basename(@file_name)}").realdirpath.to_s, job.upload_file_name
279
215
  assert job.queued?
216
+ assert_equal 50, job.priority
280
217
  end
281
218
 
282
219
  it 'fails with bad job class name' do
283
- @entry.arguments = [{}]
284
220
  @entry.job_class_name = 'Blah'
285
221
  assert_raises ArgumentError do
286
222
  @entry.later(@pathname)
@@ -17,7 +17,6 @@ class DirmonJobTest < Minitest::Test
17
17
  @entry = RocketJob::DirmonEntry.new(
18
18
  pattern: "#{@directory}/abc/*",
19
19
  job_class_name: 'DirmonJobTest::DirmonTestJob',
20
- arguments: [{input: 'yes'}],
21
20
  properties: {priority: 23},
22
21
  archive_directory: @archive_directory
23
22
  )
@@ -164,7 +163,7 @@ class DirmonJobTest < Minitest::Test
164
163
  end
165
164
  assert @dirmon_job.completed?, @dirmon_job.status.inspect
166
165
  # Job must destroy on complete
167
- refute RocketJob::Jobs::DirmonJob.find(@dirmon_job.id)
166
+ assert_equal 0, RocketJob::Jobs::DirmonJob.where(id: @dirmon_job.id).count, -> { RocketJob::Jobs::DirmonJob.all.to_a.ai }
168
167
 
169
168
  # Must have enqueued another instance to run in the future
170
169
  assert_equal 1, RocketJob::Jobs::DirmonJob.count
@@ -191,17 +190,18 @@ class DirmonJobTest < Minitest::Test
191
190
  dirmon_job.perform_now
192
191
  end
193
192
  end
193
+ dirmon_job.save!
194
194
  assert dirmon_job.aborted?, dirmon_job.status.ai
195
195
  assert_equal 'RuntimeError', dirmon_job.exception.class_name, dirmon_job.exception.attributes
196
196
  assert_equal 'Oh no', dirmon_job.exception.message, dirmon_job.exception.attributes
197
197
 
198
198
  # Must have enqueued another instance to run in the future
199
- assert_equal 2, RocketJob::Jobs::DirmonJob.count, RocketJob::Jobs::DirmonJob.to_a
200
- assert new_dirmon_job = RocketJob::Jobs::DirmonJob.last
199
+ assert_equal 2, RocketJob::Jobs::DirmonJob.count, -> { RocketJob::Jobs::DirmonJob.all.ai }
200
+ assert new_dirmon_job = RocketJob::Jobs::DirmonJob.queued.first
201
201
  assert new_dirmon_job.run_at
202
- assert_equal 11, new_dirmon_job.priority
202
+ assert_equal 11, new_dirmon_job.priority, -> { new_dirmon_job.attributes.ai }
203
203
  assert_equal 30, new_dirmon_job.check_seconds
204
- assert new_dirmon_job.queued?
204
+ assert new_dirmon_job.queued?, new_dirmon_job.state
205
205
 
206
206
  new_dirmon_job.destroy
207
207
  end
data/test/job_test.rb CHANGED
@@ -40,7 +40,7 @@ class JobTest < Minitest::Test
40
40
  end
41
41
  end
42
42
 
43
- describe '.requeue_dead_worker' do
43
+ describe '.requeue_dead_server' do
44
44
  it 'requeue jobs from dead workers' do
45
45
  assert_equal 52, @job2.priority
46
46
  worker_name = 'server:12345'
@@ -55,7 +55,7 @@ class JobTest < Minitest::Test
55
55
  assert @job2.running?, @job2.state
56
56
  @job2.save!
57
57
 
58
- RocketJob::Job.requeue_dead_worker(worker_name)
58
+ RocketJob::Job.requeue_dead_server(worker_name)
59
59
  @job.reload
60
60
 
61
61
  assert @job.queued?
@@ -6,82 +6,90 @@ module Plugins
6
6
  class CallbacksTest < Minitest::Test
7
7
  # This job adds each callback as they run into an array
8
8
  class BeforePerformJob < RocketJob::Job
9
+ field :call_list, type: Array, default: []
10
+
9
11
  before_perform do
10
- arguments.first << 'before_perform_block'
12
+ call_list << 'before_perform_block'
11
13
  end
12
14
 
13
15
  before_perform :before_perform_method
14
16
 
15
- def perform(list)
16
- list << 'perform'
17
+ def perform
18
+ call_list << 'perform'
17
19
  end
18
20
 
19
21
  private
20
22
 
21
23
  def before_perform_method
22
- arguments.first << 'before_perform_method'
24
+ call_list << 'before_perform_method'
23
25
  end
24
26
 
25
27
  end
26
28
 
27
29
  # This job adds each callback as they run into an array
28
30
  class AfterPerformJob < RocketJob::Job
31
+ field :call_list, type: Array, default: []
32
+
29
33
  after_perform do
30
- arguments.first << 'after_perform_block'
34
+ call_list << 'after_perform_block'
31
35
  end
32
36
 
33
37
  after_perform :after_perform_method
34
38
 
35
- def perform(list)
36
- list << 'perform'
39
+ def perform
40
+ call_list << 'perform'
37
41
  end
38
42
 
39
43
  private
40
44
 
41
45
  def after_perform_method
42
- arguments.first << 'after_perform_method'
46
+ call_list << 'after_perform_method'
43
47
  end
44
48
 
45
49
  end
46
50
 
47
51
  # This job adds each callback as they run into an array
48
52
  class AroundPerformJob < RocketJob::Job
53
+ field :call_list, type: Array, default: []
54
+
49
55
  around_perform do |job, block|
50
- arguments.first << 'around_perform_block_before'
56
+ call_list << 'around_perform_block_before'
51
57
  block.call
52
- arguments.first << 'around_perform_block_after'
58
+ call_list << 'around_perform_block_after'
53
59
  end
54
60
 
55
61
  around_perform :around_perform_method
56
62
 
57
- def perform(list)
58
- list << 'perform'
63
+ def perform
64
+ call_list << 'perform'
59
65
  end
60
66
 
61
67
  private
62
68
 
63
69
  def around_perform_method
64
- arguments.first << 'around_perform_method_before'
70
+ call_list << 'around_perform_method_before'
65
71
  yield
66
- arguments.first << 'around_perform_method_after'
72
+ call_list << 'around_perform_method_after'
67
73
  end
68
74
 
69
75
  end
70
76
 
71
77
  # This job adds each callback as they run into an array
72
78
  class CombinedPerformJob < RocketJob::Job
79
+ field :call_list, type: Array, default: []
80
+
73
81
  before_perform do
74
- arguments.first << 'before_perform_block'
82
+ call_list << 'before_perform_block'
75
83
  end
76
84
 
77
85
  after_perform do
78
- arguments.first << 'after_perform_block'
86
+ call_list << 'after_perform_block'
79
87
  end
80
88
 
81
89
  around_perform do |job, block|
82
- arguments.first << 'around_perform_block_before'
90
+ call_list << 'around_perform_block_before'
83
91
  block.call
84
- arguments.first << 'around_perform_block_after'
92
+ call_list << 'around_perform_block_after'
85
93
  end
86
94
 
87
95
  before_perform :before_perform_method
@@ -90,24 +98,24 @@ module Plugins
90
98
 
91
99
  after_perform :after_perform_method
92
100
 
93
- def perform(list)
94
- list << 'perform'
101
+ def perform
102
+ call_list << 'perform'
95
103
  end
96
104
 
97
105
  private
98
106
 
99
107
  def before_perform_method
100
- arguments.first << 'before_perform_method'
108
+ call_list << 'before_perform_method'
101
109
  end
102
110
 
103
111
  def around_perform_method(&block)
104
- arguments.first << 'around_perform_method_before'
112
+ call_list << 'around_perform_method_before'
105
113
  block.call
106
- arguments.first << 'around_perform_method_after'
114
+ call_list << 'around_perform_method_after'
107
115
  end
108
116
 
109
117
  def after_perform_method
110
- arguments.first << 'after_perform_method'
118
+ call_list << 'after_perform_method'
111
119
  end
112
120
 
113
121
  end
@@ -119,41 +127,41 @@ module Plugins
119
127
 
120
128
  describe '#before_perform' do
121
129
  it 'runs blocks and functions' do
122
- @job = BeforePerformJob.new(arguments: [[]])
130
+ @job = BeforePerformJob.new
123
131
  @job.perform_now
124
132
  assert @job.completed?, @job.attributes.ai
125
133
  expected = %w(before_perform_block before_perform_method perform)
126
- assert_equal expected, @job.arguments.first, 'Sequence of before_perform callbacks is incorrect'
134
+ assert_equal expected, @job.call_list, 'Sequence of before_perform callbacks is incorrect'
127
135
  end
128
136
  end
129
137
 
130
138
  describe '#after_perform' do
131
139
  it 'runs blocks and functions' do
132
- @job = AfterPerformJob.new(arguments: [[]])
140
+ @job = AfterPerformJob.new
133
141
  @job.perform_now
134
142
  assert @job.completed?, @job.attributes.ai
135
143
  expected = %w(perform after_perform_method after_perform_block)
136
- assert_equal expected, @job.arguments.first, 'Sequence of after_perform callbacks is incorrect'
144
+ assert_equal expected, @job.call_list, 'Sequence of after_perform callbacks is incorrect'
137
145
  end
138
146
  end
139
147
 
140
148
  describe '#around_perform' do
141
149
  it 'runs blocks and functions' do
142
- @job = AroundPerformJob.new(arguments: [[]])
150
+ @job = AroundPerformJob.new
143
151
  @job.perform_now
144
152
  assert @job.completed?, @job.attributes.ai
145
153
  expected = %w(around_perform_block_before around_perform_method_before perform around_perform_method_after around_perform_block_after)
146
- assert_equal expected, @job.arguments.first, 'Sequence of around_perform callbacks is incorrect'
154
+ assert_equal expected, @job.call_list, 'Sequence of around_perform callbacks is incorrect'
147
155
  end
148
156
  end
149
157
 
150
158
  describe 'all callbacks' do
151
159
  it 'runs them in the right order' do
152
- @job = CombinedPerformJob.new(arguments: [[]])
160
+ @job = CombinedPerformJob.new
153
161
  @job.perform_now
154
162
  assert @job.completed?, @job.attributes.ai
155
163
  expected = %w(before_perform_block around_perform_block_before before_perform_method around_perform_method_before perform after_perform_method around_perform_method_after around_perform_block_after after_perform_block)
156
- assert_equal expected, @job.arguments.first, 'Sequence of around_perform callbacks is incorrect'
164
+ assert_equal expected, @job.call_list, 'Sequence of around_perform callbacks is incorrect'
157
165
  end
158
166
  end
159
167