rocketjob 3.4.3 → 3.5.0
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 +5 -5
- data/README.md +27 -0
- data/bin/rocketjob +1 -1
- data/lib/rocket_job/active_worker.rb +4 -3
- data/lib/rocket_job/cli.rb +13 -12
- data/lib/rocket_job/config.rb +17 -13
- data/lib/rocket_job/dirmon_entry.rb +88 -91
- data/lib/rocket_job/extensions/mongo/logging.rb +8 -4
- data/lib/rocket_job/extensions/mongoid/factory.rb +8 -6
- data/lib/rocket_job/extensions/rocket_job_adapter.rb +2 -4
- data/lib/rocket_job/heartbeat.rb +7 -8
- data/lib/rocket_job/job_exception.rb +6 -5
- data/lib/rocket_job/jobs/dirmon_job.rb +5 -7
- data/lib/rocket_job/jobs/housekeeping_job.rb +3 -2
- data/lib/rocket_job/jobs/on_demand_job.rb +104 -0
- data/lib/rocket_job/jobs/simple_job.rb +0 -2
- data/lib/rocket_job/jobs/upload_file_job.rb +100 -0
- data/lib/rocket_job/performance.rb +15 -10
- data/lib/rocket_job/plugins/cron.rb +7 -124
- data/lib/rocket_job/plugins/document.rb +8 -10
- data/lib/rocket_job/plugins/job/callbacks.rb +0 -1
- data/lib/rocket_job/plugins/job/logger.rb +0 -1
- data/lib/rocket_job/plugins/job/model.rb +15 -20
- data/lib/rocket_job/plugins/job/persistence.rb +3 -13
- data/lib/rocket_job/plugins/job/state_machine.rb +1 -2
- data/lib/rocket_job/plugins/job/throttle.rb +16 -12
- data/lib/rocket_job/plugins/job/worker.rb +15 -19
- data/lib/rocket_job/plugins/processing_window.rb +2 -2
- data/lib/rocket_job/plugins/restart.rb +3 -4
- data/lib/rocket_job/plugins/retry.rb +2 -3
- data/lib/rocket_job/plugins/singleton.rb +2 -3
- data/lib/rocket_job/plugins/state_machine.rb +19 -23
- data/lib/rocket_job/rocket_job.rb +4 -5
- data/lib/rocket_job/server.rb +35 -41
- data/lib/rocket_job/version.rb +2 -2
- data/lib/rocket_job/worker.rb +22 -21
- data/lib/rocketjob.rb +2 -0
- data/test/config/mongoid.yml +2 -2
- data/test/config_test.rb +0 -2
- data/test/dirmon_entry_test.rb +161 -134
- data/test/dirmon_job_test.rb +80 -78
- data/test/job_test.rb +0 -2
- data/test/jobs/housekeeping_job_test.rb +0 -1
- data/test/jobs/on_demand_job_test.rb +59 -0
- data/test/jobs/upload_file_job_test.rb +99 -0
- data/test/plugins/cron_test.rb +1 -3
- data/test/plugins/job/callbacks_test.rb +8 -13
- data/test/plugins/job/defaults_test.rb +0 -1
- data/test/plugins/job/logger_test.rb +2 -4
- data/test/plugins/job/model_test.rb +1 -2
- data/test/plugins/job/persistence_test.rb +0 -2
- data/test/plugins/job/state_machine_test.rb +0 -2
- data/test/plugins/job/throttle_test.rb +6 -8
- data/test/plugins/job/worker_test.rb +1 -2
- data/test/plugins/processing_window_test.rb +0 -2
- data/test/plugins/restart_test.rb +0 -1
- data/test/plugins/retry_test.rb +1 -2
- data/test/plugins/singleton_test.rb +0 -2
- data/test/plugins/state_machine_event_callbacks_test.rb +1 -2
- data/test/plugins/state_machine_test.rb +0 -2
- data/test/plugins/transaction_test.rb +5 -7
- data/test/test_db.sqlite3 +0 -0
- data/test/test_helper.rb +2 -1
- metadata +42 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9dd8c3c0ab00ae83d73d63aef3887f62d1d2a695399f263814ad7a5881aa980a
|
4
|
+
data.tar.gz: 715304e4587a9eda64c3cb5f73a69cd72ecdbf4ee232884c61f36666ef7c1a3a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3bc50f4e10068d2b193747c24880dee618be8df6ab58e3093f442332f93c591796901132490a856ee955aa19cb78abaad6034eb7280e080c494676c7c36d3899
|
7
|
+
data.tar.gz: 86d8dbe971e8e44a8e4854d1691078ac93a25f84fd8e482b9e84a3669457ad8886f84fc47007f199625e70fcecc1f4b1403804e38dc50acebd5c06b13b11d20b
|
data/README.md
CHANGED
@@ -17,6 +17,33 @@ Checkout http://rocketjob.io/
|
|
17
17
|
* Questions? Join the chat room on Gitter for [rocketjob support](https://gitter.im/rocketjob/support)
|
18
18
|
* [Report bugs](https://github.com/rocketjob/rocketjob/issues)
|
19
19
|
|
20
|
+
## Contributing to the documentation
|
21
|
+
|
22
|
+
To contribute to the documentation it is as easy as forking the repository
|
23
|
+
and then editing the markdown pages directly via the github web interface.
|
24
|
+
|
25
|
+
For more complex documentation changes checkout the source code locally.
|
26
|
+
|
27
|
+
#### Local checkout
|
28
|
+
|
29
|
+
* Fork the repository in github.
|
30
|
+
* Checkout your fork of the source code locally.
|
31
|
+
* Install Jekyll
|
32
|
+
~~~
|
33
|
+
cd docs
|
34
|
+
bundle update
|
35
|
+
~~~
|
36
|
+
* Run Jekyll web server:
|
37
|
+
~~~
|
38
|
+
jekyll serve
|
39
|
+
~~~
|
40
|
+
* Open a web browser to view the local documentation:
|
41
|
+
[http://127.0.0.1:4000](http://127.0.0.1:4000)
|
42
|
+
* Edit the files in the `/docs` folder.
|
43
|
+
* Refresh the page to see the changes.
|
44
|
+
|
45
|
+
Once the changes are complete, submit a github pull request.
|
46
|
+
|
20
47
|
## Upgrading to V3
|
21
48
|
|
22
49
|
V3 replaces MongoMapper with Mongoid which supports the latest MongoDB Ruby client driver.
|
data/bin/rocketjob
CHANGED
@@ -6,7 +6,7 @@ require 'rocket_job/cli'
|
|
6
6
|
# Start a rocketjob server instance from the command line
|
7
7
|
begin
|
8
8
|
RocketJob::CLI.new(ARGV).run
|
9
|
-
rescue => exc
|
9
|
+
rescue Exception => exc
|
10
10
|
# Failsafe logger that writes to STDERR
|
11
11
|
SemanticLogger.add_appender(io: STDERR, level: :error, formatter: :color)
|
12
12
|
SemanticLogger['RocketJob'].error('Rocket Job shutting down due to exception', exc)
|
@@ -4,7 +4,8 @@ module RocketJob
|
|
4
4
|
# When this server started working on this job / slice
|
5
5
|
attr_accessor :started_at
|
6
6
|
|
7
|
-
attr_accessor :
|
7
|
+
attr_accessor :job
|
8
|
+
attr_reader :name
|
8
9
|
|
9
10
|
# Returns [Hash<String:ActiveWorker>] hash of all servers sorted by name
|
10
11
|
# and what they are currently working on.
|
@@ -16,7 +17,7 @@ module RocketJob
|
|
16
17
|
def self.all(server_name = nil)
|
17
18
|
servers = []
|
18
19
|
# Need paused, failed or aborted since servers may still be working on active slices
|
19
|
-
query = RocketJob::Job.where(:state.in => [
|
20
|
+
query = RocketJob::Job.where(:state.in => %i[running paused failed aborted])
|
20
21
|
query = query.where(worker_name: /\A#{server_name}/) if server_name
|
21
22
|
query.each do |job|
|
22
23
|
servers += job.rocket_job_active_workers
|
@@ -50,7 +51,7 @@ module RocketJob
|
|
50
51
|
|
51
52
|
# Returns [String] the name of the server running this worker
|
52
53
|
def server_name
|
53
|
-
if match = name.to_s.match(/(.*:.*):.*/)
|
54
|
+
if (match = name.to_s.match(/(.*:.*):.*/))
|
54
55
|
match[1]
|
55
56
|
else
|
56
57
|
name
|
data/lib/rocket_job/cli.rb
CHANGED
@@ -4,7 +4,7 @@ require 'mongoid'
|
|
4
4
|
require 'rocketjob'
|
5
5
|
require 'rocket_job/extensions/mongoid/factory'
|
6
6
|
module RocketJob
|
7
|
-
# Command Line Interface parser for
|
7
|
+
# Command Line Interface parser for Rocket Job
|
8
8
|
class CLI
|
9
9
|
include SemanticLogger::Loggable
|
10
10
|
attr_accessor :name, :workers, :environment, :pidfile, :directory, :quiet,
|
@@ -41,7 +41,7 @@ module RocketJob
|
|
41
41
|
opts = {}
|
42
42
|
opts[:name] = name if name
|
43
43
|
opts[:max_workers] = workers if workers
|
44
|
-
opts[:filter] = {:
|
44
|
+
opts[:filter] = {_type: filter} if filter
|
45
45
|
Server.run(opts)
|
46
46
|
end
|
47
47
|
|
@@ -70,12 +70,12 @@ module RocketJob
|
|
70
70
|
# Override Rails log level if command line option was supplied
|
71
71
|
SemanticLogger.default_level = log_level.to_sym if log_level
|
72
72
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
73
|
+
return unless Rails.configuration.eager_load
|
74
|
+
|
75
|
+
logger.measure_info('Eager loaded Rails and all Engines') do
|
76
|
+
Rails.application.eager_load!
|
77
|
+
Rails::Engine.subclasses.each(&:eager_load!)
|
78
|
+
self.class.eager_load_jobs(File.expand_path('jobs', File.dirname(__FILE__)))
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
@@ -86,12 +86,14 @@ module RocketJob
|
|
86
86
|
require 'bundler/setup'
|
87
87
|
Bundler.require(environment)
|
88
88
|
rescue LoadError
|
89
|
+
nil
|
89
90
|
end
|
90
91
|
|
91
92
|
require 'rocketjob'
|
92
93
|
begin
|
93
94
|
require 'rocketjob_pro'
|
94
95
|
rescue LoadError
|
96
|
+
nil
|
95
97
|
end
|
96
98
|
|
97
99
|
# Log to file except when booting rails, when it will add the log file path
|
@@ -138,10 +140,10 @@ module RocketJob
|
|
138
140
|
end
|
139
141
|
|
140
142
|
# Eager load files in jobs folder
|
141
|
-
def self.eager_load_jobs(
|
142
|
-
Pathname.glob("#{
|
143
|
+
def self.eager_load_jobs(job_path = 'jobs')
|
144
|
+
Pathname.glob("#{job_path}/**/*.rb").each do |path|
|
143
145
|
next if path.directory?
|
144
|
-
logger.debug "Loading #{path
|
146
|
+
logger.debug "Loading #{path}"
|
145
147
|
require path.expand_path.to_s
|
146
148
|
end
|
147
149
|
end
|
@@ -198,6 +200,5 @@ module RocketJob
|
|
198
200
|
end
|
199
201
|
parser.parse! argv
|
200
202
|
end
|
201
|
-
|
202
203
|
end
|
203
204
|
end
|
data/lib/rocket_job/config.rb
CHANGED
@@ -51,22 +51,26 @@ module RocketJob
|
|
51
51
|
# Configure Mongoid
|
52
52
|
def self.load!(environment = 'development', file_name = nil, encryption_file_name = nil)
|
53
53
|
config_file = file_name ? Pathname.new(file_name) : Pathname.pwd.join('config/mongoid.yml')
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end
|
54
|
+
|
55
|
+
raise(ArgumentError, "Mongo Configuration file: #{config_file} not found") unless config_file.file?
|
56
|
+
|
57
|
+
logger.debug "Reading Mongo configuration from: #{config_file}"
|
58
|
+
Mongoid.load!(config_file, environment)
|
60
59
|
|
61
60
|
# Load Encryption configuration file if present
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
61
|
+
return unless defined?(SymmetricEncryption)
|
62
|
+
|
63
|
+
config_file =
|
64
|
+
if encryption_file_name
|
65
|
+
Pathname.new(encryption_file_name)
|
66
|
+
else
|
67
|
+
Pathname.pwd.join('config/symmetric-encryption.yml')
|
67
68
|
end
|
68
|
-
end
|
69
|
-
end
|
70
69
|
|
70
|
+
return unless config_file.file?
|
71
|
+
|
72
|
+
logger.debug "Reading SymmetricEncryption configuration from: #{config_file}"
|
73
|
+
SymmetricEncryption.load!(config_file.to_s, environment)
|
74
|
+
end
|
71
75
|
end
|
72
76
|
end
|
@@ -6,9 +6,14 @@ module RocketJob
|
|
6
6
|
include Plugins::Document
|
7
7
|
include Plugins::StateMachine
|
8
8
|
|
9
|
+
# The default archive directory that is used when the job being queued does not respond
|
10
|
+
# to #upload, and does not have an `archive_directory` specified in this entry
|
11
|
+
class_attribute :default_archive_directory
|
12
|
+
self.default_archive_directory = 'archive'.freeze
|
13
|
+
|
9
14
|
store_in collection: 'rocket_job.dirmon_entries'
|
10
15
|
|
11
|
-
# User defined name used to identify this DirmonEntry in
|
16
|
+
# User defined name used to identify this DirmonEntry in the Web Interface.
|
12
17
|
field :name, type: String
|
13
18
|
|
14
19
|
# Pattern for finding files
|
@@ -48,7 +53,7 @@ module RocketJob
|
|
48
53
|
# If supplied, the file will be moved to this directory before the job is started
|
49
54
|
# If the file was in a sub-directory, the corresponding sub-directory will
|
50
55
|
# be created in the archive directory.
|
51
|
-
field :archive_directory, type: String
|
56
|
+
field :archive_directory, type: String, default: default_archive_directory
|
52
57
|
|
53
58
|
# If this DirmonEntry is in the failed state, exception contains the cause
|
54
59
|
embeds_one :exception, class_name: 'RocketJob::JobException'
|
@@ -59,7 +64,7 @@ module RocketJob
|
|
59
64
|
# Exceeding this number will result in an exception being logged in a failed Dirmon instance.
|
60
65
|
# Dirmon processing will continue with new instances.
|
61
66
|
# TODO: Implement max_hits
|
62
|
-
#field :max_hits, type: Integer, default: 100
|
67
|
+
# field :max_hits, type: Integer, default: 100
|
63
68
|
|
64
69
|
#
|
65
70
|
# Read-only attributes
|
@@ -71,6 +76,11 @@ module RocketJob
|
|
71
76
|
# Unique index on pattern to help prevent two entries from scanning the same files
|
72
77
|
index({pattern: 1}, background: true, unique: true, drop_dups: true)
|
73
78
|
|
79
|
+
before_validation :strip_whitespace
|
80
|
+
validates_presence_of :pattern, :job_class_name, :archive_directory
|
81
|
+
validate :job_is_a_rocket_job
|
82
|
+
validate :job_has_properties
|
83
|
+
|
74
84
|
# State Machine events and transitions
|
75
85
|
#
|
76
86
|
# :pending -> :enabled -> :disabled
|
@@ -108,27 +118,6 @@ module RocketJob
|
|
108
118
|
end
|
109
119
|
end
|
110
120
|
|
111
|
-
# @formatter:on
|
112
|
-
validates_presence_of :pattern, :job_class_name
|
113
|
-
|
114
|
-
validates_each :job_class_name do |record, attr, value|
|
115
|
-
exists =
|
116
|
-
begin
|
117
|
-
value.nil? ? false : record.job_class.ancestors.include?(RocketJob::Job)
|
118
|
-
rescue NameError
|
119
|
-
false
|
120
|
-
end
|
121
|
-
record.errors.add(attr, 'job_class_name must be defined and must be derived from RocketJob::Job') unless exists
|
122
|
-
end
|
123
|
-
|
124
|
-
validates_each :properties do |record, attr, value|
|
125
|
-
if record.job_class && (methods = record.job_class.instance_methods)
|
126
|
-
value.each_pair do |k, v|
|
127
|
-
record.errors.add(attr, "Unknown property: #{k.inspect} with value: #{v}") unless methods.include?("#{k}=".to_sym)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
121
|
# Security Settings
|
133
122
|
#
|
134
123
|
# A whitelist of paths from which to process files.
|
@@ -147,7 +136,7 @@ module RocketJob
|
|
147
136
|
#
|
148
137
|
# Returns [Array<String>] a copy of the whitelisted paths
|
149
138
|
def self.get_whitelist_paths
|
150
|
-
|
139
|
+
whitelist_paths.dup
|
151
140
|
end
|
152
141
|
|
153
142
|
# Add a path to the whitelist
|
@@ -155,8 +144,8 @@ module RocketJob
|
|
155
144
|
def self.add_whitelist_path(path)
|
156
145
|
# Confirms that path exists
|
157
146
|
path = Pathname.new(path).realpath.to_s
|
158
|
-
|
159
|
-
|
147
|
+
whitelist_paths << path
|
148
|
+
whitelist_paths.uniq!
|
160
149
|
path
|
161
150
|
end
|
162
151
|
|
@@ -165,8 +154,8 @@ module RocketJob
|
|
165
154
|
def self.delete_whitelist_path(path)
|
166
155
|
# Confirms that path exists
|
167
156
|
path = Pathname.new(path).realpath.to_s
|
168
|
-
|
169
|
-
|
157
|
+
whitelist_paths.delete(path)
|
158
|
+
whitelist_paths.uniq!
|
170
159
|
path
|
171
160
|
end
|
172
161
|
|
@@ -193,30 +182,8 @@ module RocketJob
|
|
193
182
|
counts
|
194
183
|
end
|
195
184
|
|
196
|
-
# The default archive directory that is used when the job being queued does not respond
|
197
|
-
# to #upload, and does not have an `archive_directory` specified in this entry
|
198
|
-
class_attribute :default_archive_directory
|
199
|
-
|
200
|
-
self.default_archive_directory = '_archive'.freeze
|
201
|
-
|
202
|
-
# Returns [Pathname] the archive_directory if set, otherwise the default_archive_directory
|
203
|
-
# Creates the archive directory if one is set
|
204
|
-
def archive_pathname(file_pathname)
|
205
|
-
if archive_directory
|
206
|
-
path = Pathname.new(archive_directory)
|
207
|
-
begin
|
208
|
-
path.mkpath unless path.exist?
|
209
|
-
rescue Errno::ENOENT => exc
|
210
|
-
raise(Errno::ENOENT, "DirmonJob failed to create archive directory: #{path}, #{exc.message}")
|
211
|
-
end
|
212
|
-
path.realpath
|
213
|
-
else
|
214
|
-
file_pathname.dirname.join(self.class.default_archive_directory).realdirpath
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
185
|
# Passes each filename [Pathname] found that matches the pattern into the supplied block
|
219
|
-
def each
|
186
|
+
def each
|
220
187
|
SemanticLogger.named_tagged(dirmon_entry: id.to_s) do
|
221
188
|
# Case insensitive filename matching
|
222
189
|
Pathname.glob(pattern, File::FNM_CASEFOLD).each do |pathname|
|
@@ -234,7 +201,7 @@ module RocketJob
|
|
234
201
|
next if file_name.include?(self.class.default_archive_directory)
|
235
202
|
|
236
203
|
# Security check?
|
237
|
-
if
|
204
|
+
if whitelist_paths.size.positive? && whitelist_paths.none? { |whitepath| file_name.to_s.start_with?(whitepath) }
|
238
205
|
logger.error "Skipping file: #{file_name} since it is not in any of the whitelisted paths: #{whitelist_paths.join(', ')}"
|
239
206
|
next
|
240
207
|
end
|
@@ -244,7 +211,7 @@ module RocketJob
|
|
244
211
|
logger.error "Skipping file: #{file_name} since it is not writable by the current user. Must be able to delete/move the file after queueing the job"
|
245
212
|
next
|
246
213
|
end
|
247
|
-
|
214
|
+
yield(pathname)
|
248
215
|
end
|
249
216
|
end
|
250
217
|
end
|
@@ -264,7 +231,7 @@ module RocketJob
|
|
264
231
|
end
|
265
232
|
end
|
266
233
|
|
267
|
-
# Returns the Job to be
|
234
|
+
# Returns the Job to be created.
|
268
235
|
def job_class
|
269
236
|
return if job_class_name.nil?
|
270
237
|
job_class_name.constantize
|
@@ -272,47 +239,44 @@ module RocketJob
|
|
272
239
|
nil
|
273
240
|
end
|
274
241
|
|
275
|
-
#
|
242
|
+
# Archives the file and kicks off a proxy job to upload the file.
|
276
243
|
def later(pathname)
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
244
|
+
job_id = BSON::ObjectId.new
|
245
|
+
archived_file_name = archive_file(job_id, pathname)
|
246
|
+
|
247
|
+
job = RocketJob::Jobs::UploadFileJob.create!(
|
248
|
+
job_class_name: job_class_name,
|
249
|
+
properties: properties,
|
250
|
+
description: "#{name}: #{pathname.basename}",
|
251
|
+
upload_file_name: archived_file_name.to_s,
|
252
|
+
original_file_name: pathname.to_s,
|
253
|
+
job_id: job_id
|
254
|
+
)
|
255
|
+
|
256
|
+
logger.info(
|
257
|
+
message: 'Created RocketJob::Jobs::UploadFileJob',
|
258
|
+
payload: {
|
259
|
+
dirmon_entry_name: name,
|
260
|
+
upload_file_name: archived_file_name.to_s,
|
261
|
+
original_file_name: pathname.to_s,
|
262
|
+
job_class_name: job_class_name,
|
263
|
+
job_id: job_id.to_s,
|
264
|
+
upload_job_id: job.id.to_s
|
265
|
+
}
|
266
|
+
)
|
267
|
+
job
|
287
268
|
end
|
288
269
|
|
289
270
|
private
|
290
271
|
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
def upload_file(job, pathname)
|
296
|
-
if job.respond_to?(:upload)
|
297
|
-
# With RocketJob Pro the file can be uploaded directly into the Job itself
|
298
|
-
job.upload(pathname.to_s)
|
299
|
-
archive_directory ? archive_file(job, pathname) : pathname.unlink
|
300
|
-
else
|
301
|
-
upload_default(job, pathname)
|
302
|
-
end
|
272
|
+
# strip whitespaces from all variables that reference paths or patterns
|
273
|
+
def strip_whitespace
|
274
|
+
self.pattern = pattern.strip unless pattern.nil?
|
275
|
+
self.archive_directory = archive_directory.strip unless archive_directory.nil?
|
303
276
|
end
|
304
277
|
|
305
|
-
|
306
|
-
|
307
|
-
full_file_name = archive_file(job, pathname)
|
308
|
-
if job.respond_to?(:upload_file_name=)
|
309
|
-
job.upload_file_name = full_file_name
|
310
|
-
elsif job.respond_to?(:full_file_name=)
|
311
|
-
job.full_file_name = full_file_name
|
312
|
-
else
|
313
|
-
raise(ArgumentError, "#{job_class_name} must either have attribute 'upload_file_name' or 'full_file_name'")
|
314
|
-
end
|
315
|
-
end
|
278
|
+
class_attribute :whitelist_paths
|
279
|
+
self.whitelist_paths = Concurrent::Array.new
|
316
280
|
|
317
281
|
# Move the file to the archive directory
|
318
282
|
#
|
@@ -322,14 +286,47 @@ module RocketJob
|
|
322
286
|
#
|
323
287
|
# Note:
|
324
288
|
# - Works across partitions when the file and the archive are on different partitions
|
325
|
-
def archive_file(
|
289
|
+
def archive_file(job_id, pathname)
|
326
290
|
target_path = archive_pathname(pathname)
|
327
291
|
target_path.mkpath
|
328
|
-
target_file_name = target_path.join("#{
|
292
|
+
target_file_name = target_path.join("#{job_id}_#{pathname.basename}")
|
329
293
|
# In case the file is being moved across partitions
|
330
294
|
FileUtils.move(pathname.to_s, target_file_name.to_s)
|
331
295
|
target_file_name.to_s
|
332
296
|
end
|
333
297
|
|
298
|
+
# Returns [Pathname] to the archive directory, and creates it if it does not exist.
|
299
|
+
#
|
300
|
+
# If `archive_directory` is a relative path, it is appended to the `file_pathname`.
|
301
|
+
# If `archive_directory` is an absolute path, it is returned as-is.
|
302
|
+
def archive_pathname(file_pathname)
|
303
|
+
path = Pathname.new(archive_directory)
|
304
|
+
path = file_pathname.dirname.join(archive_directory) if path.relative?
|
305
|
+
|
306
|
+
begin
|
307
|
+
path.mkpath unless path.exist?
|
308
|
+
rescue Errno::ENOENT => exc
|
309
|
+
raise(Errno::ENOENT, "DirmonJob failed to create archive directory: #{path}, #{exc.message}")
|
310
|
+
end
|
311
|
+
path.realpath
|
312
|
+
end
|
313
|
+
|
314
|
+
# Validates job_class is a Rocket Job
|
315
|
+
def job_is_a_rocket_job
|
316
|
+
klass = job_class
|
317
|
+
return if job_class_name.nil? || klass&.ancestors&.include?(RocketJob::Job)
|
318
|
+
errors.add(:job_class_name, "Job #{job_class_name} must be defined and inherit from RocketJob::Job")
|
319
|
+
end
|
320
|
+
|
321
|
+
# Does the job have all the supplied properties
|
322
|
+
def job_has_properties
|
323
|
+
klass = job_class
|
324
|
+
return unless klass
|
325
|
+
|
326
|
+
properties.each_pair do |k, _v|
|
327
|
+
next if klass.public_method_defined?("#{k}=".to_sym)
|
328
|
+
errors.add(:properties, "Unknown Property: Attempted to set a value for #{k.inspect} which is not allowed on the job #{job_class_name}")
|
329
|
+
end
|
330
|
+
end
|
334
331
|
end
|
335
332
|
end
|