rocketjob 1.3.0 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +201 -0
  3. data/README.md +15 -10
  4. data/bin/rocketjob +3 -1
  5. data/bin/rocketjob_perf +92 -0
  6. data/lib/rocket_job/cli.rb +71 -31
  7. data/lib/rocket_job/config.rb +21 -23
  8. data/lib/rocket_job/dirmon_entry.rb +63 -45
  9. data/lib/rocket_job/extensions/aasm.rb +56 -0
  10. data/lib/rocket_job/extensions/mongo.rb +23 -0
  11. data/lib/rocket_job/job.rb +9 -433
  12. data/lib/rocket_job/jobs/dirmon_job.rb +20 -20
  13. data/lib/rocket_job/jobs/simple_job.rb +12 -0
  14. data/lib/rocket_job/plugins/document.rb +69 -0
  15. data/lib/rocket_job/plugins/job/callbacks.rb +92 -0
  16. data/lib/rocket_job/plugins/job/defaults.rb +40 -0
  17. data/lib/rocket_job/plugins/job/logger.rb +36 -0
  18. data/lib/rocket_job/plugins/job/model.rb +288 -0
  19. data/lib/rocket_job/plugins/job/persistence.rb +167 -0
  20. data/lib/rocket_job/plugins/job/state_machine.rb +166 -0
  21. data/lib/rocket_job/plugins/job/worker.rb +167 -0
  22. data/lib/rocket_job/plugins/restart.rb +54 -0
  23. data/lib/rocket_job/plugins/singleton.rb +26 -0
  24. data/lib/rocket_job/plugins/state_machine.rb +105 -0
  25. data/lib/rocket_job/version.rb +1 -1
  26. data/lib/rocket_job/worker.rb +150 -119
  27. data/lib/rocketjob.rb +43 -21
  28. data/test/config_test.rb +12 -0
  29. data/test/dirmon_entry_test.rb +81 -85
  30. data/test/dirmon_job_test.rb +40 -28
  31. data/test/job_test.rb +14 -257
  32. data/test/plugins/job/callbacks_test.rb +163 -0
  33. data/test/plugins/job/defaults_test.rb +52 -0
  34. data/test/plugins/job/logger_test.rb +58 -0
  35. data/test/plugins/job/model_test.rb +97 -0
  36. data/test/plugins/job/persistence_test.rb +81 -0
  37. data/test/plugins/job/state_machine_test.rb +118 -0
  38. data/test/plugins/job/worker_test.rb +183 -0
  39. data/test/plugins/restart_test.rb +185 -0
  40. data/test/plugins/singleton_test.rb +94 -0
  41. data/test/plugins/state_machine_event_callbacks_test.rb +101 -0
  42. data/test/plugins/state_machine_test.rb +64 -0
  43. data/test/test_helper.rb +3 -36
  44. metadata +64 -19
  45. data/lib/rocket_job/concerns/singleton.rb +0 -33
  46. data/lib/rocket_job/concerns/worker.rb +0 -214
  47. data/test/files/_archive/archived.txt +0 -3
  48. data/test/job_worker_test.rb +0 -86
  49. data/test/jobs/test_job.rb +0 -46
  50. data/test/worker_test.rb +0 -97
@@ -1,17 +1,34 @@
1
1
  require_relative 'test_helper'
2
- require_relative 'jobs/test_job'
3
2
 
4
3
  # Unit Test for RocketJob::Job
5
4
  class DirmonEntryTest < Minitest::Test
5
+
6
+ class OneArgumentJob < RocketJob::Job
7
+ def perform(arg)
8
+ end
9
+ end
10
+
6
11
  class WithFullFileNameJob < RocketJob::Job
7
12
  # Dirmon will store the filename in this property when starting the job
8
- key :full_file_name, String
13
+ key :upload_file_name, String
9
14
 
10
15
  def perform
11
- # Do something with the file name stored in :full_file_name
16
+ # Do something with the file name stored in :upload_file_name
12
17
  end
13
18
  end
14
19
 
20
+ class SumJob < RocketJob::Job
21
+ @@result = nil
22
+
23
+ # For temp test data
24
+ def self.result
25
+ @@result
26
+ end
27
+
28
+ def perform(a, b)
29
+ @@result = a + b
30
+ end
31
+ end
15
32
 
16
33
  describe RocketJob::DirmonEntry do
17
34
  describe '.config' do
@@ -57,31 +74,33 @@ class DirmonEntryTest < Minitest::Test
57
74
  end
58
75
 
59
76
  it 'convert relative path to an absolute one' do
60
- path = Pathname('test/jobs').realpath.to_s
61
- assert_equal path, RocketJob::DirmonEntry.add_whitelist_path('test/jobs')
77
+ path = Pathname('test/files').realpath.to_s
78
+ assert_equal path, RocketJob::DirmonEntry.add_whitelist_path('test/files')
62
79
  assert_equal [path], RocketJob::DirmonEntry.whitelist_paths
63
80
  end
64
81
 
65
82
  it 'prevent duplicates' do
66
- path = Pathname('test/jobs').realpath.to_s
67
- assert_equal path, RocketJob::DirmonEntry.add_whitelist_path('test/jobs')
68
- assert_equal path, RocketJob::DirmonEntry.add_whitelist_path('test/jobs')
83
+ path = Pathname('test/files').realpath.to_s
84
+ assert_equal path, RocketJob::DirmonEntry.add_whitelist_path('test/files')
85
+ assert_equal path, RocketJob::DirmonEntry.add_whitelist_path('test/files')
69
86
  assert_equal path, RocketJob::DirmonEntry.add_whitelist_path(path)
70
87
  assert_equal [path], RocketJob::DirmonEntry.whitelist_paths
71
88
  end
72
89
  end
73
90
 
74
- describe '#fail_with_exception!' do
91
+ describe '#fail!' do
75
92
  before do
76
- @dirmon_entry = RocketJob::DirmonEntry.new(job_class_name: 'Jobs::TestJob', pattern: 'test/files/**', arguments: [1])
93
+ @dirmon_entry = RocketJob::DirmonEntry.new(job_class_name: 'DirmonEntryTest::OneArgumentJob', pattern: 'test/files/**', arguments: [1])
77
94
  @dirmon_entry.enable!
95
+ assert @dirmon_entry.valid?, @dirmon_entry.errors.messages.ai
78
96
  end
97
+
79
98
  after do
80
99
  @dirmon_entry.destroy if @dirmon_entry && @dirmon_entry.new_record?
81
100
  end
82
101
 
83
102
  it 'fail with message' do
84
- @dirmon_entry.fail_with_exception!('myworker:2323', 'oh no')
103
+ @dirmon_entry.fail!('myworker:2323', 'oh no')
85
104
  assert_equal true, @dirmon_entry.failed?
86
105
  assert_equal 'RocketJob::DirmonEntryException', @dirmon_entry.exception.class_name
87
106
  assert_equal 'oh no', @dirmon_entry.exception.message
@@ -94,7 +113,7 @@ class DirmonEntryTest < Minitest::Test
94
113
  rescue Exception => exc
95
114
  exception = exc
96
115
  end
97
- @dirmon_entry.fail_with_exception!('myworker:2323', exception)
116
+ @dirmon_entry.fail!('myworker:2323', exception)
98
117
 
99
118
  assert_equal true, @dirmon_entry.failed?
100
119
  assert_equal exception.class.name.to_s, @dirmon_entry.exception.class_name
@@ -104,107 +123,84 @@ class DirmonEntryTest < Minitest::Test
104
123
 
105
124
  describe '#validate' do
106
125
  it 'existance' do
107
- assert entry = RocketJob::DirmonEntry.new(job_class_name: 'Jobs::TestJob')
126
+ assert entry = RocketJob::DirmonEntry.new(job_class_name: 'DirmonEntryTest::OneArgumentJob')
108
127
  assert_equal false, entry.valid?
109
- assert_equal ["can't be blank"], entry.errors[:pattern], entry.errors.inspect
110
- end
111
-
112
- describe 'perform_method' do
113
- describe 'with an invalid method' do
114
- it 'add errors to the entry' do
115
- entry = RocketJob::DirmonEntry.new(job_class_name: 'Jobs::TestJob', perform_method: :missing_perform_method)
116
- assert_equal false, entry.valid?
117
- assert_equal ['Method not implemented by Jobs::TestJob'], entry.errors[:perform_method], entry.errors.inspect
118
- end
119
- end
128
+ assert_equal ["can't be blank"], entry.errors[:pattern], entry.errors.messages.ai
120
129
  end
121
130
 
122
131
  describe 'job_class_name' do
123
132
  it 'ensure presence' do
124
133
  assert entry = RocketJob::DirmonEntry.new(pattern: 'test/files/**')
125
134
  assert_equal false, entry.valid?
126
- 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.inspect
135
+ 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
127
136
  end
128
137
  end
129
138
 
130
139
  describe 'arguments' do
131
140
  it 'allow no arguments' do
132
141
  assert entry = RocketJob::DirmonEntry.new(
133
- job_class_name: 'Jobs::TestJob',
134
- pattern: 'test/files/**',
135
- perform_method: :result
136
- )
137
- assert_equal true, entry.valid?, entry.errors.inspect
138
- assert_equal [], entry.errors[:arguments], entry.errors.inspect
142
+ job_class_name: 'DirmonEntryTest::WithFullFileNameJob',
143
+ pattern: 'test/files/**'
144
+ )
145
+ assert entry.valid?, entry.errors.messages.ai
139
146
  end
140
147
 
141
148
  it 'ensure correct number of arguments' do
142
149
  assert entry = RocketJob::DirmonEntry.new(
143
- job_class_name: 'Jobs::TestJob',
144
- pattern: 'test/files/**'
145
- )
146
- assert_equal false, entry.valid?
147
- assert_equal ['There must be 1 argument(s)'], entry.errors[:arguments], entry.errors.inspect
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
148
155
  end
149
156
 
150
- it 'return false if the job name is bad' do
157
+ it 'fail if the job name is bad' do
151
158
  assert entry = RocketJob::DirmonEntry.new(
152
- job_class_name: 'Jobs::Tests::Names::Things',
153
- pattern: 'test/files/**'
154
- )
155
- assert_equal false, entry.valid?
156
- assert_equal [], entry.errors[:arguments], entry.errors.inspect
157
- end
158
- end
159
-
160
- it 'arguments with perform_method' do
161
- assert entry = RocketJob::DirmonEntry.new(
162
- job_class_name: 'Jobs::TestJob',
163
- pattern: 'test/files/**',
164
- perform_method: :sum
159
+ job_class_name: 'Jobs::Tests::Names::Things',
160
+ pattern: 'test/files/**'
165
161
  )
166
- assert_equal false, entry.valid?
167
- assert_equal ['There must be 2 argument(s)'], entry.errors[:arguments], entry.errors.inspect
162
+ refute entry.valid?
163
+ assert_equal [], entry.errors[:arguments], entry.errors.messages.ai
164
+ end
168
165
  end
169
166
 
170
- it 'valid' do
167
+ it 'invalid without 2 arguments' do
171
168
  assert entry = RocketJob::DirmonEntry.new(
172
- job_class_name: 'Jobs::TestJob',
173
- pattern: 'test/files/**',
174
- arguments: [1]
175
- )
176
- assert entry.valid?, entry.errors.inspect
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
177
174
  end
178
175
 
179
- it 'valid with perform_method' do
176
+ it 'valid with 2 arguments' do
180
177
  assert entry = RocketJob::DirmonEntry.new(
181
- job_class_name: 'Jobs::TestJob',
182
- pattern: 'test/files/**',
183
- perform_method: :sum,
184
- arguments: [1, 2]
185
- )
186
- assert entry.valid?, entry.errors.inspect
178
+ job_class_name: 'DirmonEntryTest::SumJob',
179
+ pattern: 'test/files/**',
180
+ arguments: [1, 2]
181
+ )
182
+ assert entry.valid?, entry.errors.messages.ai
187
183
  end
188
184
  end
189
185
 
190
186
  describe 'with valid entry' do
191
187
  before do
188
+ RocketJob::Jobs::DirmonJob.delete_all
192
189
  @archive_directory = '/tmp/archive_directory'
193
190
  @archive_path = Pathname.new(@archive_directory)
194
191
  @archive_path.mkpath
195
192
  @archive_path = @archive_path.realdirpath
196
193
  @entry = RocketJob::DirmonEntry.new(
197
194
  pattern: 'test/files/**/*',
198
- job_class_name: 'Jobs::TestJob',
195
+ job_class_name: 'RocketJob::Jobs::DirmonJob',
199
196
  arguments: [{}],
200
- properties: {priority: 23, perform_method: :event},
197
+ properties: {priority: 23},
201
198
  archive_directory: @archive_directory
202
199
  )
203
- @job = Jobs::TestJob.new(
200
+ @job = DirmonEntryTest::OneArgumentJob.new(
204
201
  @entry.properties.merge(
205
- arguments: @entry.arguments,
206
- properties: @entry.properties,
207
- perform_method: @entry.perform_method
202
+ arguments: @entry.arguments,
203
+ properties: @entry.properties
208
204
  )
209
205
  )
210
206
  @file = Tempfile.new('archive')
@@ -217,6 +213,7 @@ class DirmonEntryTest < Minitest::Test
217
213
 
218
214
  after do
219
215
  @file.delete if @file
216
+ RocketJob::Jobs::DirmonJob.delete_all
220
217
  end
221
218
 
222
219
  describe '#archive_pathname' do
@@ -243,7 +240,7 @@ class DirmonEntryTest < Minitest::Test
243
240
  assert_equal @archive_real_name, @job.arguments.first[:full_file_name], @job.arguments
244
241
  end
245
242
 
246
- it 'sets full_file_name property' do
243
+ it 'sets upload_file_name property' do
247
244
  @entry = RocketJob::DirmonEntry.new(
248
245
  pattern: 'test/files/**/*',
249
246
  job_class_name: 'DirmonEntryTest::WithFullFileNameJob',
@@ -253,7 +250,7 @@ class DirmonEntryTest < Minitest::Test
253
250
  job = @entry.job_class.new
254
251
  @entry.send(:upload_default, job, @pathname)
255
252
  archive_real_name = @archive_path.join("#{job.id}_#{File.basename(@file_name)}").to_s
256
- assert_equal archive_real_name, job.full_file_name, job.arguments
253
+ assert_equal archive_real_name, job.upload_file_name, job.arguments
257
254
  end
258
255
 
259
256
  it 'handles non hash argument and missing property' do
@@ -265,14 +262,6 @@ class DirmonEntryTest < Minitest::Test
265
262
  end
266
263
 
267
264
  describe '#upload_file' do
268
- it 'upload using #file_store_upload' do
269
- @job.define_singleton_method(:file_store_upload) do |file_name|
270
- self.description = "FILE:#{file_name}"
271
- end
272
- @entry.send(:upload_file, @job, @pathname)
273
- assert_equal "FILE:#{@file_name}", @job.description
274
- end
275
-
276
265
  it 'upload using #upload' do
277
266
  @job.define_singleton_method(:upload) do |file_name|
278
267
  self.description = "FILE:#{file_name}"
@@ -283,13 +272,20 @@ class DirmonEntryTest < Minitest::Test
283
272
  end
284
273
 
285
274
  describe '#later' do
286
- it 'enqueue job' do
287
- @entry.arguments = [{}]
288
- @entry.perform_method = :event
289
- job = @entry.later(@pathname)
275
+ it 'enqueues job' do
276
+ @entry.arguments = [{}]
277
+ job = @entry.later(@pathname)
290
278
  assert_equal Pathname.new(@archive_directory).join("#{job.id}_#{File.basename(@file_name)}").realdirpath.to_s, job.arguments.first[:full_file_name]
291
279
  assert job.queued?
292
280
  end
281
+
282
+ it 'fails with bad job class name' do
283
+ @entry.arguments = [{}]
284
+ @entry.job_class_name = 'Blah'
285
+ assert_raises ArgumentError do
286
+ @entry.later(@pathname)
287
+ end
288
+ end
293
289
  end
294
290
 
295
291
  describe '#each' do
@@ -1,18 +1,24 @@
1
1
  require_relative 'test_helper'
2
- require_relative 'jobs/test_job'
3
2
 
4
3
  # Unit Test for RocketJob::Job
5
4
  class DirmonJobTest < Minitest::Test
5
+ class DirmonTestJob < RocketJob::Job
6
+ def perform(hash)
7
+ 3645
8
+ end
9
+ end
10
+
6
11
  describe RocketJob::Jobs::DirmonJob do
7
12
  before do
13
+ RocketJob::Jobs::DirmonJob.delete_all
8
14
  @dirmon_job = RocketJob::Jobs::DirmonJob.new
9
15
  @directory = '/tmp/directory'
10
16
  @archive_directory = '/tmp/archive_directory'
11
17
  @entry = RocketJob::DirmonEntry.new(
12
18
  pattern: "#{@directory}/abc/*",
13
- job_class_name: 'Jobs::TestJob',
19
+ job_class_name: 'DirmonJobTest::DirmonTestJob',
14
20
  arguments: [{input: 'yes'}],
15
- properties: {priority: 23, perform_method: :event},
21
+ properties: {priority: 23},
16
22
  archive_directory: @archive_directory
17
23
  )
18
24
  FileUtils.makedirs("#{@directory}/abc")
@@ -20,7 +26,7 @@ class DirmonJobTest < Minitest::Test
20
26
  end
21
27
 
22
28
  after do
23
- @dirmon_job.destroy if @dirmon_job && !@dirmon_job.new_record?
29
+ @dirmon_job.delete if @dirmon_job && !@dirmon_job.new_record?
24
30
  FileUtils.remove_dir(@archive_directory, true) if Dir.exist?(@archive_directory)
25
31
  FileUtils.remove_dir(@directory, true) if Dir.exist?(@directory)
26
32
  end
@@ -57,8 +63,9 @@ class DirmonJobTest < Minitest::Test
57
63
  it 'check deleted file' do
58
64
  previous_size = 5
59
65
  file_name = Pathname.new('blah')
60
- result = @dirmon_job.send(:check_file, @entry, file_name, previous_size)
61
- assert_equal nil, result
66
+ assert_raises Errno::ENOENT do
67
+ @dirmon_job.send(:check_file, @entry, file_name, previous_size)
68
+ end
62
69
  end
63
70
  end
64
71
 
@@ -137,7 +144,6 @@ class DirmonJobTest < Minitest::Test
137
144
 
138
145
  describe '#perform' do
139
146
  it 'check directories and reschedule' do
140
- dirmon_job = nil
141
147
  previous_file_names = {
142
148
  "#{@directory}/abc/file1" => 5,
143
149
  "#{@directory}/abc/file2" => 10,
@@ -146,22 +152,24 @@ class DirmonJobTest < Minitest::Test
146
152
  "#{@directory}/abc/file1" => 10,
147
153
  "#{@directory}/abc/file2" => 10,
148
154
  }
149
- RocketJob::Jobs::DirmonJob.destroy_all
155
+ assert_equal 0, RocketJob::Jobs::DirmonJob.count
156
+ # perform_now does not save the job, just runs it
157
+ @dirmon_job = RocketJob::Jobs::DirmonJob.create!(
158
+ previous_file_names: previous_file_names,
159
+ priority: 11,
160
+ check_seconds: 30
161
+ )
150
162
  RocketJob::Jobs::DirmonJob.stub_any_instance(:check_directories, new_file_names) do
151
- # perform_now does not save the job, just runs it
152
- dirmon_job = RocketJob::Jobs::DirmonJob.new(
153
- previous_file_names: previous_file_names,
154
- priority: 11,
155
- check_seconds: 30
156
- )
157
- dirmon_job.work_now
163
+ @dirmon_job.perform_now
158
164
  end
159
- assert dirmon_job.completed?, dirmon_job.status.inspect
165
+ assert @dirmon_job.completed?, @dirmon_job.status.inspect
166
+ # Job must destroy on complete
167
+ refute RocketJob::Jobs::DirmonJob.find(@dirmon_job.id)
160
168
 
161
- # It it have enqueued another instance to run in the future
169
+ # Must have enqueued another instance to run in the future
162
170
  assert_equal 1, RocketJob::Jobs::DirmonJob.count
163
171
  assert new_dirmon_job = RocketJob::Jobs::DirmonJob.last
164
- assert_equal false, dirmon_job.id == new_dirmon_job.id
172
+ refute_equal @dirmon_job.id.to_s, new_dirmon_job.id.to_s
165
173
  assert new_dirmon_job.run_at
166
174
  assert_equal 11, new_dirmon_job.priority
167
175
  assert_equal 30, new_dirmon_job.check_seconds
@@ -171,20 +179,24 @@ class DirmonJobTest < Minitest::Test
171
179
  end
172
180
 
173
181
  it 'check directories and reschedule even on exception' do
174
- dirmon_job = nil
175
182
  RocketJob::Jobs::DirmonJob.destroy_all
176
- RocketJob::Jobs::DirmonJob.stub_any_instance(:check_directories, -> previous { raise RuntimeError.new("Oh no") }) do
177
- # perform_now does not save the job, just runs it
178
- dirmon_job = RocketJob::Jobs::DirmonJob.create!(
179
- priority: 11,
180
- check_seconds: 30
181
- )
182
- dirmon_job.work_now
183
+ # perform_now does not save the job, just runs it
184
+ dirmon_job = RocketJob::Jobs::DirmonJob.create!(
185
+ priority: 11,
186
+ check_seconds: 30,
187
+ destroy_on_complete: false
188
+ )
189
+ RocketJob::Jobs::DirmonJob.stub_any_instance(:check_directories, -> { raise RuntimeError.new('Oh no') }) do
190
+ assert_raises RuntimeError do
191
+ dirmon_job.perform_now
192
+ end
183
193
  end
184
- assert dirmon_job.failed?, dirmon_job.status.inspect
194
+ assert dirmon_job.aborted?, dirmon_job.status.ai
195
+ assert_equal 'RuntimeError', dirmon_job.exception.class_name, dirmon_job.exception.attributes
196
+ assert_equal 'Oh no', dirmon_job.exception.message, dirmon_job.exception.attributes
185
197
 
186
198
  # Must have enqueued another instance to run in the future
187
- assert_equal 2, RocketJob::Jobs::DirmonJob.count
199
+ assert_equal 2, RocketJob::Jobs::DirmonJob.count, RocketJob::Jobs::DirmonJob.to_a
188
200
  assert new_dirmon_job = RocketJob::Jobs::DirmonJob.last
189
201
  assert new_dirmon_job.run_at
190
202
  assert_equal 11, new_dirmon_job.priority