rocketjob 5.1.1 → 5.2.0.beta1
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/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
@@ -13,8 +13,8 @@ module RocketJob
|
|
13
13
|
#
|
14
14
|
# tabular.render(row)
|
15
15
|
class Tabular
|
16
|
-
autoload :Input,
|
17
|
-
autoload :Output,
|
16
|
+
autoload :Input, "rocket_job/batch/tabular/input"
|
17
|
+
autoload :Output, "rocket_job/batch/tabular/output"
|
18
18
|
|
19
19
|
def initialize(map)
|
20
20
|
@map = map
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/concern"
|
2
2
|
|
3
3
|
module RocketJob
|
4
4
|
module Batch
|
@@ -53,7 +53,7 @@ module RocketJob
|
|
53
53
|
input_stream = stream.nil? ? nil : IOStreams.new(stream)
|
54
54
|
|
55
55
|
if stream && (tabular_input_type == :text)
|
56
|
-
input_stream.option_or_stream(:encode, encoding:
|
56
|
+
input_stream.option_or_stream(:encode, encoding: "UTF-8", cleaner: :printable, replace: "")
|
57
57
|
end
|
58
58
|
|
59
59
|
# If an input header is not required, then we don't extract it'
|
@@ -67,14 +67,14 @@ module RocketJob
|
|
67
67
|
|
68
68
|
case tabular_input_mode
|
69
69
|
when :line
|
70
|
-
parse_header =
|
70
|
+
parse_header = lambda do |line|
|
71
71
|
tabular_input.parse_header(line)
|
72
72
|
tabular_input_cleanse_header
|
73
73
|
self.tabular_input_header = tabular_input.header.columns
|
74
74
|
end
|
75
75
|
super(input_stream, on_first: parse_header, stream_mode: :line, **args, &block)
|
76
76
|
when :array, :row
|
77
|
-
set_header =
|
77
|
+
set_header = lambda do |row|
|
78
78
|
tabular_input.header.columns = row
|
79
79
|
tabular_input_cleanse_header
|
80
80
|
self.tabular_input_header = tabular_input.header.columns
|
@@ -101,19 +101,23 @@ module RocketJob
|
|
101
101
|
end
|
102
102
|
|
103
103
|
def tabular_input_render
|
104
|
-
|
104
|
+
unless tabular_input_header.blank? && tabular_input.header?
|
105
|
+
@rocket_job_input = tabular_input.record_parse(@rocket_job_input)
|
106
|
+
end
|
105
107
|
end
|
106
108
|
|
107
109
|
# Cleanse custom input header if supplied.
|
108
110
|
def tabular_input_cleanse_header
|
109
111
|
ignored_columns = tabular_input.header.cleanse!
|
110
|
-
logger.warn(
|
112
|
+
logger.warn("Stripped out invalid columns from custom header", ignored_columns) unless ignored_columns.empty?
|
111
113
|
|
112
114
|
self.tabular_input_header = tabular_input.header.columns
|
113
115
|
end
|
114
116
|
|
115
117
|
def tabular_input_header_present
|
116
|
-
|
118
|
+
if tabular_input_header.present? || !tabular_input.header? || (tabular_input_mode == :hash || tabular_input_mode == :record)
|
119
|
+
return
|
120
|
+
end
|
117
121
|
|
118
122
|
errors.add(:tabular_input_header, "is required when tabular_input_format is #{tabular_input_format.inspect}")
|
119
123
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/concern"
|
2
2
|
|
3
3
|
module RocketJob
|
4
4
|
module Batch
|
@@ -31,7 +31,6 @@ module RocketJob
|
|
31
31
|
|
32
32
|
included do
|
33
33
|
class_attribute :rocket_job_batch_throttles
|
34
|
-
self.rocket_job_batch_throttles = []
|
35
34
|
end
|
36
35
|
|
37
36
|
module ClassMethods
|
@@ -48,44 +47,26 @@ module RocketJob
|
|
48
47
|
#
|
49
48
|
# Note: Throttles are executed in the order they are defined.
|
50
49
|
def define_batch_throttle(method_name, filter: :throttle_filter_class)
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
raise(ArgumentError, "Cannot define #{method_name} twice, undefine previous throttle first")
|
56
|
-
end
|
57
|
-
|
58
|
-
self.rocket_job_batch_throttles += [ThrottleDefinition.new(method_name, filter)]
|
50
|
+
# Duplicate to prevent modifying parent class throttles
|
51
|
+
definitions = rocket_job_batch_throttles ? rocket_job_batch_throttles.dup : ThrottleDefinitions.new
|
52
|
+
definitions.add(method_name, filter)
|
53
|
+
self.rocket_job_batch_throttles = definitions
|
59
54
|
end
|
60
55
|
|
61
56
|
# Undefine a previously defined throttle
|
62
57
|
def undefine_batch_throttle(method_name)
|
63
|
-
|
58
|
+
return unless rocket_job_batch_throttles
|
59
|
+
|
60
|
+
definitions = rocket_job_batch_throttles.dup
|
61
|
+
definitions.remove(method_name)
|
62
|
+
self.rocket_job_batch_throttles = definitions
|
64
63
|
end
|
65
64
|
|
66
65
|
# Has a throttle been defined?
|
67
66
|
def batch_throttle?(method_name)
|
68
|
-
rocket_job_batch_throttles.
|
67
|
+
rocket_job_batch_throttles.exist?(method_name)
|
69
68
|
end
|
70
69
|
end
|
71
|
-
|
72
|
-
private
|
73
|
-
|
74
|
-
ThrottleDefinition = Struct.new(:method_name, :filter)
|
75
|
-
|
76
|
-
# Returns the matching filter, or nil if no throttles were triggered.
|
77
|
-
def rocket_job_batch_evaluate_throttles(slice)
|
78
|
-
rocket_job_batch_throttles.each do |throttle|
|
79
|
-
throttle_exceeded = method(throttle.method_name).arity == 0 ? send(throttle.method_name) : send(throttle.method_name, slice)
|
80
|
-
next unless throttle_exceeded
|
81
|
-
|
82
|
-
logger.debug { "Batch Throttle: #{throttle.method_name} has been exceeded. #{self.class.name}:#{id}" }
|
83
|
-
filter = throttle.filter
|
84
|
-
return filter.is_a?(Proc) ? filter.call(self) : send(filter)
|
85
|
-
end
|
86
|
-
nil
|
87
|
-
end
|
88
|
-
|
89
70
|
end
|
90
71
|
end
|
91
72
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/concern"
|
2
2
|
|
3
3
|
module RocketJob
|
4
4
|
module Batch
|
@@ -9,7 +9,7 @@ module RocketJob
|
|
9
9
|
# include RocketJob::Batch
|
10
10
|
#
|
11
11
|
# # Maximum number of slices to process at the same time for each running instance.
|
12
|
-
# self.
|
12
|
+
# self.throttle_running_workers = 25
|
13
13
|
#
|
14
14
|
# def perform(record)
|
15
15
|
# # ....
|
@@ -28,28 +28,31 @@ module RocketJob
|
|
28
28
|
# 0 or nil : No limits in place
|
29
29
|
#
|
30
30
|
# Default: nil
|
31
|
-
module
|
31
|
+
module ThrottleRunningWorkers
|
32
32
|
extend ActiveSupport::Concern
|
33
33
|
|
34
34
|
included do
|
35
|
-
field :
|
35
|
+
field :throttle_running_workers, type: Integer, class_attribute: true, user_editable: true, copy_on_restart: true
|
36
36
|
|
37
|
-
validates :
|
37
|
+
validates :throttle_running_workers, numericality: {greater_than_or_equal_to: 0}, allow_nil: true
|
38
38
|
|
39
|
-
define_batch_throttle :
|
39
|
+
define_batch_throttle :throttle_running_workers_exceeded?, filter: :throttle_filter_id
|
40
|
+
|
41
|
+
# Deprecated. For backward compatibility.
|
42
|
+
alias_method :throttle_running_slices, :throttle_running_workers
|
43
|
+
alias_method :throttle_running_slices=, :throttle_running_workers=
|
40
44
|
end
|
41
45
|
|
42
46
|
private
|
43
47
|
|
44
48
|
# Returns [Boolean] whether the throttle for this job has been exceeded
|
45
|
-
def
|
46
|
-
return unless
|
49
|
+
def throttle_running_workers_exceeded?(slice)
|
50
|
+
return unless throttle_running_workers&.positive?
|
47
51
|
|
48
52
|
input.running.with(read: {mode: :primary}) do |conn|
|
49
|
-
conn.where(:id.ne => slice.id).count >=
|
53
|
+
conn.where(:id.ne => slice.id).count >= throttle_running_workers
|
50
54
|
end
|
51
55
|
end
|
52
|
-
|
53
56
|
end
|
54
57
|
end
|
55
58
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "active_support/concern"
|
2
2
|
|
3
3
|
module RocketJob
|
4
4
|
module Batch
|
@@ -16,10 +16,10 @@ module RocketJob
|
|
16
16
|
|
17
17
|
# Processes records in each available slice for this job. Slices are processed
|
18
18
|
# one at a time to allow for concurrent calls to this method to increase
|
19
|
-
# throughput. Processing will continue until there are no more
|
19
|
+
# throughput. Processing will continue until there are no more slices available
|
20
20
|
# for this job.
|
21
21
|
#
|
22
|
-
# Returns [true|false] whether
|
22
|
+
# Returns [true|false] whether any work was performed.
|
23
23
|
#
|
24
24
|
# Slices are destroyed after their records are successfully processed
|
25
25
|
#
|
@@ -33,36 +33,34 @@ module RocketJob
|
|
33
33
|
# Mongo connection failure occurs.
|
34
34
|
#
|
35
35
|
# Thread-safe, can be called by multiple threads at the same time
|
36
|
-
def rocket_job_work(worker, re_raise_exceptions = false
|
37
|
-
raise
|
36
|
+
def rocket_job_work(worker, re_raise_exceptions = false)
|
37
|
+
raise "Job must be started before calling #rocket_job_work" unless running?
|
38
|
+
|
38
39
|
start_time = Time.now
|
39
40
|
if sub_state != :processing
|
40
|
-
|
41
|
+
fail_on_exception!(re_raise_exceptions) { rocket_job_batch_callbacks(worker) }
|
41
42
|
return false unless running?
|
42
43
|
end
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
slice.
|
50
|
-
|
45
|
+
SemanticLogger.named_tagged(job: id.to_s) do
|
46
|
+
until worker.shutdown?
|
47
|
+
if slice = input.next_slice(worker.name)
|
48
|
+
# Grab a slice before checking the throttle to reduce concurrency race condition.
|
49
|
+
return true if slice.fail_on_exception!(re_raise_exceptions) { rocket_job_batch_throttled?(slice, worker) }
|
50
|
+
next if slice.failed?
|
51
|
+
|
52
|
+
slice.fail_on_exception!(re_raise_exceptions) { rocket_job_process_slice(slice) }
|
53
|
+
elsif record_count && rocket_job_batch_complete?(worker.name)
|
54
|
+
return false
|
55
|
+
else
|
56
|
+
logger.debug "No more work available for this job"
|
57
|
+
worker.add_to_current_filter(throttle_filter_id)
|
51
58
|
return true
|
52
59
|
end
|
53
60
|
|
54
|
-
|
55
|
-
|
56
|
-
end
|
57
|
-
else
|
58
|
-
break if record_count && rocket_job_batch_complete?(worker.name)
|
59
|
-
logger.debug 'No more work available for this job'
|
60
|
-
self.class.send(:rocket_job_merge_filter, filter, throttle_filter_id)
|
61
|
-
return true
|
61
|
+
# Allow new jobs with a higher priority to interrupt this job
|
62
|
+
break if (Time.now - start_time) >= Config.re_check_seconds
|
62
63
|
end
|
63
|
-
|
64
|
-
# Allow new jobs with a higher priority to interrupt this job
|
65
|
-
break if (Time.now - start_time) >= Config.re_check_seconds
|
66
64
|
end
|
67
65
|
false
|
68
66
|
end
|
@@ -76,27 +74,26 @@ module RocketJob
|
|
76
74
|
#
|
77
75
|
# Note: The slice will be removed from processing when this method completes
|
78
76
|
def work_first_slice(&block)
|
79
|
-
raise
|
80
|
-
|
77
|
+
raise "#work_first_slice can only be called from within before_batch callbacks" unless sub_state == :before
|
78
|
+
|
79
|
+
# TODO: Make these settings configurable
|
81
80
|
count = 0
|
82
81
|
wait_seconds = 5
|
83
|
-
while
|
82
|
+
while input.first.nil?
|
84
83
|
break if count > 10
|
84
|
+
|
85
85
|
logger.info "First slice has not arrived yet, sleeping for #{wait_seconds} seconds"
|
86
86
|
sleep wait_seconds
|
87
87
|
count += 1
|
88
88
|
end
|
89
89
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
# No records processed
|
98
|
-
0
|
99
|
-
end
|
90
|
+
slice = input.first
|
91
|
+
# No records processed
|
92
|
+
return 0 unless slice
|
93
|
+
|
94
|
+
# TODO: Persist that the first slice is being processed by this worker
|
95
|
+
slice.start
|
96
|
+
rocket_job_process_slice(slice, &block)
|
100
97
|
end
|
101
98
|
|
102
99
|
# Returns [Array<ActiveWorker>] All workers actively working on this job
|
@@ -119,50 +116,73 @@ module RocketJob
|
|
119
116
|
|
120
117
|
private
|
121
118
|
|
119
|
+
def rocket_job_batch_throttled?(slice, worker)
|
120
|
+
filter = self.class.rocket_job_batch_throttles.matching_filter(self, slice)
|
121
|
+
return false unless filter
|
122
|
+
|
123
|
+
# Restore retrieved slice so that other workers can process it later.
|
124
|
+
slice.set(worker_name: nil, state: :queued, started_at: nil)
|
125
|
+
worker.add_to_current_filter(filter)
|
126
|
+
true
|
127
|
+
end
|
128
|
+
|
122
129
|
# Process a single slice from Mongo
|
123
130
|
# Once the slice has been successfully processed it will be removed from the input collection
|
124
131
|
# Returns [Integer] the number of records successfully processed
|
125
|
-
def rocket_job_process_slice(slice
|
126
|
-
|
132
|
+
def rocket_job_process_slice(slice)
|
133
|
+
# TODO: Skip records already processed
|
127
134
|
@rocket_job_record_number = slice.first_record_number || 0
|
128
135
|
@rocket_job_slice = slice
|
129
|
-
|
136
|
+
|
137
|
+
processed_records = 0
|
138
|
+
run_callbacks(:slice) do
|
139
|
+
# Allow before_slice callbacks to fail, complete or abort this slice.
|
140
|
+
return 0 unless running?
|
141
|
+
|
130
142
|
RocketJob::Sliced::Writer::Output.collect(self, slice) do |writer|
|
131
143
|
slice.each do |record|
|
132
|
-
slice_record_number += 1
|
133
144
|
SemanticLogger.named_tagged(record: @rocket_job_record_number) do
|
134
|
-
|
135
|
-
|
136
|
-
else
|
137
|
-
# Allows @rocket_job_input to be modified by before/around callbacks
|
138
|
-
@rocket_job_input = record
|
139
|
-
# Allow callbacks to fail, complete or abort the job
|
140
|
-
if running?
|
141
|
-
if block_given?
|
142
|
-
run_callbacks(:perform) { @rocket_job_output = yield(@rocket_job_input) }
|
143
|
-
else
|
144
|
-
# Allows @rocket_job_output to be modified by after/around callbacks
|
145
|
-
run_callbacks(:perform) { @rocket_job_output = perform(@rocket_job_input) }
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
writer << @rocket_job_output
|
145
|
+
writer << rocket_job_batch_perform(slice, record)
|
146
|
+
processed_records += 1
|
150
147
|
end
|
151
|
-
# JRuby
|
148
|
+
# JRuby thinks self.rocket_job_record_number= is private and cannot be accessed
|
152
149
|
@rocket_job_record_number += 1
|
153
150
|
end
|
154
151
|
end
|
155
|
-
@
|
152
|
+
@rocket_job_slice = nil
|
153
|
+
@rocket_job_record_number = nil
|
156
154
|
end
|
157
155
|
|
158
156
|
# On successful completion remove the slice from the input queue
|
159
|
-
# TODO
|
157
|
+
# TODO: Add option to complete slice instead of destroying it to retain input data.
|
160
158
|
slice.destroy
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
159
|
+
processed_records
|
160
|
+
end
|
161
|
+
|
162
|
+
# Perform a single record within the current slice.
|
163
|
+
def rocket_job_batch_perform(slice, record)
|
164
|
+
slice.processing_record_number ||= 0
|
165
|
+
slice.processing_record_number += 1
|
166
|
+
|
167
|
+
return block_given? ? yield(record) : perform(record) if _perform_callbacks.empty?
|
168
|
+
|
169
|
+
# @rocket_job_input and @rocket_job_output can be modified by before/around callbacks
|
170
|
+
@rocket_job_input = record
|
171
|
+
@rocket_job_output = nil
|
172
|
+
|
173
|
+
run_callbacks(:perform) do
|
174
|
+
@rocket_job_output =
|
175
|
+
if block_given?
|
176
|
+
yield(@rocket_job_input)
|
177
|
+
else
|
178
|
+
perform(@rocket_job_input)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
@rocket_job_input = nil
|
183
|
+
result = @rocket_job_output
|
184
|
+
@rocket_job_output = nil
|
185
|
+
result
|
166
186
|
end
|
167
187
|
|
168
188
|
# Checks for completion and runs after_batch if defined
|
@@ -174,7 +194,7 @@ module RocketJob
|
|
174
194
|
# Only failed slices left?
|
175
195
|
input_count = input.count
|
176
196
|
failed_count = input.failed.count
|
177
|
-
if
|
197
|
+
if failed_count.positive? && (input_count == failed_count)
|
178
198
|
# Reload to pull in any counters or other data that was modified.
|
179
199
|
reload unless new_record?
|
180
200
|
if may_fail?
|
@@ -185,9 +205,9 @@ module RocketJob
|
|
185
205
|
result = self.class.with(write: {w: 1}) do |query|
|
186
206
|
query.
|
187
207
|
where(id: id, state: :running, sub_state: :processing).
|
188
|
-
update({
|
208
|
+
update({"$set" => {state: :failed, worker_name: worker_name}})
|
189
209
|
end
|
190
|
-
fail_job = false unless result.modified_count
|
210
|
+
fail_job = false unless result.modified_count.positive?
|
191
211
|
end
|
192
212
|
if fail_job
|
193
213
|
message = "#{failed_count} slices failed to process"
|
@@ -199,7 +219,7 @@ module RocketJob
|
|
199
219
|
end
|
200
220
|
|
201
221
|
# Any work left?
|
202
|
-
return false if input_count
|
222
|
+
return false if input_count.positive?
|
203
223
|
|
204
224
|
# If the job was not saved to the queue, do not save any changes
|
205
225
|
if new_record?
|
@@ -212,12 +232,12 @@ module RocketJob
|
|
212
232
|
result = self.class.with(write: {w: 1}) do |query|
|
213
233
|
query.
|
214
234
|
where(id: id, state: :running, sub_state: :processing).
|
215
|
-
update(
|
235
|
+
update("$set" => {sub_state: :after, worker_name: worker_name})
|
216
236
|
end
|
217
237
|
|
218
238
|
# Reload to pull in any counters or other data that was modified.
|
219
239
|
reload
|
220
|
-
if result.modified_count
|
240
|
+
if result.modified_count.positive?
|
221
241
|
rocket_job_batch_run_after_callbacks(false)
|
222
242
|
else
|
223
243
|
# Repeat cleanup in case this worker was still running when the job was aborted
|
@@ -233,7 +253,7 @@ module RocketJob
|
|
233
253
|
self.sub_state = :before
|
234
254
|
save! unless new_record? || destroyed?
|
235
255
|
logger.measure_info(
|
236
|
-
|
256
|
+
"before_batch",
|
237
257
|
metric: "#{self.class.name}/before_batch",
|
238
258
|
log_exception: :full,
|
239
259
|
on_exception_level: :error,
|
@@ -253,7 +273,7 @@ module RocketJob
|
|
253
273
|
self.sub_state = :after
|
254
274
|
save! if save_before && !new_record? && !destroyed?
|
255
275
|
logger.measure_info(
|
256
|
-
|
276
|
+
"after_batch",
|
257
277
|
metric: "#{self.class.name}/after_batch",
|
258
278
|
log_exception: :full,
|
259
279
|
on_exception_level: :error,
|
@@ -269,20 +289,17 @@ module RocketJob
|
|
269
289
|
end
|
270
290
|
end
|
271
291
|
|
272
|
-
#
|
273
|
-
def
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
rocket_job_batch_run_after_callbacks
|
282
|
-
end
|
292
|
+
# Run Batch before and after callbacks
|
293
|
+
def rocket_job_batch_callbacks(worker)
|
294
|
+
# If this is the first worker to pickup this job
|
295
|
+
if sub_state == :before
|
296
|
+
rocket_job_batch_run_before_callbacks
|
297
|
+
# Check for 0 record jobs
|
298
|
+
rocket_job_batch_complete?(worker.name) if running?
|
299
|
+
elsif sub_state == :after
|
300
|
+
rocket_job_batch_run_after_callbacks
|
283
301
|
end
|
284
302
|
end
|
285
|
-
|
286
303
|
end
|
287
304
|
end
|
288
305
|
end
|