rocketjob 3.2.1 → 3.3.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 +4 -4
- data/lib/rocket_job/config.rb +1 -1
- data/lib/rocket_job/dirmon_entry.rb +10 -14
- data/lib/rocket_job/jobs/housekeeping_job.rb +10 -5
- data/lib/rocket_job/plugins/restart.rb +5 -3
- data/lib/rocket_job/plugins/transaction.rb +44 -0
- data/lib/rocket_job/server.rb +8 -8
- data/lib/rocket_job/version.rb +1 -1
- data/lib/rocketjob.rb +1 -0
- data/test/dirmon_entry_test.rb +3 -3
- data/test/jobs/housekeeping_job_test.rb +61 -31
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1974e77ea4b6aa126dfa57155d15bd49a659ae1e
|
4
|
+
data.tar.gz: 900333f68eb5ee6e378fc19d494b7408944fa83b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 741923205b5e7caa759db125afe234fe4c237e80bfdadbb58db512b2ef2269f42fd9fc58207c4e9eb97a0447f164b9179472ccc0e1ba3ec64aaa155753cf0257
|
7
|
+
data.tar.gz: b44d77f843c6e6342a2be309ec50fbf25eae7f9db26e074eb96143d18283a321981050d70287189cc5c855bc3f9600da5d11328e388ac9b2f5a3aea3420170cf
|
data/lib/rocket_job/config.rb
CHANGED
@@ -7,7 +7,7 @@ module RocketJob
|
|
7
7
|
# Returns the single instance of the Rocket Job Configuration for this site
|
8
8
|
# in a thread-safe way
|
9
9
|
def self.instance
|
10
|
-
|
10
|
+
@instance ||= begin
|
11
11
|
first || create
|
12
12
|
rescue StandardError
|
13
13
|
# In case another process has already created the first document
|
@@ -146,8 +146,8 @@ module RocketJob
|
|
146
146
|
# Default: [] ==> Do not enforce whitelists
|
147
147
|
#
|
148
148
|
# Returns [Array<String>] a copy of the whitelisted paths
|
149
|
-
def self.
|
150
|
-
|
149
|
+
def self.get_whitelist_paths
|
150
|
+
self.whitelist_paths.dup
|
151
151
|
end
|
152
152
|
|
153
153
|
# Add a path to the whitelist
|
@@ -155,8 +155,8 @@ module RocketJob
|
|
155
155
|
def self.add_whitelist_path(path)
|
156
156
|
# Confirms that path exists
|
157
157
|
path = Pathname.new(path).realpath.to_s
|
158
|
-
|
159
|
-
|
158
|
+
self.whitelist_paths << path
|
159
|
+
self.whitelist_paths.uniq!
|
160
160
|
path
|
161
161
|
end
|
162
162
|
|
@@ -165,8 +165,8 @@ module RocketJob
|
|
165
165
|
def self.delete_whitelist_path(path)
|
166
166
|
# Confirms that path exists
|
167
167
|
path = Pathname.new(path).realpath.to_s
|
168
|
-
|
169
|
-
|
168
|
+
self.whitelist_paths.delete(path)
|
169
|
+
self.whitelist_paths.uniq!
|
170
170
|
path
|
171
171
|
end
|
172
172
|
|
@@ -203,9 +203,9 @@ module RocketJob
|
|
203
203
|
|
204
204
|
# The default archive directory that is used when the job being queued does not respond
|
205
205
|
# to #upload, and does not have an `archive_directory` specified in this entry
|
206
|
-
|
206
|
+
class_attribute :default_archive_directory
|
207
207
|
|
208
|
-
|
208
|
+
self.default_archive_directory = '_archive'.freeze
|
209
209
|
|
210
210
|
# Returns [Pathname] the archive_directory if set, otherwise the default_archive_directory
|
211
211
|
# Creates the archive directory if one is set
|
@@ -266,8 +266,6 @@ module RocketJob
|
|
266
266
|
end
|
267
267
|
end
|
268
268
|
|
269
|
-
@@whitelist_paths = Concurrent::Array.new
|
270
|
-
|
271
269
|
# Returns the Job to be queued
|
272
270
|
def job_class
|
273
271
|
return if job_class_name.nil?
|
@@ -292,10 +290,8 @@ module RocketJob
|
|
292
290
|
|
293
291
|
private
|
294
292
|
|
295
|
-
|
296
|
-
|
297
|
-
@@whitelist_paths
|
298
|
-
end
|
293
|
+
class_attribute :whitelist_paths
|
294
|
+
self.whitelist_paths = Concurrent::Array.new
|
299
295
|
|
300
296
|
# Upload the file to the job
|
301
297
|
def upload_file(job, pathname)
|
@@ -30,12 +30,15 @@ module RocketJob
|
|
30
30
|
include RocketJob::Plugins::Singleton
|
31
31
|
|
32
32
|
self.priority = 25
|
33
|
-
self.description = 'Cleans out historical jobs'
|
34
|
-
# Runs
|
35
|
-
self.cron_schedule = '
|
33
|
+
self.description = 'Cleans out historical jobs, and zombie servers.'
|
34
|
+
# Runs every 15 minutes
|
35
|
+
self.cron_schedule = '*/15 * * * * UTC'
|
36
36
|
|
37
|
-
#
|
38
|
-
|
37
|
+
# Whether to destroy zombie servers automatically
|
38
|
+
field :destroy_zombies, type: Boolean, default: true, user_editable: true, copy_on_restart: true
|
39
|
+
|
40
|
+
# Retention intervals in seconds.
|
41
|
+
# Set to nil to retain everything.
|
39
42
|
field :aborted_retention, type: Integer, default: 7.days, user_editable: true, copy_on_restart: true
|
40
43
|
field :completed_retention, type: Integer, default: 7.days, user_editable: true, copy_on_restart: true
|
41
44
|
field :failed_retention, type: Integer, default: 14.days, user_editable: true, copy_on_restart: true
|
@@ -43,6 +46,8 @@ module RocketJob
|
|
43
46
|
field :queued_retention, type: Integer, user_editable: true, copy_on_restart: true
|
44
47
|
|
45
48
|
def perform
|
49
|
+
RocketJob::Server.destroy_zombies if destroy_zombies
|
50
|
+
|
46
51
|
RocketJob::Job.aborted.where(created_at: {'$lte' => aborted_retention.seconds.ago}).destroy_all if aborted_retention
|
47
52
|
RocketJob::Job.completed.where(created_at: {'$lte' => completed_retention.seconds.ago}).destroy_all if completed_retention
|
48
53
|
RocketJob::Job.failed.where(created_at: {'$lte' => failed_retention.seconds.ago}).destroy_all if failed_retention
|
@@ -87,8 +87,10 @@ module RocketJob
|
|
87
87
|
|
88
88
|
# Run again in the future, even if this run fails with an exception
|
89
89
|
def rocket_job_restart_new_instance
|
90
|
-
|
91
|
-
|
90
|
+
if expired?
|
91
|
+
logger.info('Job has expired. Not creating a new instance.')
|
92
|
+
return
|
93
|
+
end
|
92
94
|
attrs = rocket_job_restart_attributes.reduce({}) { |attrs, attr| attrs[attr] = send(attr); attrs }
|
93
95
|
rocket_job_restart_create(attrs)
|
94
96
|
end
|
@@ -112,7 +114,7 @@ module RocketJob
|
|
112
114
|
end
|
113
115
|
count += 1
|
114
116
|
end
|
115
|
-
logger.warn(
|
117
|
+
logger.warn("New job instance not started: #{job.errors.messages.join(', ')}")
|
116
118
|
false
|
117
119
|
end
|
118
120
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module RocketJob
|
4
|
+
module Plugins
|
5
|
+
# Perform under a single Active Record transaction / unit or work.
|
6
|
+
#
|
7
|
+
# If the perform raises an exception it will cause any database changes to be rolled back.
|
8
|
+
#
|
9
|
+
# For Batch Jobs the transaction is at the slice level so that the entire slice succeeds,
|
10
|
+
# or is rolled back.
|
11
|
+
#
|
12
|
+
# Example:
|
13
|
+
# # Update User and create an Audit entry as a single database transaction.
|
14
|
+
# # If Audit.create! fails then the user change will also be rolled back.
|
15
|
+
# class MyJob < RocketJob::Job
|
16
|
+
# include RocketJob::Plugins::Transaction
|
17
|
+
#
|
18
|
+
# def perform
|
19
|
+
# u = User.find(name: 'Jack')
|
20
|
+
# u.age = 21
|
21
|
+
# u.save!
|
22
|
+
#
|
23
|
+
# Audit.create!(table: 'user', description: 'Changed age to 21')
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
module Transaction
|
27
|
+
extend ActiveSupport::Concern
|
28
|
+
|
29
|
+
included do
|
30
|
+
if respond_to?(:around_slice)
|
31
|
+
around_slice :rocket_job_transaction
|
32
|
+
else
|
33
|
+
around_perform :rocket_job_transaction
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def rocket_job_transaction(&block)
|
40
|
+
ActiveRecord::Base.transaction(&block)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/rocket_job/server.rb
CHANGED
@@ -92,8 +92,8 @@ module RocketJob
|
|
92
92
|
# Requeue any jobs being worked by this server when it is destroyed
|
93
93
|
before_destroy :requeue_jobs
|
94
94
|
|
95
|
-
# Destroy's all instances of zombie
|
96
|
-
# on those servers
|
95
|
+
# Destroy's all instances of zombie servers and requeues any jobs still "running"
|
96
|
+
# on those servers.
|
97
97
|
def self.destroy_zombies
|
98
98
|
count = 0
|
99
99
|
each do |server|
|
@@ -159,27 +159,27 @@ module RocketJob
|
|
159
159
|
if defined?(Concurrent::JavaAtomicBoolean) || defined?(Concurrent::CAtomicBoolean)
|
160
160
|
# Returns [true|false] whether the shutdown indicator has been set for this server process
|
161
161
|
def self.shutdown?
|
162
|
-
|
162
|
+
@shutdown.value
|
163
163
|
end
|
164
164
|
|
165
165
|
# Set shutdown indicator for this server process
|
166
166
|
def self.shutdown!
|
167
|
-
|
167
|
+
@shutdown.make_true
|
168
168
|
end
|
169
169
|
|
170
|
-
|
170
|
+
@shutdown = Concurrent::AtomicBoolean.new(false)
|
171
171
|
else
|
172
172
|
# Returns [true|false] whether the shutdown indicator has been set for this server process
|
173
173
|
def self.shutdown?
|
174
|
-
|
174
|
+
@shutdown
|
175
175
|
end
|
176
176
|
|
177
177
|
# Set shutdown indicator for this server process
|
178
178
|
def self.shutdown!
|
179
|
-
|
179
|
+
@shutdown = true
|
180
180
|
end
|
181
181
|
|
182
|
-
|
182
|
+
@shutdown = false
|
183
183
|
end
|
184
184
|
|
185
185
|
# Run the server process
|
data/lib/rocket_job/version.rb
CHANGED
data/lib/rocketjob.rb
CHANGED
@@ -27,6 +27,7 @@ module RocketJob
|
|
27
27
|
autoload :Persistence, 'rocket_job/plugins/job/persistence'
|
28
28
|
autoload :Throttle, 'rocket_job/plugins/job/throttle'
|
29
29
|
autoload :ThrottleRunningJobs, 'rocket_job/plugins/job/throttle_running_jobs'
|
30
|
+
autoload :Transaction, 'rocket_job/plugins/job/transaction'
|
30
31
|
autoload :Worker, 'rocket_job/plugins/job/worker'
|
31
32
|
end
|
32
33
|
module Rufus
|
data/test/dirmon_entry_test.rb
CHANGED
@@ -13,15 +13,15 @@ class DirmonEntryTest < Minitest::Test
|
|
13
13
|
end
|
14
14
|
|
15
15
|
class SumJob < RocketJob::Job
|
16
|
-
|
16
|
+
@result = nil
|
17
17
|
|
18
18
|
# For temp test data
|
19
19
|
def self.result
|
20
|
-
|
20
|
+
@result
|
21
21
|
end
|
22
22
|
|
23
23
|
def perform(a, b)
|
24
|
-
|
24
|
+
@result = a + b
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
@@ -11,49 +11,79 @@ class HousekeepingJobTest < Minitest::Test
|
|
11
11
|
before do
|
12
12
|
HousekeepingJobTest::TestJob.delete_all
|
13
13
|
RocketJob::Jobs::HousekeepingJob.delete_all
|
14
|
+
RocketJob::Server.delete_all
|
15
|
+
end
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
describe 'job retention' do
|
18
|
+
before do
|
19
|
+
job = HousekeepingJobTest::TestJob.new(created_at: 2.days.ago)
|
20
|
+
job.abort!
|
21
|
+
job = HousekeepingJobTest::TestJob.new(created_at: 8.days.ago)
|
22
|
+
job.abort!
|
19
23
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
job = HousekeepingJobTest::TestJob.new(created_at: 2.days.ago)
|
25
|
+
job.perform_now
|
26
|
+
job.save!
|
27
|
+
job = HousekeepingJobTest::TestJob.new(created_at: 8.days.ago)
|
28
|
+
job.perform_now
|
29
|
+
job.save!
|
26
30
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
+
job = HousekeepingJobTest::TestJob.new(created_at: 2.days.ago)
|
32
|
+
job.fail!
|
33
|
+
job = HousekeepingJobTest::TestJob.new(created_at: 15.days.ago)
|
34
|
+
job.fail!
|
31
35
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
+
job = HousekeepingJobTest::TestJob.new(created_at: 400.days.ago)
|
37
|
+
job.pause!
|
38
|
+
job = HousekeepingJobTest::TestJob.new
|
39
|
+
job.pause!
|
36
40
|
|
37
|
-
|
38
|
-
|
41
|
+
HousekeepingJobTest::TestJob.create!(created_at: 15.days.ago)
|
42
|
+
HousekeepingJobTest::TestJob.create!
|
39
43
|
|
40
|
-
|
41
|
-
|
44
|
+
assert_equal 10, HousekeepingJobTest::TestJob.count, -> { HousekeepingJobTest::TestJob.all.to_a.ai }
|
45
|
+
end
|
42
46
|
|
43
|
-
|
44
|
-
|
47
|
+
after do
|
48
|
+
@job.destroy if @job && !@job.new_record?
|
49
|
+
end
|
50
|
+
|
51
|
+
describe 'perform' do
|
52
|
+
it 'destroys jobs' do
|
53
|
+
@job = RocketJob::Jobs::HousekeepingJob.new
|
54
|
+
@job.perform_now
|
55
|
+
assert_equal 1, HousekeepingJobTest::TestJob.aborted.count, -> { HousekeepingJobTest::TestJob.aborted.to_a.ai }
|
56
|
+
assert_equal 1, HousekeepingJobTest::TestJob.completed.count, -> { HousekeepingJobTest::TestJob.completed.to_a.ai }
|
57
|
+
assert_equal 1, HousekeepingJobTest::TestJob.failed.count, -> { HousekeepingJobTest::TestJob.failed.to_a.ai }
|
58
|
+
assert_equal 2, HousekeepingJobTest::TestJob.paused.count, -> { HousekeepingJobTest::TestJob.paused.to_a.ai }
|
59
|
+
assert_equal 2, HousekeepingJobTest::TestJob.queued.count, -> { HousekeepingJobTest::TestJob.queued.to_a.ai }
|
60
|
+
end
|
61
|
+
end
|
45
62
|
end
|
46
63
|
|
47
|
-
describe '
|
48
|
-
|
64
|
+
describe 'zombie cleanup' do
|
65
|
+
before do
|
66
|
+
@server = RocketJob::Server.new
|
67
|
+
@server.started!
|
68
|
+
assert @server.reload.zombie?
|
69
|
+
assert_equal 1, RocketJob::Server.count, -> { RocketJob::Server.all.to_a.ai }
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'removes zombies' do
|
49
73
|
@job = RocketJob::Jobs::HousekeepingJob.new
|
74
|
+
assert @job.destroy_zombies
|
75
|
+
@job.perform_now
|
76
|
+
assert_equal 0, RocketJob::Server.count, -> { RocketJob::Server.all.to_a.ai }
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'leaves zombies' do
|
80
|
+
@job = RocketJob::Jobs::HousekeepingJob.new(destroy_zombies: false)
|
81
|
+
refute @job.destroy_zombies
|
82
|
+
assert_equal 1, RocketJob::Server.count, -> { RocketJob::Server.all.to_a.ai }
|
50
83
|
@job.perform_now
|
51
|
-
assert_equal 1,
|
52
|
-
assert_equal 1, HousekeepingJobTest::TestJob.completed.count, -> { HousekeepingJobTest::TestJob.completed.to_a.ai }
|
53
|
-
assert_equal 1, HousekeepingJobTest::TestJob.failed.count, -> { HousekeepingJobTest::TestJob.failed.to_a.ai }
|
54
|
-
assert_equal 2, HousekeepingJobTest::TestJob.paused.count, -> { HousekeepingJobTest::TestJob.paused.to_a.ai }
|
55
|
-
assert_equal 2, HousekeepingJobTest::TestJob.queued.count, -> { HousekeepingJobTest::TestJob.queued.to_a.ai }
|
84
|
+
assert_equal 1, RocketJob::Server.count, -> { RocketJob::Server.all.to_a.ai }
|
56
85
|
end
|
57
86
|
end
|
87
|
+
|
58
88
|
end
|
59
89
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rocketjob
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Reid Morrison
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-04-
|
11
|
+
date: 2017-04-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -111,6 +111,7 @@ files:
|
|
111
111
|
- lib/rocket_job/plugins/rufus/zo_time.rb
|
112
112
|
- lib/rocket_job/plugins/singleton.rb
|
113
113
|
- lib/rocket_job/plugins/state_machine.rb
|
114
|
+
- lib/rocket_job/plugins/transaction.rb
|
114
115
|
- lib/rocket_job/rocket_job.rb
|
115
116
|
- lib/rocket_job/server.rb
|
116
117
|
- lib/rocket_job/version.rb
|