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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ba34033326ffcb1f7047751977fdca6cd5f2ae6d
4
- data.tar.gz: 834c136c510ebad348c84925d8d63f985fd9b612
3
+ metadata.gz: 1974e77ea4b6aa126dfa57155d15bd49a659ae1e
4
+ data.tar.gz: 900333f68eb5ee6e378fc19d494b7408944fa83b
5
5
  SHA512:
6
- metadata.gz: d6cb3e4861f65738fda7ef5a135cc7f48ff446fe35ed5dce3f6058044a3f8bb12e887e2ffdaf1a4985dc37777c1ab02fb38f0587ec831684593f64fc69ea0197
7
- data.tar.gz: 75c958355fb7f96e1b7ad6af4aaf10ba740fce214dcdfefe37c638495cb951abe0eb9d60e715f1bbede8c375b8e83d78570303b0d2303e3c4ec401e60f4002f4
6
+ metadata.gz: 741923205b5e7caa759db125afe234fe4c237e80bfdadbb58db512b2ef2269f42fd9fc58207c4e9eb97a0447f164b9179472ccc0e1ba3ec64aaa155753cf0257
7
+ data.tar.gz: b44d77f843c6e6342a2be309ec50fbf25eae7f9db26e074eb96143d18283a321981050d70287189cc5c855bc3f9600da5d11328e388ac9b2f5a3aea3420170cf
@@ -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
- @@instance ||= begin
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.whitelist_paths
150
- @@whitelist_paths.dup
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
- @@whitelist_paths << path
159
- @@whitelist_paths.uniq!
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
- @@whitelist_paths.delete(path)
169
- @@whitelist_paths.uniq!
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
- cattr_accessor :default_archive_directory
206
+ class_attribute :default_archive_directory
207
207
 
208
- @@default_archive_directory = '_archive'.freeze
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
- # Instance method to return whitelist paths
296
- def whitelist_paths
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 hourly on the hour
35
- self.cron_schedule = '0 * * * * America/New_York'
33
+ self.description = 'Cleans out historical jobs, and zombie servers.'
34
+ # Runs every 15 minutes
35
+ self.cron_schedule = '*/15 * * * * UTC'
36
36
 
37
- # Retention intervals in seconds
38
- # Set to nil to not
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
- logger.info('Job has expired. Not creating a new instance.')
91
- return if expired?
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('New job instance not started since one is already active')
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
@@ -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 server and requeue any jobs still "running"
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
- @@shutdown.value
162
+ @shutdown.value
163
163
  end
164
164
 
165
165
  # Set shutdown indicator for this server process
166
166
  def self.shutdown!
167
- @@shutdown.make_true
167
+ @shutdown.make_true
168
168
  end
169
169
 
170
- @@shutdown = Concurrent::AtomicBoolean.new(false)
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
- @@shutdown
174
+ @shutdown
175
175
  end
176
176
 
177
177
  # Set shutdown indicator for this server process
178
178
  def self.shutdown!
179
- @@shutdown = true
179
+ @shutdown = true
180
180
  end
181
181
 
182
- @@shutdown = false
182
+ @shutdown = false
183
183
  end
184
184
 
185
185
  # Run the server process
@@ -1,3 +1,3 @@
1
1
  module RocketJob #:nodoc
2
- VERSION = '3.2.1'
2
+ VERSION = '3.3.0'
3
3
  end
@@ -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
@@ -13,15 +13,15 @@ class DirmonEntryTest < Minitest::Test
13
13
  end
14
14
 
15
15
  class SumJob < RocketJob::Job
16
- @@result = nil
16
+ @result = nil
17
17
 
18
18
  # For temp test data
19
19
  def self.result
20
- @@result
20
+ @result
21
21
  end
22
22
 
23
23
  def perform(a, b)
24
- @@result = a + b
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
- job = HousekeepingJobTest::TestJob.new(created_at: 2.days.ago)
16
- job.abort!
17
- job = HousekeepingJobTest::TestJob.new(created_at: 8.days.ago)
18
- job.abort!
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
- job = HousekeepingJobTest::TestJob.new(created_at: 2.days.ago)
21
- job.perform_now
22
- job.save!
23
- job = HousekeepingJobTest::TestJob.new(created_at: 8.days.ago)
24
- job.perform_now
25
- job.save!
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
- job = HousekeepingJobTest::TestJob.new(created_at: 2.days.ago)
28
- job.fail!
29
- job = HousekeepingJobTest::TestJob.new(created_at: 15.days.ago)
30
- job.fail!
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
- job = HousekeepingJobTest::TestJob.new(created_at: 400.days.ago)
33
- job.pause!
34
- job = HousekeepingJobTest::TestJob.new
35
- job.pause!
36
+ job = HousekeepingJobTest::TestJob.new(created_at: 400.days.ago)
37
+ job.pause!
38
+ job = HousekeepingJobTest::TestJob.new
39
+ job.pause!
36
40
 
37
- HousekeepingJobTest::TestJob.create!(created_at: 15.days.ago)
38
- HousekeepingJobTest::TestJob.create!
41
+ HousekeepingJobTest::TestJob.create!(created_at: 15.days.ago)
42
+ HousekeepingJobTest::TestJob.create!
39
43
 
40
- assert_equal 10, HousekeepingJobTest::TestJob.count, -> { HousekeepingJobTest::TestJob.all.to_a.ai }
41
- end
44
+ assert_equal 10, HousekeepingJobTest::TestJob.count, -> { HousekeepingJobTest::TestJob.all.to_a.ai }
45
+ end
42
46
 
43
- after do
44
- @job.destroy if @job && !@job.new_record?
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 'perform' do
48
- it 'destroys jobs' do
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, HousekeepingJobTest::TestJob.aborted.count, -> { HousekeepingJobTest::TestJob.aborted.to_a.ai }
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.2.1
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-06 00:00:00.000000000 Z
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