rocketjob 5.4.0.beta2 → 6.0.0.rc3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +149 -5
- data/bin/rocketjob_batch_perf +1 -1
- data/bin/rocketjob_perf +1 -1
- data/lib/rocket_job/batch.rb +3 -1
- data/lib/rocket_job/batch/categories.rb +341 -0
- data/lib/rocket_job/batch/io.rb +128 -60
- data/lib/rocket_job/batch/model.rb +20 -68
- data/lib/rocket_job/batch/performance.rb +19 -7
- data/lib/rocket_job/batch/statistics.rb +34 -12
- data/lib/rocket_job/batch/tabular.rb +2 -0
- data/lib/rocket_job/batch/tabular/input.rb +8 -6
- data/lib/rocket_job/batch/tabular/output.rb +4 -2
- data/lib/rocket_job/batch/throttle_running_workers.rb +8 -17
- data/lib/rocket_job/batch/worker.rb +27 -24
- data/lib/rocket_job/category/base.rb +78 -0
- data/lib/rocket_job/category/input.rb +110 -0
- data/lib/rocket_job/category/output.rb +25 -0
- data/lib/rocket_job/cli.rb +25 -17
- data/lib/rocket_job/dirmon_entry.rb +22 -12
- data/lib/rocket_job/event.rb +1 -1
- data/lib/rocket_job/extensions/iostreams/path.rb +32 -0
- data/lib/rocket_job/extensions/mongoid/contextual/mongo.rb +2 -2
- data/lib/rocket_job/extensions/mongoid/factory.rb +4 -12
- data/lib/rocket_job/extensions/mongoid/stringified_symbol.rb +50 -0
- data/lib/rocket_job/extensions/psych/yaml_tree.rb +8 -0
- data/lib/rocket_job/extensions/rocket_job_adapter.rb +2 -2
- data/lib/rocket_job/jobs/conversion_job.rb +39 -0
- data/lib/rocket_job/jobs/dirmon_job.rb +2 -2
- data/lib/rocket_job/jobs/housekeeping_job.rb +7 -7
- data/lib/rocket_job/jobs/on_demand_batch_job.rb +17 -6
- data/lib/rocket_job/jobs/on_demand_job.rb +1 -2
- data/lib/rocket_job/jobs/performance_job.rb +3 -1
- data/lib/rocket_job/jobs/re_encrypt/relational_job.rb +103 -96
- data/lib/rocket_job/jobs/upload_file_job.rb +44 -8
- data/lib/rocket_job/lookup_collection.rb +69 -0
- data/lib/rocket_job/plugins/job/model.rb +25 -50
- data/lib/rocket_job/plugins/job/throttle.rb +2 -2
- data/lib/rocket_job/plugins/job/throttle_running_jobs.rb +12 -4
- data/lib/rocket_job/plugins/job/worker.rb +2 -7
- data/lib/rocket_job/plugins/restart.rb +12 -5
- data/lib/rocket_job/plugins/state_machine.rb +2 -1
- data/lib/rocket_job/plugins/throttle_dependent_jobs.rb +38 -0
- data/lib/rocket_job/ractor_worker.rb +42 -0
- data/lib/rocket_job/server/model.rb +1 -1
- data/lib/rocket_job/sliced.rb +15 -70
- data/lib/rocket_job/sliced/bzip2_output_slice.rb +1 -1
- data/lib/rocket_job/sliced/input.rb +1 -1
- data/lib/rocket_job/sliced/slice.rb +5 -13
- data/lib/rocket_job/sliced/slices.rb +14 -2
- data/lib/rocket_job/sliced/writer/output.rb +33 -45
- data/lib/rocket_job/subscribers/server.rb +1 -1
- data/lib/rocket_job/thread_worker.rb +46 -0
- data/lib/rocket_job/throttle_definitions.rb +7 -1
- data/lib/rocket_job/version.rb +1 -1
- data/lib/rocket_job/worker.rb +21 -55
- data/lib/rocket_job/worker_pool.rb +5 -7
- data/lib/rocketjob.rb +53 -43
- metadata +36 -26
- data/lib/rocket_job/extensions/mongoid/remove_warnings.rb +0 -12
- data/lib/rocket_job/jobs/on_demand_batch_tabular_job.rb +0 -28
@@ -0,0 +1,25 @@
|
|
1
|
+
module RocketJob
|
2
|
+
module Category
|
3
|
+
# Define the layout for each category of input or output data
|
4
|
+
class Output
|
5
|
+
include SemanticLogger::Loggable
|
6
|
+
include Plugins::Document
|
7
|
+
include Category::Base
|
8
|
+
|
9
|
+
embedded_in :job, class_name: "RocketJob::Job", inverse_of: :output_categories
|
10
|
+
|
11
|
+
# Whether to skip nil values returned from the `perform` method.
|
12
|
+
# true: save nil values to the output categories.
|
13
|
+
# false: do not save nil values to the output categories.
|
14
|
+
field :nils, type: ::Mongoid::Boolean, default: false
|
15
|
+
|
16
|
+
# Renders [String] the header line.
|
17
|
+
# Returns [nil] if no header is needed.
|
18
|
+
def render_header
|
19
|
+
return if !tabular? || !tabular.requires_header?
|
20
|
+
|
21
|
+
tabular.render_header
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/rocket_job/cli.rb
CHANGED
@@ -233,24 +233,23 @@ module RocketJob
|
|
233
233
|
|
234
234
|
# Parse command line options placing results in the corresponding instance variables
|
235
235
|
def parse(argv)
|
236
|
-
parser
|
236
|
+
parser = OptionParser.new do |o|
|
237
237
|
o.on("-n", "--name NAME", "Unique Name of this server (Default: host_name:PID)") do |arg|
|
238
238
|
Config.name = arg
|
239
239
|
end
|
240
240
|
o.on("-w", "--workers COUNT", "Number of workers (threads) to start") do |arg|
|
241
241
|
@max_workers = arg.to_i
|
242
242
|
end
|
243
|
-
o.on("--include REGEXP",
|
243
|
+
o.on("--include REGEXP",
|
244
|
+
'Limit this server to only those job classes that match this regular expression (case-insensitive). Example: "DirmonJob|WeeklyReportJob"') do |arg|
|
244
245
|
@include_filter = Regexp.new(arg, true)
|
245
246
|
end
|
246
|
-
o.on("-
|
247
|
-
|
248
|
-
@include_filter = Regexp.new(arg, true)
|
249
|
-
end
|
250
|
-
o.on("-E", "--exclude REGEXP", 'Prevent this server from working on any job classes that match this regular expression (case-insensitive). Example: "DirmonJob|WeeklyReportJob"') do |arg|
|
247
|
+
o.on("-E", "--exclude REGEXP",
|
248
|
+
'Prevent this server from working on any job classes that match this regular expression (case-insensitive). Example: "DirmonJob|WeeklyReportJob"') do |arg|
|
251
249
|
@exclude_filter = Regexp.new(arg, true)
|
252
250
|
end
|
253
|
-
o.on("-W", "--where JSON",
|
251
|
+
o.on("-W", "--where JSON",
|
252
|
+
"Limit this server instance to the supplied mongo query filter. Supply as a string in JSON format. Example: '{\"priority\":{\"$lte\":25}}'") do |arg|
|
254
253
|
@where_filter = JSON.parse(arg)
|
255
254
|
end
|
256
255
|
o.on("-q", "--quiet", "Do not write to stdout, only to logfile. Necessary when running as a daemon") do
|
@@ -259,7 +258,8 @@ module RocketJob
|
|
259
258
|
o.on("-d", "--dir DIR", "Directory containing Rails app, if not current directory") do |arg|
|
260
259
|
@directory = arg
|
261
260
|
end
|
262
|
-
o.on("-e", "--environment ENVIRONMENT",
|
261
|
+
o.on("-e", "--environment ENVIRONMENT",
|
262
|
+
"The environment to run the app on (Default: RAILS_ENV || RACK_ENV || development)") do |arg|
|
263
263
|
@environment = arg
|
264
264
|
end
|
265
265
|
o.on("-l", "--log_level trace|debug|info|warn|error|fatal", "The log level to use") do |arg|
|
@@ -274,38 +274,46 @@ module RocketJob
|
|
274
274
|
o.on("-m", "--mongo MONGO_CONFIG_FILE_NAME", "Path and filename of config file. Default: config/mongoid.yml") do |arg|
|
275
275
|
@mongo_config = arg
|
276
276
|
end
|
277
|
-
o.on("-s", "--symmetric-encryption SYMMETRIC_ENCRYPTION_CONFIG_FILE_NAME",
|
277
|
+
o.on("-s", "--symmetric-encryption SYMMETRIC_ENCRYPTION_CONFIG_FILE_NAME",
|
278
|
+
"Path and filename of Symmetric Encryption config file. Default: config/symmetric-encryption.yml") do |arg|
|
278
279
|
@symmetric_encryption_config = arg
|
279
280
|
end
|
280
|
-
o.on("--list [FILTER]",
|
281
|
+
o.on("--list [FILTER]",
|
282
|
+
"List active servers. Supply either an exact server name or a partial name as a filter.") do |filter|
|
281
283
|
@quiet = true
|
282
284
|
@server = false
|
283
285
|
@list_servers = filter || :all
|
284
286
|
end
|
285
|
-
o.on("--refresh [SECONDS]",
|
287
|
+
o.on("--refresh [SECONDS]",
|
288
|
+
"When listing active servers, update the list by this number of seconds. Defaults to every 1 second.") do |seconds|
|
286
289
|
@refresh = (seconds || 1).to_s.to_f
|
287
290
|
end
|
288
|
-
o.on("--stop [SERVER_NAME]",
|
291
|
+
o.on("--stop [SERVER_NAME]",
|
292
|
+
"Send event to stop a server once all in-process workers have completed. Optionally supply the complete or partial name of the server(s) to stop. Default: All servers.") do |server_name|
|
289
293
|
@quiet = true
|
290
294
|
@server = false
|
291
295
|
@stop_server = server_name || :all
|
292
296
|
end
|
293
|
-
o.on("--kill [SERVER_NAME]",
|
297
|
+
o.on("--kill [SERVER_NAME]",
|
298
|
+
"Send event to hard kill a server. Optionally supply the complete or partial name of the server(s) to kill. Default: All servers.") do |server_name|
|
294
299
|
@quiet = true
|
295
300
|
@server = false
|
296
301
|
@kill_server = server_name || :all
|
297
302
|
end
|
298
|
-
o.on("--pause [SERVER_NAME]",
|
303
|
+
o.on("--pause [SERVER_NAME]",
|
304
|
+
"Send event to pause a server. Optionally supply the complete or partial name of the server(s) to pause. Default: All servers.") do |server_name|
|
299
305
|
@quiet = true
|
300
306
|
@server = false
|
301
307
|
@pause_server = server_name || :all
|
302
308
|
end
|
303
|
-
o.on("--resume [SERVER_NAME]",
|
309
|
+
o.on("--resume [SERVER_NAME]",
|
310
|
+
"Send event to resume a server. Optionally supply the complete or partial name of the server(s) to resume. Default: All servers.") do |server_name|
|
304
311
|
@quiet = true
|
305
312
|
@server = false
|
306
313
|
@resume_server = server_name || :all
|
307
314
|
end
|
308
|
-
o.on("--dump [SERVER_NAME]",
|
315
|
+
o.on("--dump [SERVER_NAME]",
|
316
|
+
"Send event for a server to send a worker thread dump to its log file. Optionally supply the complete or partial name of the server(s). Default: All servers.") do |server_name|
|
309
317
|
@quiet = true
|
310
318
|
@server = false
|
311
319
|
@thread_dump = server_name || :all
|
@@ -57,20 +57,12 @@ module RocketJob
|
|
57
57
|
# If this DirmonEntry is in the failed state, exception contains the cause
|
58
58
|
embeds_one :exception, class_name: "RocketJob::JobException"
|
59
59
|
|
60
|
-
# The maximum number of files that should ever match during a single poll of the pattern.
|
61
|
-
#
|
62
|
-
# Too many files could be as a result of an invalid pattern specification.
|
63
|
-
# Exceeding this number will result in an exception being logged in a failed Dirmon instance.
|
64
|
-
# Dirmon processing will continue with new instances.
|
65
|
-
# TODO: Implement max_hits
|
66
|
-
# field :max_hits, type: Integer, default: 100
|
67
|
-
|
68
60
|
#
|
69
61
|
# Read-only attributes
|
70
62
|
#
|
71
63
|
|
72
64
|
# Current state, as set by the state machine. Do not modify directly.
|
73
|
-
field :state, type:
|
65
|
+
field :state, type: Mongoid::StringifiedSymbol, default: :pending
|
74
66
|
|
75
67
|
# Unique index on pattern to help prevent two entries from scanning the same files
|
76
68
|
index({pattern: 1}, background: true, unique: true)
|
@@ -240,7 +232,7 @@ module RocketJob
|
|
240
232
|
job_class_name: job_class_name,
|
241
233
|
properties: properties,
|
242
234
|
description: "#{name}: #{iopath.basename}",
|
243
|
-
upload_file_name: archive_path
|
235
|
+
upload_file_name: archive_path,
|
244
236
|
original_file_name: iopath.to_s,
|
245
237
|
job_id: job_id
|
246
238
|
)
|
@@ -249,7 +241,7 @@ module RocketJob
|
|
249
241
|
message: "Created RocketJob::Jobs::UploadFileJob",
|
250
242
|
payload: {
|
251
243
|
dirmon_entry_name: name,
|
252
|
-
upload_file_name: archive_path
|
244
|
+
upload_file_name: archive_path,
|
253
245
|
original_file_name: iopath.to_s,
|
254
246
|
job_class_name: job_class_name,
|
255
247
|
job_id: job_id.to_s,
|
@@ -295,7 +287,25 @@ module RocketJob
|
|
295
287
|
properties.each_pair do |k, _v|
|
296
288
|
next if klass.public_method_defined?("#{k}=".to_sym)
|
297
289
|
|
298
|
-
|
290
|
+
if %i[output_categories input_categories].include?(k)
|
291
|
+
category_class = k == :input_categories ? RocketJob::Category::Input : RocketJob::Category::Output
|
292
|
+
properties[k].each do |category|
|
293
|
+
category.each_pair do |key, _value|
|
294
|
+
next if category_class.public_method_defined?("#{key}=".to_sym)
|
295
|
+
|
296
|
+
errors.add(
|
297
|
+
:properties,
|
298
|
+
"Unknown Property in #{k}: Attempted to set a value for #{key}.#{k} which is not allowed on the job #{job_class_name}"
|
299
|
+
)
|
300
|
+
end
|
301
|
+
end
|
302
|
+
next
|
303
|
+
end
|
304
|
+
|
305
|
+
errors.add(
|
306
|
+
:properties,
|
307
|
+
"Unknown Property: Attempted to set a value for #{k.inspect} which is not allowed on the job #{job_class_name}"
|
308
|
+
)
|
299
309
|
end
|
300
310
|
end
|
301
311
|
end
|
data/lib/rocket_job/event.rb
CHANGED
@@ -0,0 +1,32 @@
|
|
1
|
+
module IOStreams
|
2
|
+
class Path
|
3
|
+
# Converts an object of this instance into a database friendly value.
|
4
|
+
def mongoize
|
5
|
+
to_s
|
6
|
+
end
|
7
|
+
|
8
|
+
# Get the object as it was stored in the database, and instantiate
|
9
|
+
# this custom class from it.
|
10
|
+
def self.demongoize(object)
|
11
|
+
return if object.nil?
|
12
|
+
|
13
|
+
IOStreams.new(object)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Takes any possible object and converts it to how it would be
|
17
|
+
# stored in the database.
|
18
|
+
def self.mongoize(object)
|
19
|
+
return if object.nil?
|
20
|
+
|
21
|
+
object.to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
# Converts the object that was supplied to a criteria and converts it
|
25
|
+
# into a database friendly form.
|
26
|
+
def self.evolve(object)
|
27
|
+
return if object.nil?
|
28
|
+
|
29
|
+
object.to_s
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -4,8 +4,8 @@ module Mongoid
|
|
4
4
|
class Mongo
|
5
5
|
def initialize(criteria)
|
6
6
|
@criteria = criteria
|
7
|
-
@klass
|
8
|
-
@cache
|
7
|
+
@klass = criteria.klass
|
8
|
+
@cache = criteria.options[:cache]
|
9
9
|
# Only line changed is here, get collection name from criteria, not @klass
|
10
10
|
# @collection = @klass.collection
|
11
11
|
@collection = criteria.collection
|
@@ -3,18 +3,10 @@ require "mongoid/factory"
|
|
3
3
|
module RocketJob
|
4
4
|
# Don't convert to Mongoid::Factory since it conflicts with Mongoid use.
|
5
5
|
module MongoidFactory
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
obj
|
11
|
-
end
|
12
|
-
else
|
13
|
-
def from_db(klass, attributes = nil, criteria = nil)
|
14
|
-
obj = super(klass, attributes, criteria)
|
15
|
-
obj.collection_name = criteria.collection_name if criteria
|
16
|
-
obj
|
17
|
-
end
|
6
|
+
def from_db(klass, attributes = nil, criteria = nil, selected_fields = nil)
|
7
|
+
obj = super(klass, attributes, criteria, selected_fields)
|
8
|
+
obj.collection_name = criteria.collection_name if criteria
|
9
|
+
obj
|
18
10
|
end
|
19
11
|
end
|
20
12
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# A class which sends values to the database as Strings but returns them to the user as Symbols.
|
4
|
+
module Mongoid
|
5
|
+
class StringifiedSymbol
|
6
|
+
class << self
|
7
|
+
# Convert the object from its mongo friendly ruby type to this type.
|
8
|
+
#
|
9
|
+
# @example Demongoize the object.
|
10
|
+
# Symbol.demongoize(object)
|
11
|
+
#
|
12
|
+
# @param [ Object ] object The object to demongoize.
|
13
|
+
#
|
14
|
+
# @return [ Symbol ] The object.
|
15
|
+
#
|
16
|
+
# @api private
|
17
|
+
def demongoize(object)
|
18
|
+
if object.nil?
|
19
|
+
object
|
20
|
+
else
|
21
|
+
object.to_s.to_sym
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Turn the object from the ruby type we deal with to a Mongo friendly
|
26
|
+
# type.
|
27
|
+
#
|
28
|
+
# @example Mongoize the object.
|
29
|
+
# Symbol.mongoize("123.11")
|
30
|
+
#
|
31
|
+
# @param [ Object ] object The object to mongoize.
|
32
|
+
#
|
33
|
+
# @return [ Symbol ] The object mongoized.
|
34
|
+
#
|
35
|
+
# @api private
|
36
|
+
def mongoize(object)
|
37
|
+
if object.nil?
|
38
|
+
object
|
39
|
+
else
|
40
|
+
object.to_s
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# @api private
|
45
|
+
def evolve(object)
|
46
|
+
mongoize(object)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -55,13 +55,13 @@ module ActiveJob
|
|
55
55
|
# - Completed jobs will not appear in completed since the Active Job adapter
|
56
56
|
# uses the default Rocket Job `destroy_on_completion` of `false`.
|
57
57
|
class RocketJobAdapter
|
58
|
-
def self.enqueue(active_job)
|
58
|
+
def self.enqueue(active_job)
|
59
59
|
job = RocketJob::Jobs::ActiveJob.create!(active_job_params(active_job))
|
60
60
|
active_job.provider_job_id = job.id.to_s if active_job.respond_to?(:provider_job_id=)
|
61
61
|
job
|
62
62
|
end
|
63
63
|
|
64
|
-
def self.enqueue_at(active_job, timestamp)
|
64
|
+
def self.enqueue_at(active_job, timestamp)
|
65
65
|
params = active_job_params(active_job)
|
66
66
|
params[:run_at] = Time.at(timestamp).utc
|
67
67
|
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Convert to and from CSV, JSON, xlsx, and PSV files.
|
2
|
+
#
|
3
|
+
# Example, Convert CSV file to JSON.
|
4
|
+
# job = RocketJob::ConversionJob.new
|
5
|
+
# job.upload("data.csv")
|
6
|
+
# job.output_category.file_name = "data.json"
|
7
|
+
# job.save!
|
8
|
+
#
|
9
|
+
# Example, Convert JSON file to PSV and compress it with GZip.
|
10
|
+
# job = RocketJob::ConversionJob.new
|
11
|
+
# job.upload("data.json")
|
12
|
+
# job.output_category.file_name = "data.psv.gz"
|
13
|
+
# job.save!
|
14
|
+
#
|
15
|
+
# Example, Read a CSV file that has been zipped from a remote website and the convert it to a GZipped json file.
|
16
|
+
# job = RocketJob::ConversionJob.new
|
17
|
+
# job.upload("https://example.org/file.zip")
|
18
|
+
# job.output_category.file_name = "data.json.gz"
|
19
|
+
# job.save!
|
20
|
+
#
|
21
|
+
module RocketJob
|
22
|
+
class ConversionJob < RocketJob::Job
|
23
|
+
include RocketJob::Batch
|
24
|
+
|
25
|
+
self.destroy_on_complete = false
|
26
|
+
|
27
|
+
# Detects file extension for its type
|
28
|
+
input_category format: :auto
|
29
|
+
output_category format: :auto
|
30
|
+
|
31
|
+
# When the job completes it will write the result to the output_category.file_name
|
32
|
+
after_batch :download
|
33
|
+
|
34
|
+
def perform(hash)
|
35
|
+
# For this job return the input hash record as-is. Could be transformed here as needed.
|
36
|
+
hash
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -18,7 +18,7 @@ module RocketJob
|
|
18
18
|
# file name of the archived file is passed into the job as either
|
19
19
|
# `upload_file_name` or `full_file_name`.
|
20
20
|
|
21
|
-
#
|
21
|
+
# Notes:
|
22
22
|
# - Jobs that do not implement #upload _must_ have either `upload_file_name` or `full_file_name` as an attribute.
|
23
23
|
#
|
24
24
|
# With RocketJob Pro, the file is automatically uploaded into the job itself
|
@@ -82,7 +82,7 @@ module RocketJob
|
|
82
82
|
key = iopath.to_s.tr(".", "_")
|
83
83
|
previous_size = previous_file_names[key]
|
84
84
|
# Check every few minutes for a file size change before trying to process the file.
|
85
|
-
size
|
85
|
+
size = check_file(entry, iopath, previous_size)
|
86
86
|
new_file_names[key] = size if size
|
87
87
|
end
|
88
88
|
end
|
@@ -35,7 +35,7 @@ module RocketJob
|
|
35
35
|
self.cron_schedule = "*/15 * * * * UTC"
|
36
36
|
|
37
37
|
# Whether to destroy zombie servers automatically
|
38
|
-
field :destroy_zombies, type: Boolean, default: true, user_editable: true, copy_on_restart: true
|
38
|
+
field :destroy_zombies, type: Mongoid::Boolean, default: true, user_editable: true, copy_on_restart: true
|
39
39
|
|
40
40
|
# Retention intervals in seconds.
|
41
41
|
# Set to nil to retain everything.
|
@@ -54,12 +54,12 @@ module RocketJob
|
|
54
54
|
RocketJob::Job.paused.where(completed_at: {"$lte" => paused_retention.seconds.ago}).destroy_all if paused_retention
|
55
55
|
RocketJob::Job.queued.where(created_at: {"$lte" => queued_retention.seconds.ago}).destroy_all if queued_retention
|
56
56
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
57
|
+
return unless destroy_zombies
|
58
|
+
|
59
|
+
# Cleanup zombie servers
|
60
|
+
RocketJob::Server.destroy_zombies
|
61
|
+
# Requeue jobs where the worker is in the zombie state and its server has gone away
|
62
|
+
RocketJob::ActiveWorker.requeue_zombies
|
63
63
|
end
|
64
64
|
end
|
65
65
|
end
|
@@ -31,16 +31,17 @@
|
|
31
31
|
# job.perform_now
|
32
32
|
# job.cleanup!
|
33
33
|
#
|
34
|
-
# By default output is not collected,
|
34
|
+
# By default output is not collected, call the method `#collect_output` to collect output.
|
35
35
|
#
|
36
36
|
# Example:
|
37
37
|
# job = RocketJob::Jobs::OnDemandBatchJob(
|
38
38
|
# description: 'Fix data',
|
39
39
|
# code: code,
|
40
40
|
# throttle_running_workers: 5,
|
41
|
-
# priority: 30
|
42
|
-
# collect_output: true
|
41
|
+
# priority: 30
|
43
42
|
# )
|
43
|
+
# job.collect_output
|
44
|
+
# job.save!
|
44
45
|
#
|
45
46
|
# Example: Move the upload operation into a before_batch.
|
46
47
|
# upload_code = <<-CODE
|
@@ -95,10 +96,20 @@ module RocketJob
|
|
95
96
|
before_batch :run_before_code
|
96
97
|
after_batch :run_after_code
|
97
98
|
|
99
|
+
# Shortcut for setting the slice_size
|
100
|
+
def slice_size=(slice_size)
|
101
|
+
input_category.slice_size = slice_size
|
102
|
+
end
|
103
|
+
|
104
|
+
# Add a new output category and collect output for it.
|
105
|
+
def add_output_category(**args)
|
106
|
+
self.output_categories << RocketJob::Category::Output.new(**args)
|
107
|
+
end
|
108
|
+
|
98
109
|
private
|
99
110
|
|
100
111
|
def load_perform_code
|
101
|
-
instance_eval("def perform(row)\n#{code}\nend")
|
112
|
+
instance_eval("def perform(row)\n#{code}\nend", __FILE__, __LINE__)
|
102
113
|
end
|
103
114
|
|
104
115
|
def run_before_code
|
@@ -118,13 +129,13 @@ module RocketJob
|
|
118
129
|
def validate_before_code
|
119
130
|
return if before_code.nil?
|
120
131
|
|
121
|
-
validate_field(:before_code) { instance_eval("def __before_code\n#{before_code}\nend") }
|
132
|
+
validate_field(:before_code) { instance_eval("def __before_code\n#{before_code}\nend", __FILE__, __LINE__) }
|
122
133
|
end
|
123
134
|
|
124
135
|
def validate_after_code
|
125
136
|
return if after_code.nil?
|
126
137
|
|
127
|
-
validate_field(:after_code) { instance_eval("def __after_code\n#{after_code}\nend") }
|
138
|
+
validate_field(:after_code) { instance_eval("def __after_code\n#{after_code}\nend", __FILE__, __LINE__) }
|
128
139
|
end
|
129
140
|
|
130
141
|
def validate_field(field)
|