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
data/lib/rocket_job/cli.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
1
|
+
require "optparse"
|
2
|
+
require "json"
|
3
|
+
require "semantic_logger"
|
4
|
+
require "mongoid"
|
5
|
+
require "rocketjob"
|
6
|
+
require "pathname"
|
7
7
|
module RocketJob
|
8
8
|
# Command Line Interface parser for Rocket Job
|
9
9
|
class CLI
|
@@ -18,7 +18,7 @@ module RocketJob
|
|
18
18
|
@quiet = false
|
19
19
|
@environment = nil
|
20
20
|
@pidfile = nil
|
21
|
-
@directory =
|
21
|
+
@directory = "."
|
22
22
|
@log_level = nil
|
23
23
|
@log_file = nil
|
24
24
|
@mongo_config = nil
|
@@ -36,7 +36,7 @@ module RocketJob
|
|
36
36
|
|
37
37
|
# Run a RocketJob::Server from the command line
|
38
38
|
def run
|
39
|
-
Thread.current.name =
|
39
|
+
Thread.current.name = "rocketjob main"
|
40
40
|
RocketJob.server! if server
|
41
41
|
setup_environment
|
42
42
|
setup_logger
|
@@ -60,7 +60,7 @@ module RocketJob
|
|
60
60
|
def rails?
|
61
61
|
@rails ||=
|
62
62
|
begin
|
63
|
-
boot_file = Pathname.new(directory).join(
|
63
|
+
boot_file = Pathname.new(directory).join("config/environment.rb").expand_path
|
64
64
|
boot_file.file?
|
65
65
|
end
|
66
66
|
end
|
@@ -71,13 +71,13 @@ module RocketJob
|
|
71
71
|
logger.info "Loading Rails environment: #{environment}"
|
72
72
|
RocketJob.rails!
|
73
73
|
|
74
|
-
require
|
75
|
-
require
|
76
|
-
boot_file = Pathname.new(directory).join(
|
74
|
+
require "rails"
|
75
|
+
require "rocket_job/railtie"
|
76
|
+
boot_file = Pathname.new(directory).join("config/environment.rb").expand_path
|
77
77
|
require(boot_file.to_s)
|
78
78
|
|
79
79
|
begin
|
80
|
-
require
|
80
|
+
require "rails_semantic_logger"
|
81
81
|
rescue LoadError
|
82
82
|
raise "Add the following line to your Gemfile when running rails:\n gem 'rails_semantic_logger'"
|
83
83
|
end
|
@@ -87,10 +87,10 @@ module RocketJob
|
|
87
87
|
|
88
88
|
return unless Rails.configuration.eager_load
|
89
89
|
|
90
|
-
logger.measure_info(
|
90
|
+
logger.measure_info("Eager loaded Rails and all Engines") do
|
91
91
|
Rails.application.eager_load!
|
92
92
|
Rails::Engine.subclasses.each(&:eager_load!)
|
93
|
-
self.class.eager_load_jobs(File.expand_path(
|
93
|
+
self.class.eager_load_jobs(File.expand_path("jobs", File.dirname(__FILE__)))
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
@@ -98,13 +98,13 @@ module RocketJob
|
|
98
98
|
def boot_standalone
|
99
99
|
# Try to load bundler if present
|
100
100
|
begin
|
101
|
-
require
|
101
|
+
require "bundler/setup"
|
102
102
|
Bundler.require(environment)
|
103
103
|
rescue LoadError
|
104
104
|
nil
|
105
105
|
end
|
106
106
|
|
107
|
-
require
|
107
|
+
require "rocketjob"
|
108
108
|
|
109
109
|
# Log to file except when booting rails, when it will add the log file path
|
110
110
|
path = log_file ? Pathname.new(log_file) : Pathname.pwd.join("log/#{environment}.log")
|
@@ -113,7 +113,7 @@ module RocketJob
|
|
113
113
|
|
114
114
|
logger.info "Rails not detected. Running standalone: #{environment}"
|
115
115
|
RocketJob::Config.load!(environment, mongo_config, symmetric_encryption_config)
|
116
|
-
self.class.eager_load_jobs(File.expand_path(
|
116
|
+
self.class.eager_load_jobs(File.expand_path("jobs", File.dirname(__FILE__)))
|
117
117
|
self.class.eager_load_jobs
|
118
118
|
end
|
119
119
|
|
@@ -128,8 +128,9 @@ module RocketJob
|
|
128
128
|
# Create a PID file if requested
|
129
129
|
def write_pidfile
|
130
130
|
return unless pidfile
|
131
|
+
|
131
132
|
pid = $PID
|
132
|
-
File.open(pidfile,
|
133
|
+
File.open(pidfile, "w") { |f| f.puts(pid) }
|
133
134
|
|
134
135
|
# Remove pidfile on exit
|
135
136
|
at_exit do
|
@@ -140,9 +141,9 @@ module RocketJob
|
|
140
141
|
def setup_environment
|
141
142
|
# Override Env vars when environment is supplied
|
142
143
|
if environment
|
143
|
-
ENV[
|
144
|
+
ENV["RACK_ENV"] = ENV["RAILS_ENV"] = environment
|
144
145
|
else
|
145
|
-
self.environment = ENV[
|
146
|
+
self.environment = ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development"
|
146
147
|
end
|
147
148
|
end
|
148
149
|
|
@@ -158,9 +159,10 @@ module RocketJob
|
|
158
159
|
end
|
159
160
|
|
160
161
|
# Eager load files in jobs folder
|
161
|
-
def self.eager_load_jobs(job_path =
|
162
|
+
def self.eager_load_jobs(job_path = "jobs")
|
162
163
|
Pathname.glob("#{job_path}/**/*.rb").each do |path|
|
163
164
|
next if path.directory?
|
165
|
+
|
164
166
|
logger.debug "Loading #{path}"
|
165
167
|
require path.expand_path.to_s
|
166
168
|
end
|
@@ -169,7 +171,7 @@ module RocketJob
|
|
169
171
|
def perform_list_servers(filter)
|
170
172
|
return list_the_servers(filter) unless refresh
|
171
173
|
|
172
|
-
|
174
|
+
loop do
|
173
175
|
list_the_servers(filter)
|
174
176
|
sleep(refresh)
|
175
177
|
puts
|
@@ -177,10 +179,10 @@ module RocketJob
|
|
177
179
|
end
|
178
180
|
|
179
181
|
def list_the_servers(filter)
|
180
|
-
|
181
|
-
puts format
|
182
|
+
layout = "%50.50s %20.20s %20.20s %20.20s %10.10s"
|
183
|
+
puts format(layout, "Server Name", "Workers(Current/Max)", "Started", "Heartbeat", "State")
|
182
184
|
header = "=" * 50
|
183
|
-
puts format
|
185
|
+
puts format(layout, header, header, header, header, header)
|
184
186
|
query = filter == :all ? RocketJob::Server.all : RocketJob::Server.where(name: /#{filter}/)
|
185
187
|
query.each do |server|
|
186
188
|
workers = "#{server&.heartbeat&.workers}/#{server.max_workers}"
|
@@ -188,14 +190,14 @@ module RocketJob
|
|
188
190
|
started = "#{RocketJob.seconds_as_duration(duration)} ago"
|
189
191
|
duration = Time.now - (server&.heartbeat&.updated_at || Time.now)
|
190
192
|
heartbeat = "#{RocketJob.seconds_as_duration(duration)} ago"
|
191
|
-
puts format
|
193
|
+
puts format(layout, server.name, workers, started, heartbeat, server.state)
|
192
194
|
end
|
193
195
|
0
|
194
196
|
end
|
195
197
|
|
196
198
|
def perform_server_action(server_name, action)
|
197
199
|
server_ids(server_name).each { |server_id| RocketJob::Subscribers::Server.publish(action, server_id: server_id) }
|
198
|
-
#RocketJob::Subscribers::Worker.publish(:stop, worker_id: 1, server_id: RocketJob::Server.running.last.id)
|
200
|
+
# RocketJob::Subscribers::Worker.publish(:stop, worker_id: 1, server_id: RocketJob::Server.running.last.id)
|
199
201
|
0
|
200
202
|
end
|
201
203
|
|
@@ -219,6 +221,7 @@ module RocketJob
|
|
219
221
|
if pid
|
220
222
|
server = RocketJob::Server.where(name: server_name).first
|
221
223
|
raise(ArgumentError, "No server with exact name: #{server_name} was found.") unless server
|
224
|
+
|
222
225
|
return [server.id]
|
223
226
|
end
|
224
227
|
|
@@ -230,90 +233,90 @@ module RocketJob
|
|
230
233
|
|
231
234
|
# Parse command line options placing results in the corresponding instance variables
|
232
235
|
def parse(argv)
|
233
|
-
parser
|
234
|
-
o.on(
|
236
|
+
parser = OptionParser.new do |o|
|
237
|
+
o.on("-n", "--name NAME", "Unique Name of this server (Default: host_name:PID)") do |arg|
|
235
238
|
Config.name = arg
|
236
239
|
end
|
237
|
-
o.on(
|
240
|
+
o.on("-w", "--workers COUNT", "Number of workers (threads) to start") do |arg|
|
238
241
|
@max_workers = arg.to_i
|
239
242
|
end
|
240
|
-
o.on(
|
243
|
+
o.on("--include REGEXP", 'Limit this server to only those job classes that match this regular expression (case-insensitive). Example: "DirmonJob|WeeklyReportJob"') do |arg|
|
241
244
|
@include_filter = Regexp.new(arg, true)
|
242
245
|
end
|
243
|
-
o.on(
|
244
|
-
warn
|
246
|
+
o.on("-F", "--filter REGEXP", "DEPRECATED. Use --include") do |arg|
|
247
|
+
warn "-F and --filter are deprecated, use --include"
|
245
248
|
@include_filter = Regexp.new(arg, true)
|
246
249
|
end
|
247
|
-
o.on(
|
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|
|
248
251
|
@exclude_filter = Regexp.new(arg, true)
|
249
252
|
end
|
250
|
-
o.on(
|
253
|
+
o.on("-W", "--where JSON", "Limit this server instance to the supplied mongo query filter. Supply as a string in JSON format. Example: '{\"priority\":{\"$lte\":25}}'") do |arg|
|
251
254
|
@where_filter = JSON.parse(arg)
|
252
255
|
end
|
253
|
-
o.on(
|
256
|
+
o.on("-q", "--quiet", "Do not write to stdout, only to logfile. Necessary when running as a daemon") do
|
254
257
|
@quiet = true
|
255
258
|
end
|
256
|
-
o.on(
|
259
|
+
o.on("-d", "--dir DIR", "Directory containing Rails app, if not current directory") do |arg|
|
257
260
|
@directory = arg
|
258
261
|
end
|
259
|
-
o.on(
|
262
|
+
o.on("-e", "--environment ENVIRONMENT", "The environment to run the app on (Default: RAILS_ENV || RACK_ENV || development)") do |arg|
|
260
263
|
@environment = arg
|
261
264
|
end
|
262
|
-
o.on(
|
265
|
+
o.on("-l", "--log_level trace|debug|info|warn|error|fatal", "The log level to use") do |arg|
|
263
266
|
@log_level = arg
|
264
267
|
end
|
265
|
-
o.on(
|
268
|
+
o.on("-f", "--log_file FILE_NAME", "The log file to write to. Default: log/<environment>.log") do |arg|
|
266
269
|
@log_file = arg
|
267
270
|
end
|
268
|
-
o.on(
|
271
|
+
o.on("--pidfile PATH", "Use PATH as a pidfile") do |arg|
|
269
272
|
@pidfile = arg
|
270
273
|
end
|
271
|
-
o.on(
|
274
|
+
o.on("-m", "--mongo MONGO_CONFIG_FILE_NAME", "Path and filename of config file. Default: config/mongoid.yml") do |arg|
|
272
275
|
@mongo_config = arg
|
273
276
|
end
|
274
|
-
o.on(
|
277
|
+
o.on("-s", "--symmetric-encryption SYMMETRIC_ENCRYPTION_CONFIG_FILE_NAME", "Path and filename of Symmetric Encryption config file. Default: config/symmetric-encryption.yml") do |arg|
|
275
278
|
@symmetric_encryption_config = arg
|
276
279
|
end
|
277
|
-
o.on(
|
280
|
+
o.on("--list [FILTER]", "List active servers. Supply either an exact server name or a partial name as a filter.") do |filter|
|
278
281
|
@quiet = true
|
279
282
|
@server = false
|
280
283
|
@list_servers = filter || :all
|
281
284
|
end
|
282
|
-
o.on(
|
285
|
+
o.on("--refresh [SECONDS]", "When listing active servers, update the list by this number of seconds. Defaults to every 1 second.") do |seconds|
|
283
286
|
@refresh = (seconds || 1).to_s.to_f
|
284
287
|
end
|
285
|
-
o.on(
|
288
|
+
o.on("--stop [SERVER_NAME]", "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|
|
286
289
|
@quiet = true
|
287
290
|
@server = false
|
288
291
|
@stop_server = server_name || :all
|
289
292
|
end
|
290
|
-
o.on(
|
293
|
+
o.on("--kill [SERVER_NAME]", "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|
|
291
294
|
@quiet = true
|
292
295
|
@server = false
|
293
296
|
@kill_server = server_name || :all
|
294
297
|
end
|
295
|
-
o.on(
|
298
|
+
o.on("--pause [SERVER_NAME]", "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|
|
296
299
|
@quiet = true
|
297
300
|
@server = false
|
298
301
|
@pause_server = server_name || :all
|
299
302
|
end
|
300
|
-
o.on(
|
303
|
+
o.on("--resume [SERVER_NAME]", "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|
|
301
304
|
@quiet = true
|
302
305
|
@server = false
|
303
306
|
@resume_server = server_name || :all
|
304
307
|
end
|
305
|
-
o.on(
|
308
|
+
o.on("--dump [SERVER_NAME]", "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|
|
306
309
|
@quiet = true
|
307
310
|
@server = false
|
308
311
|
@thread_dump = server_name || :all
|
309
312
|
end
|
310
|
-
o.on(
|
313
|
+
o.on("-v", "--version", "Print the version information") do
|
311
314
|
puts "Rocket Job v#{RocketJob::VERSION}"
|
312
315
|
exit 1
|
313
316
|
end
|
314
317
|
end
|
315
|
-
parser.banner =
|
316
|
-
parser.on_tail
|
318
|
+
parser.banner = "rocketjob <options>"
|
319
|
+
parser.on_tail "-h", "--help", "Show help" do
|
317
320
|
puts parser
|
318
321
|
exit 1
|
319
322
|
end
|
data/lib/rocket_job/config.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "yaml"
|
2
2
|
module RocketJob
|
3
3
|
# Rocket Job Configuration
|
4
4
|
class Config
|
@@ -72,8 +72,8 @@ module RocketJob
|
|
72
72
|
self.where_filter = nil
|
73
73
|
|
74
74
|
# Configure Mongoid
|
75
|
-
def self.load!(environment =
|
76
|
-
config_file = file_name ? Pathname.new(file_name) : Pathname.pwd.join(
|
75
|
+
def self.load!(environment = "development", file_name = nil, encryption_file_name = nil)
|
76
|
+
config_file = file_name ? Pathname.new(file_name) : Pathname.pwd.join("config/mongoid.yml")
|
77
77
|
|
78
78
|
raise(ArgumentError, "Mongo Configuration file: #{config_file} not found") unless config_file.file?
|
79
79
|
|
@@ -84,7 +84,7 @@ module RocketJob
|
|
84
84
|
if encryption_file_name
|
85
85
|
Pathname.new(encryption_file_name)
|
86
86
|
else
|
87
|
-
Pathname.pwd.join(
|
87
|
+
Pathname.pwd.join("config/symmetric-encryption.yml")
|
88
88
|
end
|
89
89
|
|
90
90
|
return unless config_file.file?
|
@@ -97,14 +97,12 @@ module RocketJob
|
|
97
97
|
# include_filter, exclude_filter, and where_filter.
|
98
98
|
# Returns nil if no filter should be applied.
|
99
99
|
def self.filter
|
100
|
-
if include_filter && exclude_filter
|
101
|
-
raise(ArgumentError, 'Cannot supply both an include_filter and an exclude_filter')
|
102
|
-
end
|
100
|
+
raise(ArgumentError, "Cannot supply both an include_filter and an exclude_filter") if include_filter && exclude_filter
|
103
101
|
|
104
102
|
filter = where_filter
|
105
|
-
(filter ||= {})[
|
106
|
-
(filter ||= {})[
|
107
|
-
filter
|
103
|
+
(filter ||= {})["_type"] = include_filter if include_filter
|
104
|
+
(filter ||= {})["_type"] = {"$not" => exclude_filter} if exclude_filter
|
105
|
+
filter&.dup
|
108
106
|
end
|
109
107
|
end
|
110
108
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "concurrent"
|
2
|
+
require "fileutils"
|
3
3
|
module RocketJob
|
4
4
|
class DirmonEntry
|
5
5
|
include Plugins::Document
|
@@ -8,9 +8,9 @@ module RocketJob
|
|
8
8
|
# The default archive directory that is used when the job being queued does not respond
|
9
9
|
# to #upload, and does not have an `archive_directory` specified in this entry
|
10
10
|
class_attribute :default_archive_directory
|
11
|
-
self.default_archive_directory =
|
11
|
+
self.default_archive_directory = "archive".freeze
|
12
12
|
|
13
|
-
store_in collection:
|
13
|
+
store_in collection: "rocket_job.dirmon_entries"
|
14
14
|
|
15
15
|
# User defined name used to identify this DirmonEntry in the Web Interface.
|
16
16
|
field :name, type: String
|
@@ -55,7 +55,7 @@ module RocketJob
|
|
55
55
|
field :archive_directory, type: String, default: default_archive_directory
|
56
56
|
|
57
57
|
# If this DirmonEntry is in the failed state, exception contains the cause
|
58
|
-
embeds_one :exception, class_name:
|
58
|
+
embeds_one :exception, class_name: "RocketJob::JobException"
|
59
59
|
|
60
60
|
# The maximum number of files that should ever match during a single poll of the pattern.
|
61
61
|
#
|
@@ -73,7 +73,7 @@ module RocketJob
|
|
73
73
|
field :state, type: Symbol, default: :pending
|
74
74
|
|
75
75
|
# Unique index on pattern to help prevent two entries from scanning the same files
|
76
|
-
index({pattern: 1}, background: true, unique: true
|
76
|
+
index({pattern: 1}, background: true, unique: true)
|
77
77
|
|
78
78
|
before_validation :strip_whitespace
|
79
79
|
validates_presence_of :pattern, :job_class_name, :archive_directory
|
@@ -175,8 +175,8 @@ module RocketJob
|
|
175
175
|
# # => {}
|
176
176
|
def self.counts_by_state
|
177
177
|
counts = {}
|
178
|
-
collection.aggregate([{
|
179
|
-
counts[result[
|
178
|
+
collection.aggregate([{"$group" => {_id: "$state", count: {"$sum" => 1}}}]).each do |result|
|
179
|
+
counts[result["_id"].to_sym] = result["count"]
|
180
180
|
end
|
181
181
|
counts
|
182
182
|
end
|
@@ -213,7 +213,7 @@ module RocketJob
|
|
213
213
|
exception.worker_name = worker_name
|
214
214
|
else
|
215
215
|
build_exception(
|
216
|
-
class_name:
|
216
|
+
class_name: "RocketJob::DirmonEntryException",
|
217
217
|
message: exc_or_message,
|
218
218
|
backtrace: [],
|
219
219
|
worker_name: worker_name
|
@@ -224,6 +224,7 @@ module RocketJob
|
|
224
224
|
# Returns the Job to be created.
|
225
225
|
def job_class
|
226
226
|
return if job_class_name.nil?
|
227
|
+
|
227
228
|
job_class_name.constantize
|
228
229
|
rescue NameError
|
229
230
|
nil
|
@@ -245,7 +246,7 @@ module RocketJob
|
|
245
246
|
)
|
246
247
|
|
247
248
|
logger.info(
|
248
|
-
message:
|
249
|
+
message: "Created RocketJob::Jobs::UploadFileJob",
|
249
250
|
payload: {
|
250
251
|
dirmon_entry_name: name,
|
251
252
|
upload_file_name: archive_path.to_s,
|
@@ -282,6 +283,7 @@ module RocketJob
|
|
282
283
|
def job_is_a_rocket_job
|
283
284
|
klass = job_class
|
284
285
|
return if job_class_name.nil? || klass&.ancestors&.include?(RocketJob::Job)
|
286
|
+
|
285
287
|
errors.add(:job_class_name, "Job #{job_class_name} must be defined and inherit from RocketJob::Job")
|
286
288
|
end
|
287
289
|
|
@@ -292,6 +294,7 @@ module RocketJob
|
|
292
294
|
|
293
295
|
properties.each_pair do |k, _v|
|
294
296
|
next if klass.public_method_defined?("#{k}=".to_sym)
|
297
|
+
|
295
298
|
errors.add(:properties, "Unknown Property: Attempted to set a value for #{k.inspect} which is not allowed on the job #{job_class_name}")
|
296
299
|
end
|
297
300
|
end
|
data/lib/rocket_job/event.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "concurrent-ruby"
|
2
2
|
|
3
3
|
module RocketJob
|
4
4
|
# RocketJob::Event
|
@@ -10,7 +10,7 @@ module RocketJob
|
|
10
10
|
include Plugins::Document
|
11
11
|
include Mongoid::Timestamps
|
12
12
|
|
13
|
-
ALL_EVENTS =
|
13
|
+
ALL_EVENTS = "*".freeze
|
14
14
|
|
15
15
|
# Capped collection long polling interval.
|
16
16
|
class_attribute :long_poll_seconds, instance_accessor: false
|
@@ -42,7 +42,7 @@ module RocketJob
|
|
42
42
|
|
43
43
|
validates_presence_of :name
|
44
44
|
|
45
|
-
store_in collection:
|
45
|
+
store_in collection: "rocket_job.events"
|
46
46
|
index({created_at: 1}, background: true)
|
47
47
|
|
48
48
|
# Add a subscriber for its events.
|
@@ -84,14 +84,14 @@ module RocketJob
|
|
84
84
|
# Indefinitely tail the capped collection looking for new events.
|
85
85
|
# time: the start time from which to start looking for new events.
|
86
86
|
def self.listener(time: @load_time)
|
87
|
-
Thread.current.name =
|
87
|
+
Thread.current.name = "rocketjob event"
|
88
88
|
create_capped_collection
|
89
89
|
|
90
|
-
logger.info(
|
90
|
+
logger.info("Event listener started")
|
91
91
|
tail_capped_collection(time) { |event| process_event(event) }
|
92
|
-
rescue Exception =>
|
93
|
-
logger.error(
|
94
|
-
raise(
|
92
|
+
rescue Exception => e
|
93
|
+
logger.error("#listener Event listener is terminating due to unhandled exception", e)
|
94
|
+
raise(e)
|
95
95
|
end
|
96
96
|
|
97
97
|
# Create the capped collection only if it does not exist.
|
@@ -117,13 +117,13 @@ module RocketJob
|
|
117
117
|
|
118
118
|
def self.tail_capped_collection(time)
|
119
119
|
with(socket_timeout: long_poll_seconds + 10) do
|
120
|
-
filter = {created_at: {
|
120
|
+
filter = {created_at: {"$gt" => time}}
|
121
121
|
collection.
|
122
122
|
find(filter).
|
123
123
|
await_data.
|
124
124
|
cursor_type(:tailable_await).
|
125
125
|
max_await_time_ms(long_poll_seconds * 1000).
|
126
|
-
sort(
|
126
|
+
sort("$natural" => 1).
|
127
127
|
each do |doc|
|
128
128
|
event = Mongoid::Factory.from_db(Event, doc)
|
129
129
|
# Recovery will occur from after the last message read
|
@@ -131,14 +131,14 @@ module RocketJob
|
|
131
131
|
yield(event)
|
132
132
|
end
|
133
133
|
end
|
134
|
-
rescue Mongo::Error::SocketError, Mongo::Error::SocketTimeoutError, Mongo::Error::OperationFailure, Timeout::Error =>
|
135
|
-
logger.info("Creating a new cursor and trying again: #{
|
134
|
+
rescue Mongo::Error::SocketError, Mongo::Error::SocketTimeoutError, Mongo::Error::OperationFailure, Timeout::Error => e
|
135
|
+
logger.info("Creating a new cursor and trying again: #{e.class.name} #{e.message}")
|
136
136
|
retry
|
137
137
|
end
|
138
138
|
|
139
139
|
# Process a new event, calling registered subscribers.
|
140
140
|
def self.process_event(event)
|
141
|
-
logger.info(
|
141
|
+
logger.info("Event Received", event.attributes)
|
142
142
|
|
143
143
|
if @subscribers.key?(event.name)
|
144
144
|
@subscribers[event.name].each { |subscriber| subscriber.process_action(event.action, event.parameters) }
|
@@ -147,8 +147,8 @@ module RocketJob
|
|
147
147
|
if @subscribers.key?(ALL_EVENTS)
|
148
148
|
@subscribers[ALL_EVENTS].each { |subscriber| subscriber.process_event(event.name, event.action, event.parameters) }
|
149
149
|
end
|
150
|
-
rescue StandardError =>
|
151
|
-
logger.error(
|
150
|
+
rescue StandardError => e
|
151
|
+
logger.error("Unknown subscriber. Continuing..", e)
|
152
152
|
end
|
153
153
|
|
154
154
|
def self.collection_exists?
|
@@ -157,7 +157,7 @@ module RocketJob
|
|
157
157
|
|
158
158
|
# Convert a non-capped collection to capped
|
159
159
|
def self.convert_to_capped_collection(size)
|
160
|
-
collection.database.command(
|
160
|
+
collection.database.command("convertToCapped" => collection_name.to_s, "size" => size)
|
161
161
|
end
|
162
162
|
end
|
163
163
|
end
|