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.
- 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
|