rocketjob 5.1.1 → 5.2.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/rocketjob +2 -2
- data/bin/rocketjob_batch_perf +1 -1
- data/bin/rocketjob_perf +1 -1
- data/lib/rocket_job/active_worker.rb +1 -0
- data/lib/rocket_job/batch.rb +16 -17
- data/lib/rocket_job/batch/callbacks.rb +1 -2
- data/lib/rocket_job/batch/io.rb +10 -6
- data/lib/rocket_job/batch/logger.rb +2 -2
- data/lib/rocket_job/batch/lower_priority.rb +2 -2
- data/lib/rocket_job/batch/model.rb +23 -23
- data/lib/rocket_job/batch/performance.rb +19 -21
- data/lib/rocket_job/batch/result.rb +1 -1
- data/lib/rocket_job/batch/results.rb +1 -1
- data/lib/rocket_job/batch/state_machine.rb +5 -6
- data/lib/rocket_job/batch/statistics.rb +10 -8
- data/lib/rocket_job/batch/tabular.rb +2 -2
- data/lib/rocket_job/batch/tabular/input.rb +11 -7
- data/lib/rocket_job/batch/tabular/output.rb +1 -1
- data/lib/rocket_job/batch/throttle.rb +11 -30
- data/lib/rocket_job/batch/{throttle_running_slices.rb → throttle_running_workers.rb} +13 -10
- data/lib/rocket_job/batch/worker.rb +102 -85
- data/lib/rocket_job/cli.rb +57 -54
- data/lib/rocket_job/config.rb +8 -10
- data/lib/rocket_job/dirmon_entry.rb +13 -10
- data/lib/rocket_job/event.rb +16 -16
- data/lib/rocket_job/extensions/mongo/logging.rb +2 -2
- data/lib/rocket_job/extensions/mongoid/clients/options.rb +2 -2
- data/lib/rocket_job/extensions/mongoid/contextual/mongo.rb +4 -2
- data/lib/rocket_job/extensions/mongoid/factory.rb +13 -5
- data/lib/rocket_job/extensions/rocket_job_adapter.rb +2 -1
- data/lib/rocket_job/job_exception.rb +0 -3
- data/lib/rocket_job/jobs/dirmon_job.rb +4 -4
- data/lib/rocket_job/jobs/housekeeping_job.rb +7 -7
- data/lib/rocket_job/jobs/on_demand_batch_job.rb +14 -4
- data/lib/rocket_job/jobs/on_demand_job.rb +3 -3
- data/lib/rocket_job/jobs/performance_job.rb +1 -1
- data/lib/rocket_job/jobs/re_encrypt/relational_job.rb +11 -10
- data/lib/rocket_job/jobs/upload_file_job.rb +9 -5
- data/lib/rocket_job/performance.rb +24 -22
- data/lib/rocket_job/plugins/cron.rb +7 -3
- data/lib/rocket_job/plugins/document.rb +7 -5
- data/lib/rocket_job/plugins/job/callbacks.rb +1 -1
- data/lib/rocket_job/plugins/job/logger.rb +3 -3
- data/lib/rocket_job/plugins/job/model.rb +34 -27
- data/lib/rocket_job/plugins/job/persistence.rb +7 -34
- data/lib/rocket_job/plugins/job/state_machine.rb +5 -4
- data/lib/rocket_job/plugins/job/throttle.rb +12 -28
- data/lib/rocket_job/plugins/job/throttle_running_jobs.rb +2 -2
- data/lib/rocket_job/plugins/job/worker.rb +22 -70
- data/lib/rocket_job/plugins/processing_window.rb +5 -4
- data/lib/rocket_job/plugins/restart.rb +3 -3
- data/lib/rocket_job/plugins/retry.rb +2 -2
- data/lib/rocket_job/plugins/singleton.rb +1 -2
- data/lib/rocket_job/plugins/state_machine.rb +4 -4
- data/lib/rocket_job/plugins/transaction.rb +1 -1
- data/lib/rocket_job/rocket_job.rb +5 -4
- data/lib/rocket_job/server.rb +2 -2
- data/lib/rocket_job/server/model.rb +14 -13
- data/lib/rocket_job/server/state_machine.rb +1 -2
- data/lib/rocket_job/sliced/compressed_slice.rb +4 -4
- data/lib/rocket_job/sliced/encrypted_slice.rb +4 -4
- data/lib/rocket_job/sliced/input.rb +16 -16
- data/lib/rocket_job/sliced/output.rb +2 -2
- data/lib/rocket_job/sliced/slice.rb +43 -20
- data/lib/rocket_job/sliced/slices.rb +14 -11
- data/lib/rocket_job/subscriber.rb +6 -6
- data/lib/rocket_job/subscribers/logger.rb +3 -3
- data/lib/rocket_job/supervisor.rb +12 -12
- data/lib/rocket_job/supervisor/shutdown.rb +7 -7
- data/lib/rocket_job/throttle_definition.rb +37 -0
- data/lib/rocket_job/throttle_definitions.rb +39 -0
- data/lib/rocket_job/version.rb +1 -1
- data/lib/rocket_job/worker.rb +116 -34
- data/lib/rocket_job/worker_pool.rb +6 -6
- data/lib/rocketjob.rb +72 -76
- metadata +16 -18
- data/lib/rocket_job/extensions/mongoid_5/clients/options.rb +0 -38
- data/lib/rocket_job/extensions/mongoid_5/contextual/mongo.rb +0 -64
- data/lib/rocket_job/extensions/mongoid_5/factory.rb +0 -13
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/concern"
|
2
2
|
|
3
3
|
module RocketJob
|
4
4
|
module Plugins
|
@@ -8,27 +8,29 @@ module RocketJob
|
|
8
8
|
include ::Mongoid::Document
|
9
9
|
|
10
10
|
included do
|
11
|
-
store_in client:
|
11
|
+
store_in client: "rocketjob"
|
12
12
|
end
|
13
13
|
|
14
|
+
# rubocop:disable Style/RedundantSort
|
14
15
|
module ClassMethods
|
15
16
|
# Mongoid does not apply ordering, add sort
|
16
17
|
def first
|
17
|
-
all.sort(
|
18
|
+
all.sort("_id" => 1).first
|
18
19
|
end
|
19
20
|
|
20
21
|
# Mongoid does not apply ordering, add sort
|
21
22
|
def last
|
22
|
-
all.sort(
|
23
|
+
all.sort("_id" => -1).first
|
23
24
|
end
|
24
25
|
end
|
26
|
+
# rubocop:enable Style/RedundantSort
|
25
27
|
|
26
28
|
private
|
27
29
|
|
28
30
|
# Apply changes to this document returning the updated document from the database.
|
29
31
|
# Allows other changes to be made on the server that will be loaded.
|
30
32
|
def find_and_update(attrs)
|
31
|
-
doc = collection.find(_id: id).find_one_and_update({
|
33
|
+
doc = collection.find(_id: id).find_one_and_update({"$set" => attrs}, return_document: :after)
|
32
34
|
raise(::Mongoid::Errors::DocumentNotFound.new(self.class, id)) unless doc
|
33
35
|
|
34
36
|
# Clear out keys that are not returned during the reload from MongoDB
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/concern"
|
2
2
|
|
3
3
|
module RocketJob
|
4
4
|
module Plugins
|
@@ -18,9 +18,9 @@ module RocketJob
|
|
18
18
|
# - on_exception_level changes log level from info to error on exception
|
19
19
|
# - silence noisy jobs by raising log level
|
20
20
|
def rocket_job_around_logger(&block)
|
21
|
-
logger.info(
|
21
|
+
logger.info("Start #perform")
|
22
22
|
logger.measure_info(
|
23
|
-
|
23
|
+
"Completed #perform",
|
24
24
|
metric: "#{self.class.name}/perform",
|
25
25
|
log_exception: :full,
|
26
26
|
on_exception_level: :error,
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/concern"
|
2
2
|
|
3
3
|
module RocketJob
|
4
4
|
module Plugins
|
@@ -87,7 +87,7 @@ module RocketJob
|
|
87
87
|
field :percent_complete, type: Integer, default: 0
|
88
88
|
|
89
89
|
# Store the last exception for this job
|
90
|
-
embeds_one :exception, class_name:
|
90
|
+
embeds_one :exception, class_name: "RocketJob::JobException"
|
91
91
|
|
92
92
|
# Store the Hash result from this job if collect_output is true,
|
93
93
|
# and the job returned actually returned a Hash, otherwise nil
|
@@ -110,7 +110,7 @@ module RocketJob
|
|
110
110
|
# job.underscore_name
|
111
111
|
# # => "data_study"
|
112
112
|
def underscore_name
|
113
|
-
@underscore_name ||= name.sub(/Job$/,
|
113
|
+
@underscore_name ||= name.sub(/Job$/, "").underscore
|
114
114
|
end
|
115
115
|
|
116
116
|
# Allow the collective name for this job class to be overridden
|
@@ -125,7 +125,7 @@ module RocketJob
|
|
125
125
|
# job.human_name
|
126
126
|
# # => "Data Study"
|
127
127
|
def human_name
|
128
|
-
@human_name ||= name.sub(/Job$/,
|
128
|
+
@human_name ||= name.sub(/Job$/, "").titleize
|
129
129
|
end
|
130
130
|
|
131
131
|
# Allow the human readable job name for this job class to be overridden
|
@@ -140,7 +140,7 @@ module RocketJob
|
|
140
140
|
# job.collective_name
|
141
141
|
# # => "data_studies"
|
142
142
|
def collective_name
|
143
|
-
@collective_name ||= name.sub(/Job$/,
|
143
|
+
@collective_name ||= name.sub(/Job$/, "").pluralize.underscore
|
144
144
|
end
|
145
145
|
|
146
146
|
# Allow the collective name for this job class to be overridden
|
@@ -155,8 +155,14 @@ module RocketJob
|
|
155
155
|
|
156
156
|
# Scope for queued jobs that can run now
|
157
157
|
# I.e. Queued jobs excluding scheduled jobs
|
158
|
-
|
159
|
-
|
158
|
+
if Mongoid::VERSION.to_f >= 7.1
|
159
|
+
def queued_now
|
160
|
+
queued.and(RocketJob::Job.where(run_at: nil).or(:run_at.lte => Time.now))
|
161
|
+
end
|
162
|
+
else
|
163
|
+
def queued_now
|
164
|
+
queued.or({run_at: nil}, :run_at.lte => Time.now)
|
165
|
+
end
|
160
166
|
end
|
161
167
|
|
162
168
|
# Defines all the fields that are accessible on the Document
|
@@ -193,7 +199,7 @@ module RocketJob
|
|
193
199
|
|
194
200
|
# DEPRECATED
|
195
201
|
def rocket_job
|
196
|
-
warn
|
202
|
+
warn "Replace calls to .rocket_job with calls to set class instance variables. For example: self.priority = 50"
|
197
203
|
yield(self)
|
198
204
|
end
|
199
205
|
|
@@ -276,42 +282,42 @@ module RocketJob
|
|
276
282
|
# Returns [Hash] status of this job
|
277
283
|
def as_json
|
278
284
|
attrs = serializable_hash(methods: %i[seconds duration])
|
279
|
-
attrs.delete(
|
280
|
-
attrs.delete(
|
285
|
+
attrs.delete("result") unless collect_output?
|
286
|
+
attrs.delete("failure_count") unless failure_count.positive?
|
281
287
|
if queued?
|
282
|
-
attrs.delete(
|
283
|
-
attrs.delete(
|
284
|
-
attrs.delete(
|
288
|
+
attrs.delete("started_at")
|
289
|
+
attrs.delete("completed_at")
|
290
|
+
attrs.delete("result")
|
285
291
|
attrs
|
286
292
|
elsif running?
|
287
|
-
attrs.delete(
|
288
|
-
attrs.delete(
|
293
|
+
attrs.delete("completed_at")
|
294
|
+
attrs.delete("result")
|
289
295
|
attrs
|
290
296
|
elsif completed?
|
291
|
-
attrs.delete(
|
297
|
+
attrs.delete("percent_complete")
|
292
298
|
attrs
|
293
299
|
elsif paused?
|
294
|
-
attrs.delete(
|
295
|
-
attrs.delete(
|
300
|
+
attrs.delete("completed_at")
|
301
|
+
attrs.delete("result")
|
296
302
|
# Ensure 'paused_at' appears first in the hash
|
297
|
-
{
|
303
|
+
{"paused_at" => completed_at}.merge(attrs)
|
298
304
|
elsif aborted?
|
299
|
-
attrs.delete(
|
300
|
-
attrs.delete(
|
301
|
-
{
|
305
|
+
attrs.delete("completed_at")
|
306
|
+
attrs.delete("result")
|
307
|
+
{"aborted_at" => completed_at}.merge(attrs)
|
302
308
|
elsif failed?
|
303
|
-
attrs.delete(
|
304
|
-
attrs.delete(
|
305
|
-
{
|
309
|
+
attrs.delete("completed_at")
|
310
|
+
attrs.delete("result")
|
311
|
+
{"failed_at" => completed_at}.merge(attrs)
|
306
312
|
else
|
307
313
|
attrs
|
308
314
|
end
|
309
315
|
end
|
310
316
|
|
311
317
|
# Returns [Hash] the status of this job
|
312
|
-
def status(time_zone =
|
318
|
+
def status(time_zone = "Eastern Time (US & Canada)")
|
313
319
|
h = as_json
|
314
|
-
h.delete(
|
320
|
+
h.delete("seconds")
|
315
321
|
h.dup.each_pair do |k, v|
|
316
322
|
if v.is_a?(Time)
|
317
323
|
h[k] = v.in_time_zone(time_zone).to_s
|
@@ -325,6 +331,7 @@ module RocketJob
|
|
325
331
|
# Returns [Boolean] whether the worker runs on a particular server.
|
326
332
|
def worker_on_server?(server_name)
|
327
333
|
return false unless worker_name.present? && server_name.present?
|
334
|
+
|
328
335
|
worker_name.start_with?(server_name)
|
329
336
|
end
|
330
337
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/concern"
|
2
2
|
|
3
3
|
module RocketJob
|
4
4
|
module Plugins
|
@@ -9,38 +9,10 @@ module RocketJob
|
|
9
9
|
|
10
10
|
included do
|
11
11
|
# Store all job types in this collection
|
12
|
-
store_in collection:
|
12
|
+
store_in collection: "rocket_job.jobs"
|
13
13
|
end
|
14
14
|
|
15
15
|
module ClassMethods
|
16
|
-
# Retrieves the next job to work on in priority based order
|
17
|
-
# and assigns it to this worker
|
18
|
-
#
|
19
|
-
# Returns nil if no jobs are available for processing
|
20
|
-
#
|
21
|
-
# Parameters
|
22
|
-
# worker_name: [String]
|
23
|
-
# Name of the worker that will be processing this job
|
24
|
-
#
|
25
|
-
# filter: [Hash]
|
26
|
-
# Filter to apply to the query.
|
27
|
-
# For example: to exclude jobs from being returned.
|
28
|
-
#
|
29
|
-
# Example:
|
30
|
-
# # Skip any job ids from the job_ids_list
|
31
|
-
# filter = {:id.nin => job_ids_list}
|
32
|
-
# job = RocketJob::Job.rocket_job_retrieve('host:pid:worker', filter)
|
33
|
-
def rocket_job_retrieve(worker_name, filter)
|
34
|
-
SemanticLogger.silence(:info) do
|
35
|
-
scheduled = {'$or' => [{run_at: nil}, {:run_at.lte => Time.now}]}
|
36
|
-
working = {'$or' => [{state: :queued}, {state: :running, sub_state: :processing}]}
|
37
|
-
query = self.and(working, scheduled)
|
38
|
-
query = query.where(filter) unless filter.blank?
|
39
|
-
update = {'$set' => {'worker_name' => worker_name, 'state' => 'running'}}
|
40
|
-
query.sort(priority: 1, _id: 1).find_one_and_update(update, bypass_document_validation: true)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
16
|
# Returns [Hash<String:Integer>] of the number of jobs in each state
|
45
17
|
# Queued jobs are separated into :queued_now and :scheduled
|
46
18
|
# :queued_now are jobs that are awaiting processing and can be processed now.
|
@@ -73,14 +45,14 @@ module RocketJob
|
|
73
45
|
collection.aggregate(
|
74
46
|
[
|
75
47
|
{
|
76
|
-
|
77
|
-
_id:
|
78
|
-
count: {
|
48
|
+
"$group" => {
|
49
|
+
_id: "$state",
|
50
|
+
count: {"$sum" => 1}
|
79
51
|
}
|
80
52
|
}
|
81
53
|
]
|
82
54
|
).each do |result|
|
83
|
-
counts[result[
|
55
|
+
counts[result["_id"].to_sym] = result["count"]
|
84
56
|
end
|
85
57
|
|
86
58
|
# Calculate :queued_now and :scheduled if there are queued jobs
|
@@ -101,6 +73,7 @@ module RocketJob
|
|
101
73
|
# Set in-memory job to complete if `destroy_on_complete` and the job has been destroyed
|
102
74
|
def reload
|
103
75
|
return super unless destroy_on_complete
|
76
|
+
|
104
77
|
begin
|
105
78
|
super
|
106
79
|
rescue ::Mongoid::Errors::DocumentNotFound
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/concern"
|
2
2
|
|
3
3
|
module RocketJob
|
4
4
|
module Plugins
|
@@ -126,7 +126,7 @@ module RocketJob
|
|
126
126
|
exception.worker_name = worker_name
|
127
127
|
else
|
128
128
|
build_exception(
|
129
|
-
class_name:
|
129
|
+
class_name: "RocketJob::JobException",
|
130
130
|
message: exc_or_message,
|
131
131
|
backtrace: [],
|
132
132
|
worker_name: worker_name
|
@@ -134,8 +134,9 @@ module RocketJob
|
|
134
134
|
end
|
135
135
|
end
|
136
136
|
|
137
|
-
def rocket_job_set_started_at
|
138
|
-
self.started_at
|
137
|
+
def rocket_job_set_started_at(worker_name = nil)
|
138
|
+
self.started_at = Time.now
|
139
|
+
self.worker_name = worker_name if worker_name
|
139
140
|
end
|
140
141
|
|
141
142
|
def rocket_job_mark_complete
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/concern"
|
2
2
|
|
3
3
|
module RocketJob
|
4
4
|
module Plugins
|
@@ -30,7 +30,6 @@ module RocketJob
|
|
30
30
|
|
31
31
|
included do
|
32
32
|
class_attribute :rocket_job_throttles
|
33
|
-
self.rocket_job_throttles = []
|
34
33
|
end
|
35
34
|
|
36
35
|
module ClassMethods
|
@@ -40,6 +39,7 @@ module RocketJob
|
|
40
39
|
# method_name: [Symbol]
|
41
40
|
# Name of method to call to evaluate whether a throttle has been exceeded.
|
42
41
|
# Note: Must return true or false.
|
42
|
+
#
|
43
43
|
# filter: [Symbol|Proc]
|
44
44
|
# Name of method to call to return the filter when the throttle has been exceeded.
|
45
45
|
# Or, a block that will return the filter.
|
@@ -47,24 +47,24 @@ module RocketJob
|
|
47
47
|
#
|
48
48
|
# Note: Throttles are executed in the order they are defined.
|
49
49
|
def define_throttle(method_name, filter: :throttle_filter_class)
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
raise(ArgumentError, "Cannot define #{method_name} twice, undefine previous throttle first")
|
55
|
-
end
|
56
|
-
|
57
|
-
self.rocket_job_throttles += [ThrottleDefinition.new(method_name, filter)]
|
50
|
+
# Duplicate to prevent modifying parent class throttles
|
51
|
+
definitions = rocket_job_throttles ? rocket_job_throttles.dup : ThrottleDefinitions.new
|
52
|
+
definitions.add(method_name, filter)
|
53
|
+
self.rocket_job_throttles = definitions
|
58
54
|
end
|
59
55
|
|
60
56
|
# Undefine a previously defined throttle
|
61
57
|
def undefine_throttle(method_name)
|
62
|
-
|
58
|
+
return unless rocket_job_throttles
|
59
|
+
|
60
|
+
definitions = rocket_job_throttles.dup
|
61
|
+
definitions.remove(method_name)
|
62
|
+
self.rocket_job_throttles = definitions
|
63
63
|
end
|
64
64
|
|
65
65
|
# Has a throttle been defined?
|
66
66
|
def throttle?(method_name)
|
67
|
-
rocket_job_throttles
|
67
|
+
rocket_job_throttles&.exist?(method_name)
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
@@ -81,22 +81,6 @@ module RocketJob
|
|
81
81
|
def throttle_filter_id
|
82
82
|
{:id.nin => [id]}
|
83
83
|
end
|
84
|
-
|
85
|
-
private
|
86
|
-
|
87
|
-
ThrottleDefinition = Struct.new(:method_name, :filter)
|
88
|
-
|
89
|
-
# Returns the matching filter, or nil if no throttles were triggered.
|
90
|
-
def rocket_job_evaluate_throttles
|
91
|
-
rocket_job_throttles.each do |throttle|
|
92
|
-
# Throttle exceeded?
|
93
|
-
next unless send(throttle.method_name)
|
94
|
-
logger.debug { "Throttle: #{throttle.method_name} has been exceeded. #{self.class.name}:#{id}" }
|
95
|
-
filter = throttle.filter
|
96
|
-
return filter.is_a?(Proc) ? filter.call(self) : send(filter)
|
97
|
-
end
|
98
|
-
nil
|
99
|
-
end
|
100
84
|
end
|
101
85
|
end
|
102
86
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/concern"
|
2
2
|
|
3
3
|
module RocketJob
|
4
4
|
module Plugins
|
@@ -40,7 +40,7 @@ module RocketJob
|
|
40
40
|
|
41
41
|
# Cannot use this class since it will include instances of parent job classes.
|
42
42
|
RocketJob::Job.with(read: {mode: :primary}) do |conn|
|
43
|
-
conn.running.where(
|
43
|
+
conn.running.where("_type" => self.class.name, :id.ne => id).count >= throttle_running_jobs
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/concern"
|
2
2
|
|
3
3
|
# Worker behavior for a job
|
4
4
|
module RocketJob
|
@@ -23,41 +23,6 @@ module RocketJob
|
|
23
23
|
job
|
24
24
|
end
|
25
25
|
|
26
|
-
# Returns the next job to work on in priority based order
|
27
|
-
# Returns nil if there are currently no queued jobs, or processing batch jobs
|
28
|
-
# with records that require processing
|
29
|
-
#
|
30
|
-
# Parameters
|
31
|
-
# worker_name [String]
|
32
|
-
# Name of the worker that will be processing this job
|
33
|
-
#
|
34
|
-
# skip_job_ids [Array<BSON::ObjectId>]
|
35
|
-
# Job ids to exclude when looking for the next job
|
36
|
-
#
|
37
|
-
# Note:
|
38
|
-
# If a job is in queued state it will be started
|
39
|
-
def rocket_job_next_job(worker_name, filter = {})
|
40
|
-
while (job = rocket_job_retrieve(worker_name, filter))
|
41
|
-
# Batch Job?
|
42
|
-
return job if job.running?
|
43
|
-
|
44
|
-
if job.expired?
|
45
|
-
job.rocket_job_fail_on_exception!(worker_name) { job.destroy }
|
46
|
-
logger.info "Destroyed expired job #{job.class.name}, id:#{job.id}"
|
47
|
-
elsif (new_filter = job.send(:rocket_job_evaluate_throttles))
|
48
|
-
rocket_job_merge_filter(filter, new_filter)
|
49
|
-
# Restore retrieved job so that other workers can process it later
|
50
|
-
job.set(worker_name: nil, state: :queued)
|
51
|
-
else
|
52
|
-
job.worker_name = worker_name
|
53
|
-
job.rocket_job_fail_on_exception!(worker_name) do
|
54
|
-
job.start!
|
55
|
-
end
|
56
|
-
return job if job.running?
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
26
|
# Requeues all jobs that were running on a server that died
|
62
27
|
def requeue_dead_server(server_name)
|
63
28
|
# Need to requeue paused, failed since user may have transitioned job before it finished
|
@@ -67,20 +32,6 @@ module RocketJob
|
|
67
32
|
end
|
68
33
|
end
|
69
34
|
end
|
70
|
-
|
71
|
-
private
|
72
|
-
|
73
|
-
def rocket_job_merge_filter(target, source)
|
74
|
-
source.each_pair do |k, v|
|
75
|
-
target[k] =
|
76
|
-
if (previous = target[k])
|
77
|
-
v.is_a?(Array) ? previous + v : v
|
78
|
-
else
|
79
|
-
v
|
80
|
-
end
|
81
|
-
end
|
82
|
-
target
|
83
|
-
end
|
84
35
|
end
|
85
36
|
|
86
37
|
# Runs the job now in the current thread.
|
@@ -112,38 +63,38 @@ module RocketJob
|
|
112
63
|
#
|
113
64
|
# The job is automatically saved only if an exception is raised in the supplied block.
|
114
65
|
#
|
115
|
-
# worker_name: [String]
|
116
|
-
# Name of the server on which the exception has occurred
|
117
|
-
#
|
118
66
|
# re_raise_exceptions: [true|false]
|
119
67
|
# Re-raise the exception after updating the job
|
120
68
|
# Default: false
|
121
|
-
def
|
122
|
-
|
123
|
-
rescue Exception =>
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
69
|
+
def fail_on_exception!(re_raise_exceptions = false, &block)
|
70
|
+
SemanticLogger.named_tagged(job: id.to_s, &block)
|
71
|
+
rescue Exception => e
|
72
|
+
SemanticLogger.named_tagged(job: id.to_s) do
|
73
|
+
if failed? || !may_fail?
|
74
|
+
self.exception = JobException.from_exception(e)
|
75
|
+
exception.worker_name = worker_name
|
76
|
+
save! unless new_record? || destroyed?
|
77
|
+
elsif new_record? || destroyed?
|
78
|
+
fail(worker_name, e)
|
79
|
+
else
|
80
|
+
fail!(worker_name, e)
|
81
|
+
end
|
82
|
+
raise e if re_raise_exceptions
|
132
83
|
end
|
133
|
-
raise exc if re_raise_exceptions
|
134
84
|
end
|
135
85
|
|
136
86
|
# Works on this job
|
137
87
|
#
|
138
|
-
# Returns [true|false] whether
|
88
|
+
# Returns [true|false] whether any work was performed.
|
139
89
|
#
|
140
90
|
# If an exception is thrown the job is marked as failed and the exception
|
141
91
|
# is set in the job itself.
|
142
92
|
#
|
143
93
|
# Thread-safe, can be called by multiple threads at the same time
|
144
|
-
def rocket_job_work(
|
145
|
-
raise(ArgumentError,
|
146
|
-
|
94
|
+
def rocket_job_work(_worker, re_raise_exceptions = false)
|
95
|
+
raise(ArgumentError, "Job must be started before calling #rocket_job_work") unless running?
|
96
|
+
|
97
|
+
fail_on_exception!(re_raise_exceptions) do
|
147
98
|
if _perform_callbacks.empty?
|
148
99
|
@rocket_job_output = perform
|
149
100
|
else
|
@@ -156,7 +107,7 @@ module RocketJob
|
|
156
107
|
|
157
108
|
if collect_output?
|
158
109
|
# Result must be a Hash, if not put it in a Hash
|
159
|
-
self.result = @rocket_job_output.is_a?(Hash) ? @rocket_job_output : {
|
110
|
+
self.result = @rocket_job_output.is_a?(Hash) ? @rocket_job_output : {"result" => @rocket_job_output}
|
160
111
|
end
|
161
112
|
|
162
113
|
if new_record? || destroyed?
|
@@ -171,6 +122,7 @@ module RocketJob
|
|
171
122
|
# Returns [Hash<String:[Array<ActiveWorker>]>] All servers actively working on this job
|
172
123
|
def rocket_job_active_workers(server_name = nil)
|
173
124
|
return [] if !running? || (server_name && !worker_on_server?(server_name))
|
125
|
+
|
174
126
|
[ActiveWorker.new(worker_name, started_at, self)]
|
175
127
|
end
|
176
128
|
end
|