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,101 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
module Plugins
|
4
|
+
# Unit Test for RocketJob::Job
|
5
|
+
class StateMachineEventCallbacksTest < Minitest::Test
|
6
|
+
# This job adds each event callback as they run into an array
|
7
|
+
# [:start, :complete, :fail, :retry, :pause, :resume, :abort, :requeue]
|
8
|
+
class PositivePathJob < RocketJob::Job
|
9
|
+
before_complete do
|
10
|
+
arguments.first << 'before_complete_block'
|
11
|
+
end
|
12
|
+
|
13
|
+
after_complete do
|
14
|
+
arguments.first << 'after_complete_block'
|
15
|
+
end
|
16
|
+
|
17
|
+
before_complete :before_complete_method
|
18
|
+
|
19
|
+
before_start do
|
20
|
+
arguments.first << 'before_start_block'
|
21
|
+
end
|
22
|
+
|
23
|
+
before_start :before_start_method
|
24
|
+
|
25
|
+
before_start do
|
26
|
+
arguments.first << 'before_start2_block'
|
27
|
+
end
|
28
|
+
|
29
|
+
after_start :after_start_method
|
30
|
+
after_complete :after_complete_method
|
31
|
+
|
32
|
+
before_complete do
|
33
|
+
arguments.first << 'before_complete2_block'
|
34
|
+
end
|
35
|
+
|
36
|
+
after_start do
|
37
|
+
arguments.first << 'after_start_block'
|
38
|
+
end
|
39
|
+
|
40
|
+
after_complete do
|
41
|
+
arguments.first << 'after_complete2_block'
|
42
|
+
end
|
43
|
+
|
44
|
+
after_start :after_start_method
|
45
|
+
|
46
|
+
after_start do
|
47
|
+
arguments.first << 'after_start2_block'
|
48
|
+
end
|
49
|
+
|
50
|
+
before_start :before_start_method2
|
51
|
+
before_complete :before_complete_method2
|
52
|
+
|
53
|
+
def perform(list)
|
54
|
+
list << 'perform'
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def before_start_method
|
60
|
+
arguments.first << 'before_start_method'
|
61
|
+
end
|
62
|
+
|
63
|
+
def before_start_method2
|
64
|
+
arguments.first << 'before_start_method2'
|
65
|
+
end
|
66
|
+
|
67
|
+
def after_start_method
|
68
|
+
arguments.first << 'after_start_method'
|
69
|
+
end
|
70
|
+
|
71
|
+
def before_complete_method
|
72
|
+
arguments.first << 'before_complete_method'
|
73
|
+
end
|
74
|
+
|
75
|
+
def before_complete_method2
|
76
|
+
arguments.first << 'before_complete_method2'
|
77
|
+
end
|
78
|
+
|
79
|
+
def after_complete_method
|
80
|
+
arguments.first << 'after_complete_method'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe RocketJob::Plugins::StateMachine do
|
85
|
+
after do
|
86
|
+
@job.destroy if @job && !@job.new_record?
|
87
|
+
end
|
88
|
+
|
89
|
+
describe 'before_start after_start & before_complete after_complete' do
|
90
|
+
it 'runs blocks and functions' do
|
91
|
+
@job = PositivePathJob.new(arguments: [[]])
|
92
|
+
@job.perform_now
|
93
|
+
assert @job.completed?, @job.attributes.ai
|
94
|
+
expected = %w(before_start_block before_start_method before_start2_block before_start_method2 after_start2_block after_start_method after_start_block perform before_complete_block before_complete_method before_complete2_block before_complete_method2 after_complete2_block after_complete_method after_complete_block)
|
95
|
+
assert_equal expected, @job.arguments.first, 'Sequence of before_perform callbacks is incorrect'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
module Plugins
|
4
|
+
# Unit Test for RocketJob::Job
|
5
|
+
class StateMachineTest < Minitest::Test
|
6
|
+
|
7
|
+
class Test
|
8
|
+
include RocketJob::Plugins::Document
|
9
|
+
include RocketJob::Plugins::StateMachine
|
10
|
+
|
11
|
+
key :name
|
12
|
+
key :state
|
13
|
+
validates_presence_of :name, :state
|
14
|
+
|
15
|
+
aasm column: :state do
|
16
|
+
state :pending, initial: true
|
17
|
+
state :enabled
|
18
|
+
|
19
|
+
event :enable do
|
20
|
+
transitions from: :pending, to: :enabled
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe RocketJob::Plugins::StateMachine do
|
26
|
+
before do
|
27
|
+
@doc = Test.new
|
28
|
+
end
|
29
|
+
|
30
|
+
after do
|
31
|
+
@doc.destroy if @doc && !@doc.new_record?
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#aasm_write_state' do
|
35
|
+
it 'raises an exception when a validation fails on create!' do
|
36
|
+
assert_raises MongoMapper::DocumentNotValid do
|
37
|
+
@doc = Test.create!
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'raises an exception when a validation fails on save' do
|
42
|
+
assert_raises MongoMapper::DocumentNotValid do
|
43
|
+
@doc.save!
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'raises an exception when a validation fails on state transition with save' do
|
48
|
+
assert_raises MongoMapper::DocumentNotValid do
|
49
|
+
@doc.enable!
|
50
|
+
end
|
51
|
+
assert @doc.pending?
|
52
|
+
refute @doc.valid?
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'does not raise an exception when a validation fails on state transition without save' do
|
56
|
+
@doc.enable
|
57
|
+
assert @doc.enabled?
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -4,45 +4,12 @@ require 'yaml'
|
|
4
4
|
require 'minitest/autorun'
|
5
5
|
require 'minitest/reporters'
|
6
6
|
require 'minitest/stub_any_instance'
|
7
|
-
require 'rocketjob'
|
8
7
|
require 'awesome_print'
|
9
|
-
require '
|
8
|
+
require 'rocketjob'
|
10
9
|
|
11
|
-
|
12
|
-
# See every test and how long it took
|
13
|
-
MiniTest::Reporters.use! MiniTest::Reporters::SpecReporter.new
|
14
|
-
else
|
15
|
-
# Only show failed tests
|
16
|
-
MiniTest::Reporters.use! MiniTest::Reporters::ProgressReporter.new
|
17
|
-
end
|
10
|
+
MiniTest::Reporters.use! MiniTest::Reporters::SpecReporter.new
|
18
11
|
|
19
12
|
SemanticLogger.add_appender('test.log', &SemanticLogger::Appender::Base.colorized_formatter)
|
20
13
|
SemanticLogger.default_level = :debug
|
21
14
|
|
22
|
-
|
23
|
-
config_file = File.join(File.dirname(__FILE__), 'config', 'mongo.yml')
|
24
|
-
config = YAML.load(ERB.new(File.read(config_file)).result)
|
25
|
-
if config
|
26
|
-
cfg = config['test']
|
27
|
-
options = cfg['options'] || {}
|
28
|
-
options[:logger] = SemanticLogger::DebugAsTraceLogger.new('Mongo')
|
29
|
-
|
30
|
-
MongoMapper.config = cfg
|
31
|
-
MongoMapper.connection = Mongo::MongoClient.from_uri(cfg['uri'], options)
|
32
|
-
MongoMapper.database = MongoMapper.connection.db.name
|
33
|
-
|
34
|
-
# If this environment has a separate Work server
|
35
|
-
if (cfg = config['test_work'])
|
36
|
-
options = cfg['options'] || {}
|
37
|
-
options[:logger] = SemanticLogger::DebugAsTraceLogger.new('MongoWork')
|
38
|
-
RocketJob::Config.mongo_work_connection = Mongo::MongoClient.from_uri(cfg['uri'], options)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
# Test cipher
|
43
|
-
SymmetricEncryption.cipher = SymmetricEncryption::Cipher.new(
|
44
|
-
cipher_name: 'aes-128-cbc',
|
45
|
-
key: '1234567890ABCDEF1234567890ABCDEF',
|
46
|
-
iv: '1234567890ABCDEF',
|
47
|
-
encoding: :base64strict
|
48
|
-
)
|
15
|
+
RocketJob::Config.load!('test', 'test/config/mongo.yml')
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rocketjob
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Reid Morrison
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aasm
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 4.
|
19
|
+
version: '4.3'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 4.
|
26
|
+
version: '4.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: semantic_logger
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '2.
|
33
|
+
version: '2.21'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '2.
|
40
|
+
version: '2.21'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: mongo_ha
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,40 +94,77 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '3.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: concurrent-ruby
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1.0'
|
97
111
|
description: Enterprise Batch Processing System focused on performance, scalability,
|
98
112
|
reliability, and visibility of every job in the system.
|
99
113
|
email:
|
100
114
|
- reidmo@gmail.com
|
101
115
|
executables:
|
102
116
|
- rocketjob
|
117
|
+
- rocketjob_perf
|
103
118
|
extensions: []
|
104
119
|
extra_rdoc_files: []
|
105
120
|
files:
|
121
|
+
- LICENSE.txt
|
106
122
|
- README.md
|
107
123
|
- Rakefile
|
108
124
|
- bin/rocketjob
|
125
|
+
- bin/rocketjob_perf
|
109
126
|
- lib/rocket_job/cli.rb
|
110
|
-
- lib/rocket_job/concerns/singleton.rb
|
111
|
-
- lib/rocket_job/concerns/worker.rb
|
112
127
|
- lib/rocket_job/config.rb
|
113
128
|
- lib/rocket_job/dirmon_entry.rb
|
129
|
+
- lib/rocket_job/extensions/aasm.rb
|
130
|
+
- lib/rocket_job/extensions/mongo.rb
|
114
131
|
- lib/rocket_job/heartbeat.rb
|
115
132
|
- lib/rocket_job/job.rb
|
116
133
|
- lib/rocket_job/job_exception.rb
|
117
134
|
- lib/rocket_job/jobs/dirmon_job.rb
|
135
|
+
- lib/rocket_job/jobs/simple_job.rb
|
136
|
+
- lib/rocket_job/plugins/document.rb
|
137
|
+
- lib/rocket_job/plugins/job/callbacks.rb
|
138
|
+
- lib/rocket_job/plugins/job/defaults.rb
|
139
|
+
- lib/rocket_job/plugins/job/logger.rb
|
140
|
+
- lib/rocket_job/plugins/job/model.rb
|
141
|
+
- lib/rocket_job/plugins/job/persistence.rb
|
142
|
+
- lib/rocket_job/plugins/job/state_machine.rb
|
143
|
+
- lib/rocket_job/plugins/job/worker.rb
|
144
|
+
- lib/rocket_job/plugins/restart.rb
|
145
|
+
- lib/rocket_job/plugins/singleton.rb
|
146
|
+
- lib/rocket_job/plugins/state_machine.rb
|
118
147
|
- lib/rocket_job/version.rb
|
119
148
|
- lib/rocket_job/worker.rb
|
120
149
|
- lib/rocketjob.rb
|
121
150
|
- test/config/mongo.yml
|
151
|
+
- test/config_test.rb
|
122
152
|
- test/dirmon_entry_test.rb
|
123
153
|
- test/dirmon_job_test.rb
|
124
|
-
- test/files/_archive/archived.txt
|
125
154
|
- test/files/text.txt
|
126
155
|
- test/job_test.rb
|
127
|
-
- test/
|
128
|
-
- test/
|
156
|
+
- test/plugins/job/callbacks_test.rb
|
157
|
+
- test/plugins/job/defaults_test.rb
|
158
|
+
- test/plugins/job/logger_test.rb
|
159
|
+
- test/plugins/job/model_test.rb
|
160
|
+
- test/plugins/job/persistence_test.rb
|
161
|
+
- test/plugins/job/state_machine_test.rb
|
162
|
+
- test/plugins/job/worker_test.rb
|
163
|
+
- test/plugins/restart_test.rb
|
164
|
+
- test/plugins/singleton_test.rb
|
165
|
+
- test/plugins/state_machine_event_callbacks_test.rb
|
166
|
+
- test/plugins/state_machine_test.rb
|
129
167
|
- test/test_helper.rb
|
130
|
-
- test/worker_test.rb
|
131
168
|
homepage: http://rocketjob.io
|
132
169
|
licenses:
|
133
170
|
- GPL-3.0
|
@@ -143,23 +180,31 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
143
180
|
version: '0'
|
144
181
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
182
|
requirements:
|
146
|
-
- - "
|
183
|
+
- - ">"
|
147
184
|
- !ruby/object:Gem::Version
|
148
|
-
version:
|
185
|
+
version: 1.3.1
|
149
186
|
requirements: []
|
150
187
|
rubyforge_project:
|
151
|
-
rubygems_version: 2.4.
|
188
|
+
rubygems_version: 2.4.8
|
152
189
|
signing_key:
|
153
190
|
specification_version: 4
|
154
191
|
summary: Enterprise Batch Processing System for Ruby, JRuby, and Rubinius
|
155
192
|
test_files:
|
156
193
|
- test/config/mongo.yml
|
194
|
+
- test/config_test.rb
|
157
195
|
- test/dirmon_entry_test.rb
|
158
196
|
- test/dirmon_job_test.rb
|
159
|
-
- test/files/_archive/archived.txt
|
160
197
|
- test/files/text.txt
|
161
198
|
- test/job_test.rb
|
162
|
-
- test/
|
163
|
-
- test/
|
199
|
+
- test/plugins/job/callbacks_test.rb
|
200
|
+
- test/plugins/job/defaults_test.rb
|
201
|
+
- test/plugins/job/logger_test.rb
|
202
|
+
- test/plugins/job/model_test.rb
|
203
|
+
- test/plugins/job/persistence_test.rb
|
204
|
+
- test/plugins/job/state_machine_test.rb
|
205
|
+
- test/plugins/job/worker_test.rb
|
206
|
+
- test/plugins/restart_test.rb
|
207
|
+
- test/plugins/singleton_test.rb
|
208
|
+
- test/plugins/state_machine_event_callbacks_test.rb
|
209
|
+
- test/plugins/state_machine_test.rb
|
164
210
|
- test/test_helper.rb
|
165
|
-
- test/worker_test.rb
|
@@ -1,33 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
require 'active_support/concern'
|
3
|
-
|
4
|
-
# Worker behavior for a job
|
5
|
-
module RocketJob
|
6
|
-
module Concerns
|
7
|
-
module Singleton
|
8
|
-
extend ActiveSupport::Concern
|
9
|
-
|
10
|
-
included do
|
11
|
-
# Start the single instance of this job
|
12
|
-
#
|
13
|
-
# Returns true if the job was started
|
14
|
-
# Returns false if the job is already running and doe not need to be started
|
15
|
-
def self.start(*args, &block)
|
16
|
-
# Prevent multiple Jobs of the same class from running at the same time
|
17
|
-
return false if where(state: [:running, :queued]).count > 0
|
18
|
-
|
19
|
-
perform_later(*args, &block)
|
20
|
-
true
|
21
|
-
end
|
22
|
-
|
23
|
-
# TODO Make :perform_later, :perform_now, :perform, :now protected/private
|
24
|
-
# class << self
|
25
|
-
# # Ensure that only one instance of the job is running.
|
26
|
-
# protected :perform_later, :perform_now, :perform, :now
|
27
|
-
# end
|
28
|
-
#self.send(:protected, :perform_later)
|
29
|
-
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
@@ -1,214 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
# Worker behavior for a job
|
4
|
-
module RocketJob
|
5
|
-
module Concerns
|
6
|
-
module Worker
|
7
|
-
def self.included(base)
|
8
|
-
base.extend ClassMethods
|
9
|
-
end
|
10
|
-
|
11
|
-
module ClassMethods
|
12
|
-
# Returns [Job] after queue-ing it for processing
|
13
|
-
def later(method, *args, &block)
|
14
|
-
if RocketJob::Config.inline_mode
|
15
|
-
now(method, *args, &block)
|
16
|
-
else
|
17
|
-
job = build(method, *args, &block)
|
18
|
-
job.save!
|
19
|
-
job
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
# Create a job and process it immediately in-line by this thread
|
24
|
-
def now(method, *args, &block)
|
25
|
-
build(method, *args, &block).work_now
|
26
|
-
end
|
27
|
-
|
28
|
-
# Build a Rocket Job instance
|
29
|
-
#
|
30
|
-
# Note:
|
31
|
-
# - #save! must be called on the return job instance if it needs to be
|
32
|
-
# queued for processing.
|
33
|
-
# - If data is uploaded into the job instance before saving, and is then
|
34
|
-
# discarded, call #cleanup! to clear out any partially uploaded data
|
35
|
-
def build(method, *args, &block)
|
36
|
-
job = new(arguments: args, perform_method: method.to_sym)
|
37
|
-
block.call(job) if block
|
38
|
-
job
|
39
|
-
end
|
40
|
-
|
41
|
-
# Method to be performed later
|
42
|
-
def perform_later(*args, &block)
|
43
|
-
later(:perform, *args, &block)
|
44
|
-
end
|
45
|
-
|
46
|
-
# Method to be performed later
|
47
|
-
def perform_build(*args, &block)
|
48
|
-
build(:perform, *args, &block)
|
49
|
-
end
|
50
|
-
|
51
|
-
# Method to be performed now
|
52
|
-
def perform_now(*args, &block)
|
53
|
-
now(:perform, *args, &block)
|
54
|
-
end
|
55
|
-
|
56
|
-
# Returns the next job to work on in priority based order
|
57
|
-
# Returns nil if there are currently no queued jobs, or processing batch jobs
|
58
|
-
# with records that require processing
|
59
|
-
#
|
60
|
-
# Parameters
|
61
|
-
# worker_name [String]
|
62
|
-
# Name of the worker that will be processing this job
|
63
|
-
#
|
64
|
-
# skip_job_ids [Array<BSON::ObjectId>]
|
65
|
-
# Job ids to exclude when looking for the next job
|
66
|
-
#
|
67
|
-
# Note:
|
68
|
-
# If a job is in queued state it will be started
|
69
|
-
def next_job(worker_name, skip_job_ids = nil)
|
70
|
-
query = {
|
71
|
-
'$and' => [
|
72
|
-
{
|
73
|
-
'$or' => [
|
74
|
-
{'state' => 'queued'}, # Jobs
|
75
|
-
{'state' => 'running', 'sub_state' => :processing} # Slices
|
76
|
-
]
|
77
|
-
},
|
78
|
-
{
|
79
|
-
'$or' => [
|
80
|
-
{run_at: {'$exists' => false}},
|
81
|
-
{run_at: {'$lte' => Time.now}}
|
82
|
-
]
|
83
|
-
}
|
84
|
-
]
|
85
|
-
}
|
86
|
-
query['_id'] = {'$nin' => skip_job_ids} if skip_job_ids && skip_job_ids.size > 0
|
87
|
-
|
88
|
-
while (doc = find_and_modify(
|
89
|
-
query: query,
|
90
|
-
sort: [['priority', 'asc'], ['created_at', 'asc']],
|
91
|
-
update: {'$set' => {'worker_name' => worker_name, 'state' => 'running'}}
|
92
|
-
))
|
93
|
-
job = load(doc)
|
94
|
-
if job.running?
|
95
|
-
return job
|
96
|
-
else
|
97
|
-
if job.expired?
|
98
|
-
job.destroy
|
99
|
-
logger.info "Destroyed expired job #{job.class.name}, id:#{job.id}"
|
100
|
-
else
|
101
|
-
# Also update in-memory state and run call-backs
|
102
|
-
job.start
|
103
|
-
job.set(started_at: job.started_at)
|
104
|
-
return job
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
end
|
111
|
-
|
112
|
-
# Works on this job
|
113
|
-
#
|
114
|
-
# Returns [true|false] whether this job should be excluded from the next lookup
|
115
|
-
#
|
116
|
-
# If an exception is thrown the job is marked as failed and the exception
|
117
|
-
# is set in the job itself.
|
118
|
-
#
|
119
|
-
# Thread-safe, can be called by multiple threads at the same time
|
120
|
-
def work(worker)
|
121
|
-
raise(ArgumentError, 'Job must be started before calling #work') unless running?
|
122
|
-
begin
|
123
|
-
# before_perform
|
124
|
-
call_method(perform_method, arguments, event: :before, log_level: log_level)
|
125
|
-
# Allow before perform to explicitly fail this job
|
126
|
-
return unless running?
|
127
|
-
|
128
|
-
# perform
|
129
|
-
ret = call_method(perform_method, arguments, log_level: log_level)
|
130
|
-
if self.collect_output?
|
131
|
-
self.result = (ret.is_a?(Hash) || ret.is_a?(BSON::OrderedHash)) ? ret : {result: ret}
|
132
|
-
end
|
133
|
-
|
134
|
-
# Only run after perform if perform did not explicitly fail the job
|
135
|
-
return unless running?
|
136
|
-
|
137
|
-
# after_perform
|
138
|
-
call_method(perform_method, arguments, event: :after, log_level: log_level)
|
139
|
-
|
140
|
-
new_record? ? complete : complete!
|
141
|
-
rescue StandardError => exc
|
142
|
-
fail(worker.name, exc) if may_fail?
|
143
|
-
logger.error("Exception running #{self.class.name}##{perform_method}", exc)
|
144
|
-
save! unless new_record?
|
145
|
-
raise exc if RocketJob::Config.inline_mode
|
146
|
-
end
|
147
|
-
false
|
148
|
-
end
|
149
|
-
|
150
|
-
# Validates and runs the work on this job now in the current thread
|
151
|
-
# Returns this job once it has finished running
|
152
|
-
def work_now
|
153
|
-
# Call validations
|
154
|
-
if respond_to?(:validate!)
|
155
|
-
validate!
|
156
|
-
elsif invalid?
|
157
|
-
raise(MongoMapper::DocumentNotValid, "Validation failed: #{errors.messages.join(', ')}")
|
158
|
-
end
|
159
|
-
worker = RocketJob::Worker.new(name: 'inline')
|
160
|
-
worker.started
|
161
|
-
start if may_start?
|
162
|
-
while running? && !work(worker)
|
163
|
-
end
|
164
|
-
self
|
165
|
-
end
|
166
|
-
|
167
|
-
protected
|
168
|
-
|
169
|
-
# Calls a method on this job, if it is defined
|
170
|
-
# Adds the event name to the method call if supplied
|
171
|
-
#
|
172
|
-
# Returns [Object] the result of calling the method
|
173
|
-
#
|
174
|
-
# Parameters
|
175
|
-
# method [Symbol]
|
176
|
-
# The method to call on this job
|
177
|
-
#
|
178
|
-
# arguments [Array]
|
179
|
-
# Arguments to pass to the method call
|
180
|
-
#
|
181
|
-
# Options:
|
182
|
-
# event: [Symbol]
|
183
|
-
# Any one of: :before, :after
|
184
|
-
# Default: None, just calls the method itself
|
185
|
-
#
|
186
|
-
# log_level: [Symbol]
|
187
|
-
# Log level to apply to silence logging during the call
|
188
|
-
# Default: nil ( no change )
|
189
|
-
#
|
190
|
-
def call_method(method, arguments, options = {})
|
191
|
-
options = options.dup
|
192
|
-
event = options.delete(:event)
|
193
|
-
log_level = options.delete(:log_level)
|
194
|
-
raise(ArgumentError, "Unknown #{self.class.name}#call_method options: #{options.inspect}") if options.size > 0
|
195
|
-
|
196
|
-
the_method = event.nil? ? method : "#{event}_#{method}".to_sym
|
197
|
-
if respond_to?(the_method)
|
198
|
-
method_name = "#{self.class.name}##{the_method}"
|
199
|
-
logger.info "Start #{method_name}"
|
200
|
-
logger.benchmark_info(
|
201
|
-
"Completed #{method_name}",
|
202
|
-
metric: "rocketjob/#{self.class.name.underscore}/#{the_method}",
|
203
|
-
log_exception: :full,
|
204
|
-
on_exception_level: :error,
|
205
|
-
silence: log_level
|
206
|
-
) do
|
207
|
-
send(the_method, *arguments)
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
end
|
213
|
-
end
|
214
|
-
end
|