rocketjob 3.1.0 → 3.2.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/cli.rb +2 -0
- data/lib/rocket_job/dirmon_entry.rb +1 -1
- data/lib/rocket_job/extensions/rocket_job_adapter.rb +69 -29
- data/lib/rocket_job/jobs/active_job.rb +15 -0
- data/lib/rocket_job/jobs/dirmon_job.rb +3 -2
- data/lib/rocket_job/jobs/housekeeping_job.rb +5 -5
- data/lib/rocket_job/plugins/cron.rb +1 -1
- data/lib/rocket_job/plugins/document.rb +0 -34
- data/lib/rocket_job/plugins/job/model.rb +48 -5
- data/lib/rocket_job/plugins/processing_window.rb +4 -3
- data/lib/rocket_job/plugins/restart.rb +73 -30
- data/lib/rocket_job/plugins/retry.rb +1 -1
- data/lib/rocket_job/rocket_job.rb +53 -0
- data/lib/rocket_job/version.rb +1 -1
- data/lib/rocket_job/worker.rb +1 -1
- data/lib/rocketjob.rb +2 -23
- data/test/plugins/restart_test.rb +7 -23
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1750c9257c4d70baebe0d97b1a8549aaf86fd61c
|
4
|
+
data.tar.gz: 027cb7272e67685d1f49eb5455723a093d40e690
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f109722d6ecb509dca6f4ca8fa4da70f85d9c06c6bf85c7ae24aad7e155a580bb643db19b0ab5ce1f4b67369f30639d83c9a830fa8a7035b077e3639b19710e
|
7
|
+
data.tar.gz: f2181de5a394b23acf108369d8c3b49b527714d3833010ff648168d61dfed49d5fc86d394f7fcfb93b2d36d1d666385c2eac31bf450ed0e7667d9b72bed0b7e4
|
data/lib/rocket_job/cli.rb
CHANGED
@@ -27,6 +27,7 @@ module RocketJob
|
|
27
27
|
# Run a RocketJob::Server from the command line
|
28
28
|
def run
|
29
29
|
Thread.current.name = 'rocketjob main'
|
30
|
+
RocketJob.server!
|
30
31
|
setup_environment
|
31
32
|
setup_logger
|
32
33
|
rails? ? boot_rails : boot_standalone
|
@@ -53,6 +54,7 @@ module RocketJob
|
|
53
54
|
# Returns [true|false] whether Rails is present
|
54
55
|
def boot_rails
|
55
56
|
logger.info "Loading Rails environment: #{environment}"
|
57
|
+
RocketJob.rails!
|
56
58
|
|
57
59
|
boot_file = Pathname.new(directory).join('config/environment.rb').expand_path
|
58
60
|
require(boot_file.to_s)
|
@@ -225,7 +225,7 @@ module RocketJob
|
|
225
225
|
|
226
226
|
# Passes each filename [Pathname] found that matches the pattern into the supplied block
|
227
227
|
def each(&block)
|
228
|
-
|
228
|
+
SemanticLogger.named_tagged(dirmon_entry: id.to_s) do
|
229
229
|
# Case insensitive filename matching
|
230
230
|
Pathname.glob(pattern, File::FNM_CASEFOLD).each do |pathname|
|
231
231
|
next if pathname.directory?
|
@@ -8,42 +8,82 @@ module ActiveJob
|
|
8
8
|
#
|
9
9
|
# To use Rocket Job set the queue_adapter config to +:rocket_job+.
|
10
10
|
#
|
11
|
-
#
|
11
|
+
# In application.rb add the following line:
|
12
|
+
# config.active_job.queue_adapter = :rocket_job
|
13
|
+
#
|
14
|
+
# Example:
|
15
|
+
#
|
16
|
+
# Create a new file in app/job/my_job.rb:
|
17
|
+
#
|
18
|
+
# class MyJob < ActiveJob::Base
|
19
|
+
# def perform(record)
|
20
|
+
# p "Received: #{record}"
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# Run the job inline to verify ActiveJob is working:
|
25
|
+
#
|
26
|
+
# MyJob.perform_now('hello world')
|
27
|
+
#
|
28
|
+
# Enqueue the job for processing:
|
29
|
+
#
|
30
|
+
# MyJob.perform_later('hello world')
|
31
|
+
#
|
32
|
+
# Enqueue the job for processing, 5 minutes from now:
|
33
|
+
#
|
34
|
+
# MyJob.set(wait: 5.minutes).perform_later('hello world')
|
35
|
+
#
|
36
|
+
# Start RocketJob server (or, restart if already running)
|
37
|
+
#
|
38
|
+
# bundle exec rocketjob
|
39
|
+
#
|
40
|
+
# Override the priority of the job:
|
41
|
+
#
|
42
|
+
# class MyJob < ActiveJob::Base
|
43
|
+
# queue_with_priority 20
|
44
|
+
#
|
45
|
+
# def perform(record)
|
46
|
+
# p "Received: #{record}"
|
47
|
+
# end
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# Notes:
|
51
|
+
# - ActiveJobs will appear in:
|
52
|
+
# - Queued before the are processed.
|
53
|
+
# - Failed if the fail to process.
|
54
|
+
# - Scheduled if they are to be processed in the future.
|
55
|
+
# - Completed jobs will not appear in completed since the Active Job adapter
|
56
|
+
# uses the default Rocket Job `destroy_on_completion` of `false`.
|
12
57
|
class RocketJobAdapter
|
13
|
-
def enqueue(active_job) #:nodoc:
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
job.active_job_queue = active_job.queue_name
|
18
|
-
job.description = active_job.class.name
|
19
|
-
job.priority = active_job.priority if active_job.priority
|
20
|
-
end
|
21
|
-
active_job.provider_job_id = rocket_job.id.to_s
|
22
|
-
rocket_job
|
58
|
+
def self.enqueue(active_job) #:nodoc:
|
59
|
+
job = RocketJob::Jobs::ActiveJob.create!(active_job_params(active_job))
|
60
|
+
active_job.provider_job_id = job.id.to_s if active_job.respond_to?(:provider_job_id=)
|
61
|
+
job
|
23
62
|
end
|
24
63
|
|
25
|
-
def enqueue_at(active_job, timestamp) #:nodoc:
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
job.run_at = Time.at(timestamp).utc
|
33
|
-
end
|
34
|
-
active_job.provider_job_id = rocket_job.id.to_s
|
35
|
-
rocket_job
|
64
|
+
def self.enqueue_at(active_job, timestamp) #:nodoc:
|
65
|
+
params = active_job_params(active_job)
|
66
|
+
params[:run_at] = Time.at(timestamp).utc
|
67
|
+
|
68
|
+
job = RocketJob::Jobs::ActiveJob.create!(params)
|
69
|
+
active_job.provider_job_id = job.id.to_s if active_job.respond_to?(:provider_job_id=)
|
70
|
+
job
|
36
71
|
end
|
37
72
|
|
38
|
-
|
39
|
-
field :active_job_id, type: String
|
40
|
-
field :active_job_class, type: String
|
41
|
-
field :active_job_queue, type: String
|
73
|
+
private
|
42
74
|
|
43
|
-
|
44
|
-
|
45
|
-
|
75
|
+
def self.active_job_params(active_job)
|
76
|
+
params = {
|
77
|
+
description: active_job.class.name,
|
78
|
+
data: active_job.serialize,
|
79
|
+
active_job_id: active_job.job_id,
|
80
|
+
active_job_class: active_job.class.name,
|
81
|
+
active_job_queue: active_job.queue_name,
|
82
|
+
}
|
83
|
+
params[:priority] = active_job.priority if active_job.respond_to?(:priority) && active_job.priority
|
84
|
+
params
|
46
85
|
end
|
86
|
+
|
47
87
|
end
|
48
88
|
end
|
49
89
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module RocketJob
|
2
|
+
module Jobs
|
3
|
+
# Used to wrap an Active Job
|
4
|
+
class ActiveJob < RocketJob::Job #:nodoc:
|
5
|
+
field :data, type: Hash
|
6
|
+
field :active_job_id, type: String
|
7
|
+
field :active_job_class, type: String
|
8
|
+
field :active_job_queue, type: String
|
9
|
+
|
10
|
+
def perform
|
11
|
+
::ActiveJob::Base.execute data
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -43,9 +43,10 @@ module RocketJob
|
|
43
43
|
self.priority = 40
|
44
44
|
|
45
45
|
# Number of seconds between directory scans. Default 5 mins
|
46
|
-
field :check_seconds, type: Float, default: 300.0
|
46
|
+
field :check_seconds, type: Float, default: 300.0, copy_on_restart: true
|
47
|
+
|
47
48
|
# Hash[file_name, size]
|
48
|
-
field :previous_file_names, type: Hash, default: {}
|
49
|
+
field :previous_file_names, type: Hash, default: {}, copy_on_restart: true
|
49
50
|
|
50
51
|
before_create :set_run_at
|
51
52
|
|
@@ -36,11 +36,11 @@ module RocketJob
|
|
36
36
|
|
37
37
|
# Retention intervals in seconds
|
38
38
|
# Set to nil to not
|
39
|
-
field :aborted_retention, type: Integer, default: 7.days
|
40
|
-
field :completed_retention, type: Integer, default: 7.days
|
41
|
-
field :failed_retention, type: Integer, default: 14.days
|
42
|
-
field :paused_retention, type: Integer
|
43
|
-
field :queued_retention, type: Integer
|
39
|
+
field :aborted_retention, type: Integer, default: 7.days, user_editable: true, copy_on_restart: true
|
40
|
+
field :completed_retention, type: Integer, default: 7.days, user_editable: true, copy_on_restart: true
|
41
|
+
field :failed_retention, type: Integer, default: 14.days, user_editable: true, copy_on_restart: true
|
42
|
+
field :paused_retention, type: Integer, user_editable: true, copy_on_restart: true
|
43
|
+
field :queued_retention, type: Integer, user_editable: true, copy_on_restart: true
|
44
44
|
|
45
45
|
def perform
|
46
46
|
RocketJob::Job.aborted.where(created_at: {'$lte' => aborted_retention.seconds.ago}).destroy_all if aborted_retention
|
@@ -100,7 +100,7 @@ module RocketJob
|
|
100
100
|
included do
|
101
101
|
include Restart
|
102
102
|
|
103
|
-
field :cron_schedule, type: String, class_attribute: true, user_editable: true
|
103
|
+
field :cron_schedule, type: String, class_attribute: true, user_editable: true, copy_on_restart: true
|
104
104
|
|
105
105
|
before_create :rocket_job_set_run_at
|
106
106
|
|
@@ -9,43 +9,9 @@ module RocketJob
|
|
9
9
|
|
10
10
|
included do
|
11
11
|
store_in client: 'rocketjob'
|
12
|
-
|
13
|
-
class_attribute :user_editable_fields, instance_accessor: false
|
14
|
-
self.user_editable_fields = []
|
15
12
|
end
|
16
13
|
|
17
14
|
module ClassMethods
|
18
|
-
# Defines all the fields that are accessible on the Document
|
19
|
-
# For each field that is defined, a getter and setter will be
|
20
|
-
# added as an instance method to the Document.
|
21
|
-
#
|
22
|
-
# @example Define a field.
|
23
|
-
# field :score, :type => Integer, :default => 0
|
24
|
-
#
|
25
|
-
# @param [ Symbol ] name The name of the field.
|
26
|
-
# @param [ Hash ] options The options to pass to the field.
|
27
|
-
#
|
28
|
-
# @option options [ Class ] :type The type of the field.
|
29
|
-
# @option options [ String ] :label The label for the field.
|
30
|
-
# @option options [ Object, Proc ] :default The field's default
|
31
|
-
# @option options [ Boolean ] :class_attribute Keep the fields default in a class_attribute
|
32
|
-
# @option options [ Boolean ] :user_editable Field can be edited by end users in RJMC
|
33
|
-
#
|
34
|
-
# @return [ Field ] The generated field
|
35
|
-
def field(name, options)
|
36
|
-
if options.delete(:user_editable) == true
|
37
|
-
self.user_editable_fields += [name.to_sym] unless user_editable_fields.include?(name.to_sym)
|
38
|
-
end
|
39
|
-
if options.delete(:class_attribute) == true
|
40
|
-
class_attribute(name, instance_accessor: false)
|
41
|
-
if options.has_key?(:default)
|
42
|
-
public_send("#{name}=", options[:default])
|
43
|
-
end
|
44
|
-
options[:default] = lambda { self.class.public_send(name) }
|
45
|
-
end
|
46
|
-
super(name, options)
|
47
|
-
end
|
48
|
-
|
49
15
|
# V2 Backward compatibility
|
50
16
|
# DEPRECATED
|
51
17
|
def key(name, type, options = {})
|
@@ -8,13 +8,22 @@ module RocketJob
|
|
8
8
|
extend ActiveSupport::Concern
|
9
9
|
|
10
10
|
included do
|
11
|
+
# Fields that are end user editable.
|
12
|
+
# For example are editable in Rocket Job Mission Control.
|
13
|
+
class_attribute :user_editable_fields, instance_accessor: false
|
14
|
+
self.user_editable_fields = []
|
15
|
+
|
16
|
+
# Attributes to include when copying across the attributes to a new instance on restart.
|
17
|
+
class_attribute :rocket_job_restart_attributes
|
18
|
+
self.rocket_job_restart_attributes = []
|
19
|
+
|
11
20
|
#
|
12
21
|
# User definable attributes
|
13
22
|
#
|
14
23
|
# The following attributes are set when the job is created
|
15
24
|
|
16
25
|
# Description for this job instance
|
17
|
-
field :description, type: String, class_attribute: true, user_editable: true
|
26
|
+
field :description, type: String, class_attribute: true, user_editable: true, copy_on_restart: true
|
18
27
|
|
19
28
|
# Priority of this job as it relates to other jobs [1..100]
|
20
29
|
# 1: Highest Priority
|
@@ -27,10 +36,10 @@ module RocketJob
|
|
27
36
|
# In RocketJob Pro, if a SlicedJob is running and a higher priority job
|
28
37
|
# arrives, then the current job will complete the current slices and process
|
29
38
|
# the new higher priority job
|
30
|
-
field :priority, type: Integer, default: 50, class_attribute: true, user_editable: true
|
39
|
+
field :priority, type: Integer, default: 50, class_attribute: true, user_editable: true, copy_on_restart: true
|
31
40
|
|
32
41
|
# When the job completes destroy it from both the database and the UI
|
33
|
-
field :destroy_on_complete, type: Boolean, default: true, class_attribute: true
|
42
|
+
field :destroy_on_complete, type: Boolean, default: true, class_attribute: true, user_editable: true, copy_on_restart: true
|
34
43
|
|
35
44
|
# Whether to store the results from this job
|
36
45
|
field :collect_output, type: Boolean, default: false, class_attribute: true
|
@@ -39,13 +48,13 @@ module RocketJob
|
|
39
48
|
field :run_at, type: Time
|
40
49
|
|
41
50
|
# If a job has not started by this time, destroy it
|
42
|
-
field :expires_at, type: Time
|
51
|
+
field :expires_at, type: Time, copy_on_restart: true
|
43
52
|
|
44
53
|
# Raise or lower the log level when calling the job
|
45
54
|
# Can be used to reduce log noise, especially during high volume calls
|
46
55
|
# For debugging a single job can be logged at a low level such as :trace
|
47
56
|
# Levels supported: :trace, :debug, :info, :warn, :error, :fatal
|
48
|
-
field :log_level, type: Symbol, class_attribute: true, user_editable: true
|
57
|
+
field :log_level, type: Symbol, class_attribute: true, user_editable: true, copy_on_restart: true
|
49
58
|
|
50
59
|
#
|
51
60
|
# Read-only attributes
|
@@ -150,6 +159,40 @@ module RocketJob
|
|
150
159
|
queued.or({:run_at => nil}, {:run_at.lte => Time.now})
|
151
160
|
end
|
152
161
|
|
162
|
+
# Defines all the fields that are accessible on the Document
|
163
|
+
# For each field that is defined, a getter and setter will be
|
164
|
+
# added as an instance method to the Document.
|
165
|
+
#
|
166
|
+
# @example Define a field.
|
167
|
+
# field :score, :type => Integer, :default => 0
|
168
|
+
#
|
169
|
+
# @param [ Symbol ] name The name of the field.
|
170
|
+
# @param [ Hash ] options The options to pass to the field.
|
171
|
+
#
|
172
|
+
# @option options [ Class ] :type The type of the field.
|
173
|
+
# @option options [ String ] :label The label for the field.
|
174
|
+
# @option options [ Object, Proc ] :default The field's default
|
175
|
+
# @option options [ Boolean ] :class_attribute Keep the fields default in a class_attribute
|
176
|
+
# @option options [ Boolean ] :user_editable Field can be edited by end users in RJMC
|
177
|
+
#
|
178
|
+
# @return [ Field ] The generated field
|
179
|
+
def field(name, options)
|
180
|
+
if options.delete(:user_editable) == true
|
181
|
+
self.user_editable_fields += [name.to_sym] unless user_editable_fields.include?(name.to_sym)
|
182
|
+
end
|
183
|
+
if options.delete(:class_attribute) == true
|
184
|
+
class_attribute(name, instance_accessor: false)
|
185
|
+
if options.has_key?(:default)
|
186
|
+
public_send("#{name}=", options[:default])
|
187
|
+
end
|
188
|
+
options[:default] = lambda { self.class.public_send(name) }
|
189
|
+
end
|
190
|
+
if options.delete(:copy_on_restart) == true
|
191
|
+
self.rocket_job_restart_attributes += [name.to_sym] unless rocket_job_restart_attributes.include?(name.to_sym)
|
192
|
+
end
|
193
|
+
super(name, options)
|
194
|
+
end
|
195
|
+
|
153
196
|
# DEPRECATED
|
154
197
|
def rocket_job
|
155
198
|
warn 'Replace calls to .rocket_job with calls to set class instance variables. For example: self.priority = 50'
|
@@ -21,8 +21,9 @@ module RocketJob
|
|
21
21
|
#
|
22
22
|
# # The start of the processing window
|
23
23
|
# self.processing_schedule = "30 8 * * * America/New_York"
|
24
|
+
#
|
24
25
|
# # How long the processing window is:
|
25
|
-
# self
|
26
|
+
# self.processing_duration = 12.hours
|
26
27
|
#
|
27
28
|
# def perform
|
28
29
|
# # Job will only run between 8:30am and 8:30pm Eastern
|
@@ -37,8 +38,8 @@ module RocketJob
|
|
37
38
|
extend ActiveSupport::Concern
|
38
39
|
|
39
40
|
included do
|
40
|
-
field :processing_schedule, type: String, class_attribute: true
|
41
|
-
field :processing_duration, type: Integer, class_attribute: true
|
41
|
+
field :processing_schedule, type: String, class_attribute: true, user_editable: true, copy_on_restart: true
|
42
|
+
field :processing_duration, type: Integer, class_attribute: true, user_editable: true, copy_on_restart: true
|
42
43
|
|
43
44
|
before_create :rocket_job_processing_window_set_run_at
|
44
45
|
before_retry :rocket_job_processing_window_set_run_at
|
@@ -3,49 +3,93 @@ require 'active_support/concern'
|
|
3
3
|
module RocketJob
|
4
4
|
module Plugins
|
5
5
|
# Automatically starts a new instance of this job anytime it fails, aborts, or completes.
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
6
|
+
#
|
7
|
+
# Notes:
|
8
|
+
# * Restartable jobs automatically abort if they fail. This prevents the failed job from being retried.
|
9
|
+
# - To disable this behavior, add the following empty method:
|
10
|
+
# def rocket_job_restart_abort
|
11
|
+
# end
|
12
|
+
# * On destroy this job is destroyed without starting a new instance.
|
13
|
+
# * On Abort a new instance is created.
|
14
|
+
# * Include `RocketJob::Plugins::Singleton` to prevent multiple copies of a job from running at
|
15
|
+
# the same time.
|
16
|
+
# * The job will not be restarted if:
|
17
|
+
# - A validation fails after creating the new instance of this job.
|
15
18
|
# - The job has expired.
|
19
|
+
# * Only the fields that have `copy_on_restart: true` will be passed onto the new instance of this job.
|
20
|
+
#
|
21
|
+
# Example:
|
22
|
+
#
|
23
|
+
# class RestartableJob < RocketJob::Job
|
24
|
+
# include RocketJob::Plugins::Restart
|
25
|
+
#
|
26
|
+
# # Retain the completed job under the completed tab in Rocket Job Mission Control.
|
27
|
+
# self.destroy_on_complete = false
|
28
|
+
#
|
29
|
+
# # Will be copied to the new job on restart.
|
30
|
+
# field :limit, type: Integer, copy_on_restart: true
|
31
|
+
#
|
32
|
+
# # Will _not_ be copied to the new job on restart.
|
33
|
+
# field :list, type: Array, default: [1,2,3]
|
34
|
+
#
|
35
|
+
# # Set run_at every time a new instance of the job is created.
|
36
|
+
# after_initialize set_run_at, if: :new_record?
|
37
|
+
#
|
38
|
+
# def perform
|
39
|
+
# puts "The limit is #{limit}"
|
40
|
+
# puts "The list is #{list}"
|
41
|
+
# 'DONE'
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# private
|
45
|
+
#
|
46
|
+
# # Run this job in 30 minutes.
|
47
|
+
# def set_run_at
|
48
|
+
# self.run_at = 30.minutes.from_now
|
49
|
+
# end
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# job = RestartableJob.create!(limit: 10, list: [4,5,6])
|
53
|
+
# job.reload.state
|
54
|
+
# # => :queued
|
55
|
+
#
|
56
|
+
# job.limit
|
57
|
+
# # => 10
|
58
|
+
#
|
59
|
+
# job.list
|
60
|
+
# # => [4,5,6]
|
61
|
+
#
|
62
|
+
# # Wait 30 minutes ...
|
63
|
+
#
|
64
|
+
# job.reload.state
|
65
|
+
# # => :completed
|
66
|
+
#
|
67
|
+
# # A new instance was automatically created.
|
68
|
+
# job2 = RestartableJob.last
|
69
|
+
# job2.state
|
70
|
+
# # => :queued
|
71
|
+
#
|
72
|
+
# job2.limit
|
73
|
+
# # => 10
|
74
|
+
#
|
75
|
+
# job2.list
|
76
|
+
# # => [1,2,3]
|
16
77
|
module Restart
|
17
78
|
extend ActiveSupport::Concern
|
18
79
|
|
19
80
|
included do
|
20
|
-
# Attributes to exclude when copying across the attributes to the new instance
|
21
|
-
class_attribute :rocket_job_restart_excludes
|
22
|
-
self.rocket_job_restart_excludes = %w(_id state created_at started_at completed_at failure_count worker_name percent_complete exception result run_at record_count sub_state)
|
23
|
-
|
24
81
|
after_abort :rocket_job_restart_new_instance
|
25
82
|
after_complete :rocket_job_restart_new_instance
|
26
83
|
after_fail :rocket_job_restart_abort
|
27
84
|
end
|
28
85
|
|
29
|
-
module ClassMethods
|
30
|
-
def field(name, options)
|
31
|
-
if options.delete(:copy_on_restart) == false
|
32
|
-
self.rocket_job_restart_excludes += [name.to_sym] unless rocket_job_restart_excludes.include?(name.to_sym)
|
33
|
-
end
|
34
|
-
super(name, options)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
86
|
private
|
39
87
|
|
40
88
|
# Run again in the future, even if this run fails with an exception
|
41
89
|
def rocket_job_restart_new_instance
|
90
|
+
logger.info('Job has expired. Not creating a new instance.')
|
42
91
|
return if expired?
|
43
|
-
attrs =
|
44
|
-
rocket_job_restart_excludes.each { |attr| attrs.delete(attr) }
|
45
|
-
|
46
|
-
# Copy across run_at for future dated jobs
|
47
|
-
attrs['run_at'] = run_at if run_at && (run_at > Time.now)
|
48
|
-
|
92
|
+
attrs = rocket_job_restart_attributes.reduce({}) { |attrs, attr| attrs[attr] = send(attr); attrs }
|
49
93
|
rocket_job_restart_create(attrs)
|
50
94
|
end
|
51
95
|
|
@@ -60,7 +104,7 @@ module RocketJob
|
|
60
104
|
while count < retry_limit
|
61
105
|
job = self.class.create(attrs)
|
62
106
|
if job.persisted?
|
63
|
-
logger.info("
|
107
|
+
logger.info("Created a new job instance: #{job.id}")
|
64
108
|
return true
|
65
109
|
else
|
66
110
|
logger.info('Job already active, retrying after a short sleep')
|
@@ -72,7 +116,6 @@ module RocketJob
|
|
72
116
|
false
|
73
117
|
end
|
74
118
|
|
75
|
-
|
76
119
|
end
|
77
120
|
end
|
78
121
|
end
|
@@ -49,7 +49,7 @@ module RocketJob
|
|
49
49
|
|
50
50
|
# Maximum number of times to retry this job
|
51
51
|
# 25 is approximately 3 weeks of retries
|
52
|
-
field :max_retries, type: Integer, default: 25, class_attribute: true, user_editable: true
|
52
|
+
field :max_retries, type: Integer, default: 25, class_attribute: true, user_editable: true, copy_on_restart: true
|
53
53
|
|
54
54
|
# List of times when this job failed
|
55
55
|
field :failed_times, type: Array, default: []
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module RocketJob
|
2
|
+
# Whether the current process is running inside a Rocket Job server process.
|
3
|
+
def self.server?
|
4
|
+
server
|
5
|
+
end
|
6
|
+
|
7
|
+
# When running inside a Rocket Job server process, returns
|
8
|
+
# true when Rails has been initialized.
|
9
|
+
def self.rails?
|
10
|
+
rails
|
11
|
+
end
|
12
|
+
|
13
|
+
# When running inside a Rocket Job server process, returns
|
14
|
+
# true when running standalone.
|
15
|
+
def self.standalone?
|
16
|
+
!rails
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns a human readable duration from the supplied [Float] number of seconds
|
20
|
+
def self.seconds_as_duration(seconds)
|
21
|
+
return nil unless seconds
|
22
|
+
if seconds >= 86400.0 # 1 day
|
23
|
+
"#{(seconds / 86400).to_i}d #{Time.at(seconds).strftime('%-Hh %-Mm')}"
|
24
|
+
elsif seconds >= 3600.0 # 1 hour
|
25
|
+
Time.at(seconds).strftime('%-Hh %-Mm')
|
26
|
+
elsif seconds >= 60.0 # 1 minute
|
27
|
+
Time.at(seconds).strftime('%-Mm %-Ss')
|
28
|
+
elsif seconds >= 1.0 # 1 second
|
29
|
+
"#{'%.3f' % seconds}s"
|
30
|
+
else
|
31
|
+
duration = seconds * 1000
|
32
|
+
if defined? JRuby
|
33
|
+
"#{duration.to_i}ms"
|
34
|
+
else
|
35
|
+
duration < 10.0 ? "#{'%.3f' % duration}ms" : "#{'%.1f' % duration}ms"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# private
|
41
|
+
|
42
|
+
@rails = false
|
43
|
+
@server = false
|
44
|
+
|
45
|
+
def self.server!
|
46
|
+
@server = true
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.rails!
|
50
|
+
@rails = true
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
data/lib/rocket_job/version.rb
CHANGED
data/lib/rocket_job/worker.rb
CHANGED
@@ -102,7 +102,7 @@ module RocketJob
|
|
102
102
|
job = Job.rocket_job_next_job(name, current_filter)
|
103
103
|
break unless job
|
104
104
|
|
105
|
-
|
105
|
+
SemanticLogger.named_tagged(job: job.id.to_s) do
|
106
106
|
unless job.rocket_job_work(self, false, current_filter)
|
107
107
|
processed = true
|
108
108
|
end
|
data/lib/rocketjob.rb
CHANGED
@@ -2,6 +2,7 @@ require 'semantic_logger'
|
|
2
2
|
require 'mongoid'
|
3
3
|
require 'rocket_job/extensions/mongo/logging'
|
4
4
|
require 'rocket_job/version'
|
5
|
+
require 'rocket_job/rocket_job'
|
5
6
|
|
6
7
|
# @formatter:off
|
7
8
|
module RocketJob
|
@@ -41,33 +42,11 @@ module RocketJob
|
|
41
42
|
end
|
42
43
|
|
43
44
|
module Jobs
|
45
|
+
autoload :ActiveJob, 'rocket_job/jobs/active_job'
|
44
46
|
autoload :DirmonJob, 'rocket_job/jobs/dirmon_job'
|
45
47
|
autoload :HousekeepingJob, 'rocket_job/jobs/housekeeping_job'
|
46
48
|
autoload :SimpleJob, 'rocket_job/jobs/simple_job'
|
47
49
|
end
|
48
|
-
|
49
|
-
# @formatter:on
|
50
|
-
# Returns a human readable duration from the supplied [Float] number of seconds
|
51
|
-
def self.seconds_as_duration(seconds)
|
52
|
-
return nil unless seconds
|
53
|
-
if seconds >= 86400.0 # 1 day
|
54
|
-
"#{(seconds / 86400).to_i}d #{Time.at(seconds).strftime('%-Hh %-Mm')}"
|
55
|
-
elsif seconds >= 3600.0 # 1 hour
|
56
|
-
Time.at(seconds).strftime('%-Hh %-Mm')
|
57
|
-
elsif seconds >= 60.0 # 1 minute
|
58
|
-
Time.at(seconds).strftime('%-Mm %-Ss')
|
59
|
-
elsif seconds >= 1.0 # 1 second
|
60
|
-
"#{'%.3f' % seconds}s"
|
61
|
-
else
|
62
|
-
duration = seconds * 1000
|
63
|
-
if defined? JRuby
|
64
|
-
"#{duration.to_i}ms"
|
65
|
-
else
|
66
|
-
duration < 10.0 ? "#{'%.3f' % duration}ms" : "#{'%.1f' % duration}ms"
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
50
|
end
|
72
51
|
|
73
52
|
# Add Active Job adapter for Rails
|
@@ -6,9 +6,6 @@ module Plugins
|
|
6
6
|
class RestartableJob < RocketJob::Job
|
7
7
|
include RocketJob::Plugins::Restart
|
8
8
|
|
9
|
-
# Ensure a new start_at and end_at is generated every time this job is restarted
|
10
|
-
self.rocket_job_restart_excludes += %w(start_at end_at)
|
11
|
-
|
12
9
|
field :start_at, type: Date
|
13
10
|
field :end_at, type: Date
|
14
11
|
|
@@ -153,11 +150,14 @@ module Plugins
|
|
153
150
|
assert job2 = RestartableJob.where(:id.ne => @job.id).first
|
154
151
|
assert job2.queued?, job2.attributes.ai
|
155
152
|
|
153
|
+
assert RestartableJob.rocket_job_restart_attributes.include?(:priority)
|
154
|
+
assert RestartableJob.rocket_job_restart_attributes.exclude?(:start_at)
|
155
|
+
assert RestartableJob.rocket_job_restart_attributes.exclude?(:end_at)
|
156
|
+
assert RestartableJob.rocket_job_restart_attributes.exclude?(:run_at)
|
157
|
+
|
156
158
|
# Copy across all attributes, except
|
157
|
-
|
158
|
-
|
159
|
-
next if RestartableJob.rocket_job_restart_excludes.include?(key)
|
160
|
-
assert_equal value, job2[key], "Attributes are supposed to be copied across. For #{key}"
|
159
|
+
RestartableJob.rocket_job_restart_attributes.each do |key|
|
160
|
+
assert_equal @job.send(key).to_s, job2.send(key).to_s, "Attributes are supposed to be copied across. For #{key}"
|
161
161
|
end
|
162
162
|
|
163
163
|
assert_nil job2.start_at
|
@@ -172,22 +172,6 @@ module Plugins
|
|
172
172
|
assert_nil job2.exception
|
173
173
|
refute job2.result
|
174
174
|
end
|
175
|
-
|
176
|
-
it 'copies run_at when it is in the future' do
|
177
|
-
@job = RestartableJob.create!(run_at: Time.now + 1.day, destroy_on_complete: true)
|
178
|
-
@job.perform_now
|
179
|
-
assert_equal 1, RestartableJob.count
|
180
|
-
assert job2 = RestartableJob.where(:id.ne => @job.id).first
|
181
|
-
assert job2.run_at, job2.attributes.ai
|
182
|
-
end
|
183
|
-
|
184
|
-
it 'does not copy run_at when it is in the past' do
|
185
|
-
@job = RestartableJob.create!(run_at: Time.now - 1.day, destroy_on_complete: true)
|
186
|
-
@job.perform_now
|
187
|
-
assert_equal 1, RestartableJob.count
|
188
|
-
assert job2 = RestartableJob.where(:id.ne => @job.id).first
|
189
|
-
assert_nil job2.run_at
|
190
|
-
end
|
191
175
|
end
|
192
176
|
|
193
177
|
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.2.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-
|
11
|
+
date: 2017-04-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -89,6 +89,7 @@ files:
|
|
89
89
|
- lib/rocket_job/heartbeat.rb
|
90
90
|
- lib/rocket_job/job.rb
|
91
91
|
- lib/rocket_job/job_exception.rb
|
92
|
+
- lib/rocket_job/jobs/active_job.rb
|
92
93
|
- lib/rocket_job/jobs/dirmon_job.rb
|
93
94
|
- lib/rocket_job/jobs/housekeeping_job.rb
|
94
95
|
- lib/rocket_job/jobs/simple_job.rb
|
@@ -110,6 +111,7 @@ files:
|
|
110
111
|
- lib/rocket_job/plugins/rufus/zo_time.rb
|
111
112
|
- lib/rocket_job/plugins/singleton.rb
|
112
113
|
- lib/rocket_job/plugins/state_machine.rb
|
114
|
+
- lib/rocket_job/rocket_job.rb
|
113
115
|
- lib/rocket_job/server.rb
|
114
116
|
- lib/rocket_job/version.rb
|
115
117
|
- lib/rocket_job/worker.rb
|