rocketjob 2.1.3 → 3.0.0.alpha
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/README.md +36 -0
- data/lib/rocket_job/active_server.rb +48 -0
- data/lib/rocket_job/cli.rb +29 -17
- data/lib/rocket_job/config.rb +19 -31
- data/lib/rocket_job/dirmon_entry.rb +15 -45
- data/lib/rocket_job/extensions/mongo/logging.rb +26 -0
- data/lib/rocket_job/extensions/rocket_job_adapter.rb +3 -5
- data/lib/rocket_job/heartbeat.rb +18 -23
- data/lib/rocket_job/job.rb +0 -1
- data/lib/rocket_job/job_exception.rb +11 -13
- data/lib/rocket_job/jobs/dirmon_job.rb +8 -8
- data/lib/rocket_job/jobs/housekeeping_job.rb +13 -15
- data/lib/rocket_job/performance.rb +5 -5
- data/lib/rocket_job/plugins/cron.rb +3 -10
- data/lib/rocket_job/plugins/document.rb +58 -33
- data/lib/rocket_job/plugins/job/model.rb +43 -71
- data/lib/rocket_job/plugins/job/persistence.rb +7 -63
- data/lib/rocket_job/plugins/job/worker.rb +24 -26
- data/lib/rocket_job/plugins/processing_window.rb +6 -9
- data/lib/rocket_job/plugins/retry.rb +3 -8
- data/lib/rocket_job/plugins/singleton.rb +1 -1
- data/lib/rocket_job/plugins/state_machine.rb +1 -7
- data/lib/rocket_job/server.rb +352 -0
- data/lib/rocket_job/version.rb +1 -1
- data/lib/rocket_job/worker.rb +46 -336
- data/lib/rocketjob.rb +5 -4
- data/test/config/mongoid.yml +88 -0
- data/test/config_test.rb +1 -1
- data/test/dirmon_entry_test.rb +15 -79
- data/test/dirmon_job_test.rb +6 -6
- data/test/job_test.rb +2 -2
- data/test/plugins/job/callbacks_test.rb +40 -32
- data/test/plugins/job/defaults_test.rb +10 -8
- data/test/plugins/job/model_test.rb +1 -3
- data/test/plugins/job/persistence_test.rb +11 -13
- data/test/plugins/job/worker_test.rb +45 -26
- data/test/plugins/processing_window_test.rb +4 -4
- data/test/plugins/restart_test.rb +11 -12
- data/test/plugins/state_machine_event_callbacks_test.rb +20 -18
- data/test/plugins/state_machine_test.rb +5 -5
- data/test/test_helper.rb +4 -1
- metadata +15 -29
- data/lib/rocket_job/extensions/mongo.rb +0 -23
- data/lib/rocket_job/extensions/mongo_mapper.rb +0 -30
- data/lib/rocket_job/plugins/job/defaults.rb +0 -40
- data/test/config/mongo.yml +0 -46
data/lib/rocket_job/heartbeat.rb
CHANGED
@@ -2,46 +2,41 @@
|
|
2
2
|
module RocketJob
|
3
3
|
# Heartbeat
|
4
4
|
#
|
5
|
-
# Information from the
|
5
|
+
# Information from the server as at it's last heartbeat
|
6
6
|
class Heartbeat
|
7
|
-
include
|
7
|
+
include Plugins::Document
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
# @formatter:off
|
12
|
-
# Time of the last heartbeat received from this worker
|
13
|
-
key :updated_at, Time
|
9
|
+
# Time of the last heartbeat received from this server
|
10
|
+
field :updated_at, type: Time
|
14
11
|
|
15
12
|
# Number of threads running as at the last heartbeat interval
|
16
|
-
|
13
|
+
field :active_threads, type: Integer
|
17
14
|
# Number of threads in the pool
|
18
|
-
# This number should grow and shrink between 1 and :
|
19
|
-
|
15
|
+
# This number should grow and shrink between 1 and :max_workers
|
16
|
+
field :current_threads, type: Integer
|
20
17
|
|
21
18
|
#
|
22
|
-
# Process Information
|
19
|
+
# Process Information. Future.
|
23
20
|
#
|
24
21
|
|
25
|
-
# Percentage utilization for the
|
26
|
-
|
27
|
-
# Kilo Bytes used by the
|
28
|
-
|
29
|
-
|
22
|
+
# Percentage utilization for the server process alone
|
23
|
+
#field :process_cpu, type: Integer
|
24
|
+
# Kilo Bytes used by the server process (Virtual & Physical)
|
25
|
+
#field :process_mem_phys_kb, type: Integer
|
26
|
+
#field :process_mem_virt_kb, type: Integer
|
30
27
|
|
31
28
|
#
|
32
|
-
# System Information
|
29
|
+
# System Information. Future.
|
33
30
|
#
|
34
31
|
|
35
32
|
# Percentage utilization for the host machine
|
36
|
-
|
33
|
+
#field :host_cpu, type: Integer
|
37
34
|
# Kilo Bytes Available on the host machine (Physical)
|
38
|
-
|
39
|
-
|
35
|
+
#field :host_mem_avail_phys_kbytes, type: Float
|
36
|
+
#field :host_mem_avail_virt_kbytes, type: Float
|
40
37
|
|
41
38
|
# If available
|
42
|
-
|
43
|
-
# @formatter:on
|
44
|
-
|
39
|
+
#field :load_average, type: Float
|
45
40
|
end
|
46
41
|
end
|
47
42
|
|
data/lib/rocket_job/job.rb
CHANGED
@@ -1,28 +1,26 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
module RocketJob
|
3
|
-
# Heartbeat
|
4
|
-
#
|
5
|
-
# Information from the worker as at it's last heartbeat
|
6
3
|
class JobException
|
7
|
-
include
|
4
|
+
include Plugins::Document
|
5
|
+
|
6
|
+
embedded_in :job, inverse_of: :exception
|
7
|
+
embedded_in :slice, inverse_of: :exception
|
8
|
+
embedded_in :dirmon_entry, inverse_of: :exception
|
8
9
|
|
9
|
-
# @formatter:off
|
10
10
|
# Name of the exception class
|
11
|
-
|
11
|
+
field :class_name, type: String
|
12
12
|
|
13
13
|
# Exception message
|
14
|
-
|
14
|
+
field :message, type: String
|
15
15
|
|
16
16
|
# Exception Backtrace [Array<String>]
|
17
|
-
|
17
|
+
field :backtrace, type: Array, default: []
|
18
18
|
|
19
|
-
# Name of the
|
20
|
-
|
19
|
+
# Name of the server on which this exception occurred
|
20
|
+
field :worker_name, type: String
|
21
21
|
|
22
22
|
# The record within which this exception occurred
|
23
|
-
|
24
|
-
|
25
|
-
# @formatter:on
|
23
|
+
field :record_number, type: Integer
|
26
24
|
|
27
25
|
# Returns [JobException] built from the supplied exception
|
28
26
|
def self.from_exception(exc)
|
@@ -15,10 +15,11 @@ module RocketJob
|
|
15
15
|
|
16
16
|
# * Otherwise, the file is moved to the supplied archive_directory (defaults to
|
17
17
|
# `_archive` in the same folder as the file itself. The absolute path and
|
18
|
-
# file name of the archived file is passed into the job as
|
18
|
+
# file name of the archived file is passed into the job as either
|
19
|
+
# `upload_file_name` or `full_file_name`.
|
19
20
|
|
20
21
|
# Note:
|
21
|
-
# - Jobs that do not implement #upload _must_ have
|
22
|
+
# - Jobs that do not implement #upload _must_ have either `upload_file_name` or `full_file_name` as an attribute.
|
22
23
|
#
|
23
24
|
# With RocketJob Pro, the file is automatically uploaded into the job itself
|
24
25
|
# using the job's #upload method, after which the file is archived or deleted
|
@@ -39,13 +40,12 @@ module RocketJob
|
|
39
40
|
# Start a new job when this one completes, fails, or aborts
|
40
41
|
include RocketJob::Plugins::Restart
|
41
42
|
|
42
|
-
|
43
|
-
job.priority = 40
|
44
|
-
end
|
43
|
+
self.priority = 40
|
45
44
|
|
46
45
|
# Number of seconds between directory scans. Default 5 mins
|
47
|
-
|
48
|
-
|
46
|
+
field :check_seconds, type: Float, default: 300.0
|
47
|
+
# Hash[file_name, size]
|
48
|
+
field :previous_file_names, type: Hash, default: {}
|
49
49
|
|
50
50
|
before_create :set_run_at
|
51
51
|
|
@@ -68,7 +68,7 @@ module RocketJob
|
|
68
68
|
# since the last run
|
69
69
|
def check_directories
|
70
70
|
new_file_names = {}
|
71
|
-
DirmonEntry.
|
71
|
+
DirmonEntry.enabled.each do |entry|
|
72
72
|
entry.each do |pathname|
|
73
73
|
# BSON Keys cannot contain periods
|
74
74
|
key = pathname.to_s.gsub('.', '_')
|
@@ -30,26 +30,24 @@ module RocketJob
|
|
30
30
|
include RocketJob::Plugins::Cron
|
31
31
|
include RocketJob::Plugins::Singleton
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
job.cron_schedule = '0 0 * * * America/New_York'
|
37
|
-
end
|
33
|
+
self.priority = 50
|
34
|
+
self.description = 'Cleans out historical jobs'
|
35
|
+
self.cron_schedule = '0 0 * * * America/New_York'
|
38
36
|
|
39
37
|
# Retention intervals in seconds
|
40
38
|
# Set to nil to not
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
39
|
+
field :aborted_retention, Integer, default: 7.days
|
40
|
+
field :completed_retention, Integer, default: 7.days
|
41
|
+
field :failed_retention, Integer, default: 14.days
|
42
|
+
field :paused_retention, Integer, default: 90.days
|
43
|
+
field :queued_retention, Integer
|
46
44
|
|
47
45
|
def perform
|
48
|
-
RocketJob::Job.where(
|
49
|
-
RocketJob::Job.where(
|
50
|
-
RocketJob::Job.where(
|
51
|
-
RocketJob::Job.where(
|
52
|
-
RocketJob::Job.where(
|
46
|
+
RocketJob::Job.aborted.where(created_at: {'$lte' => aborted_retention.ago}).destroy_all if aborted_retention
|
47
|
+
RocketJob::Job.completed.where(created_at: {'$lte' => completed_retention.ago}).destroy_all if completed_retention
|
48
|
+
RocketJob::Job.failed.where(created_at: {'$lte' => failed_retention.ago}).destroy_all if failed_retention
|
49
|
+
RocketJob::Job.paused.where(created_at: {'$lte' => paused_retention.ago}).destroy_all if paused_retention
|
50
|
+
RocketJob::Job.queued.where(created_at: {'$lte' => queued_retention.ago}).destroy_all if queued_retention
|
53
51
|
end
|
54
52
|
|
55
53
|
end
|
@@ -15,12 +15,12 @@ module RocketJob
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def run_test_case(count = self.count)
|
18
|
-
self.worker_processes = RocketJob::
|
18
|
+
self.worker_processes = RocketJob::Server.count
|
19
19
|
raise 'Please start workers before starting the performance test' if worker_processes == 0
|
20
20
|
|
21
21
|
self.worker_processes = 0
|
22
22
|
self.worker_threads = 0
|
23
|
-
RocketJob::
|
23
|
+
RocketJob::Server.running.each do |worker_process|
|
24
24
|
unless worker_process.zombie?
|
25
25
|
self.worker_processes += 1
|
26
26
|
self.worker_threads += worker_process.heartbeat.current_threads
|
@@ -29,7 +29,7 @@ module RocketJob
|
|
29
29
|
puts "Running: #{worker_threads} workers, distributed across #{worker_processes} processes"
|
30
30
|
|
31
31
|
puts 'Waiting for workers to pause'
|
32
|
-
RocketJob::
|
32
|
+
RocketJob::Server.pause_all
|
33
33
|
RocketJob::Jobs::SimpleJob.delete_all
|
34
34
|
sleep 15
|
35
35
|
|
@@ -39,7 +39,7 @@ module RocketJob
|
|
39
39
|
last = RocketJob::Jobs::SimpleJob.create(priority: 100, destroy_on_complete: false)
|
40
40
|
|
41
41
|
puts 'Resuming workers'
|
42
|
-
RocketJob::
|
42
|
+
RocketJob::Server.resume_all
|
43
43
|
|
44
44
|
while (!last.reload.completed?)
|
45
45
|
sleep 3
|
@@ -63,7 +63,7 @@ module RocketJob
|
|
63
63
|
o.on('-c', '--count COUNT', 'Count of jobs to enqueue') do |arg|
|
64
64
|
self.count = arg.to_i
|
65
65
|
end
|
66
|
-
o.on('-m', '--mongo MONGO_CONFIG_FILE_NAME', '
|
66
|
+
o.on('-m', '--mongo MONGO_CONFIG_FILE_NAME', 'Path and filename of config file. Default: config/mongoid.yml') do |arg|
|
67
67
|
self.mongo_config = arg
|
68
68
|
end
|
69
69
|
o.on('-e', '--environment ENVIRONMENT', 'The environment to run the app on (Default: RAILS_ENV || RACK_ENV || development)') do |arg|
|
@@ -40,9 +40,7 @@ module RocketJob
|
|
40
40
|
# include RocketJob::Plugins::Cron
|
41
41
|
#
|
42
42
|
# # Set the default cron_schedule
|
43
|
-
#
|
44
|
-
# job.cron_schedule = "* 1 * * * UTC"
|
45
|
-
# end
|
43
|
+
# self.cron_schedule = "* 1 * * * UTC"
|
46
44
|
#
|
47
45
|
# def perform
|
48
46
|
# puts "DONE"
|
@@ -70,9 +68,7 @@ module RocketJob
|
|
70
68
|
# include RocketJob::Plugins::Singleton
|
71
69
|
#
|
72
70
|
# # Set the default cron_schedule
|
73
|
-
#
|
74
|
-
# job.cron_schedule = "* 1 * * * UTC"
|
75
|
-
# end
|
71
|
+
# self.cron_schedule = "* 1 * * * UTC"
|
76
72
|
#
|
77
73
|
# def perform
|
78
74
|
# puts "DONE"
|
@@ -105,10 +101,7 @@ module RocketJob
|
|
105
101
|
included do
|
106
102
|
include Restart
|
107
103
|
|
108
|
-
|
109
|
-
|
110
|
-
# Make cron_schedule editable for scheduled jobs
|
111
|
-
public_rocket_job_properties :cron_schedule
|
104
|
+
field :cron_schedule, type: String, class_attribute: true, user_editable: true
|
112
105
|
|
113
106
|
before_create :rocket_job_set_run_at
|
114
107
|
|
@@ -1,57 +1,82 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
require 'active_support/concern'
|
3
|
-
require 'mongo'
|
4
|
-
require 'mongo_ha'
|
5
|
-
begin
|
6
|
-
require 'active_model/serializers/xml'
|
7
|
-
rescue LoadError
|
8
|
-
raise "Please add gem 'activemodel-serializers-xml' to Gemfile to support Active Model V5"
|
9
|
-
end
|
10
|
-
require 'mongo_mapper'
|
11
3
|
|
12
4
|
module RocketJob
|
13
5
|
module Plugins
|
14
6
|
# Base class for storing models in MongoDB
|
15
7
|
module Document
|
16
8
|
extend ActiveSupport::Concern
|
17
|
-
include
|
9
|
+
include Mongoid::Document
|
18
10
|
|
19
11
|
included do
|
20
|
-
|
21
|
-
self.static_keys = true
|
22
|
-
|
23
|
-
# Only save changes to this instance to prevent losing
|
24
|
-
# changes made by other processes or threads.
|
25
|
-
self.partial_updates = true
|
12
|
+
store_in client: 'rocketjob'
|
26
13
|
|
27
|
-
|
28
|
-
|
14
|
+
class_attribute :user_editable_fields, instance_accessor: false
|
15
|
+
self.user_editable_fields = []
|
29
16
|
end
|
30
17
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
18
|
+
module ClassMethods
|
19
|
+
# Defines all the fields that are accessible on the Document
|
20
|
+
# For each field that is defined, a getter and setter will be
|
21
|
+
# added as an instance method to the Document.
|
22
|
+
#
|
23
|
+
# @example Define a field.
|
24
|
+
# field :score, :type => Integer, :default => 0
|
25
|
+
#
|
26
|
+
# @param [ Symbol ] name The name of the field.
|
27
|
+
# @param [ Hash ] options The options to pass to the field.
|
28
|
+
#
|
29
|
+
# @option options [ Class ] :type The type of the field.
|
30
|
+
# @option options [ String ] :label The label for the field.
|
31
|
+
# @option options [ Object, Proc ] :default The field's default
|
32
|
+
# @option options [ Boolean ] :class_attribute Keep the fields default in a class_attribute
|
33
|
+
# @option options [ Boolean ] :user_editable Field can be edited by end users in RJMC
|
34
|
+
#
|
35
|
+
# @return [ Field ] The generated field
|
36
|
+
def field(name, options)
|
37
|
+
if options.delete(:user_editable) == true
|
38
|
+
self.user_editable_fields += [name.to_sym] unless user_editable_fields.include?(name.to_sym)
|
39
|
+
end
|
40
|
+
if options.delete(:class_attribute) == true
|
41
|
+
class_attribute(name, instance_accessor: false)
|
42
|
+
if options.has_key?(:default)
|
43
|
+
public_send("#{name}=", options[:default])
|
44
|
+
end
|
45
|
+
options[:default] = lambda { self.class.public_send(name) }
|
46
|
+
end
|
47
|
+
super(name, options)
|
48
|
+
end
|
49
|
+
|
50
|
+
# V2 Backward compatibility
|
51
|
+
# DEPRECATED
|
52
|
+
def key(name, type, options = {})
|
53
|
+
field(name, options.merge(type: type))
|
54
|
+
end
|
55
|
+
|
56
|
+
# Mongoid does not apply ordering, add sort
|
57
|
+
def first
|
58
|
+
all.sort('_id' => 1).first
|
59
|
+
end
|
60
|
+
|
61
|
+
# Mongoid does not apply ordering, add sort
|
62
|
+
def last
|
63
|
+
all.sort('_id' => -1).first
|
41
64
|
end
|
42
65
|
end
|
43
66
|
|
44
67
|
private
|
45
68
|
|
46
|
-
|
47
|
-
|
69
|
+
# Apply changes to this document returning the updated document from the database.
|
70
|
+
# Allows other changes to be made on the server that will be loaded.
|
71
|
+
def find_and_update(attrs)
|
72
|
+
if doc = collection.find(_id: id).find_one_and_update({'$set' => attrs}, return_document: :after)
|
48
73
|
# Clear out keys that are not returned during the reload from MongoDB
|
49
|
-
(keys.keys - doc.keys).each { |key| send("#{key}=", nil) }
|
50
|
-
|
51
|
-
|
74
|
+
(fields.keys + embedded_relations.keys - doc.keys).each { |key| send("#{key}=", nil) }
|
75
|
+
@attributes = attributes
|
76
|
+
apply_defaults
|
52
77
|
self
|
53
78
|
else
|
54
|
-
raise
|
79
|
+
raise Mongoid::Error::DocumentNotFound, "Document match #{_id.inspect} does not exist in #{collection.name} collection"
|
55
80
|
end
|
56
81
|
end
|
57
82
|
|
@@ -13,10 +13,9 @@ module RocketJob
|
|
13
13
|
# User definable attributes
|
14
14
|
#
|
15
15
|
# The following attributes are set when the job is created
|
16
|
-
# @formatter:off
|
17
16
|
|
18
17
|
# Description for this job instance
|
19
|
-
|
18
|
+
field :description, type: String, class_attribute: true, user_editable: true
|
20
19
|
|
21
20
|
# Priority of this job as it relates to other jobs [1..100]
|
22
21
|
# 1: Highest Priority
|
@@ -29,64 +28,47 @@ module RocketJob
|
|
29
28
|
# In RocketJob Pro, if a SlicedJob is running and a higher priority job
|
30
29
|
# arrives, then the current job will complete the current slices and process
|
31
30
|
# the new higher priority job
|
32
|
-
|
33
|
-
|
34
|
-
# Run this job no earlier than this time
|
35
|
-
key :run_at, Time
|
36
|
-
|
37
|
-
# If a job has not started by this time, destroy it
|
38
|
-
key :expires_at, Time
|
31
|
+
field :priority, type: Integer, default: 50, class_attribute: true, user_editable: true
|
39
32
|
|
40
33
|
# When the job completes destroy it from both the database and the UI
|
41
|
-
|
42
|
-
|
43
|
-
# Any user supplied arguments for the method invocation
|
44
|
-
# All keys must be UTF-8 strings. The values can be any valid BSON type:
|
45
|
-
# Integer
|
46
|
-
# Float
|
47
|
-
# Time (UTC)
|
48
|
-
# String (UTF-8)
|
49
|
-
# Array
|
50
|
-
# Hash
|
51
|
-
# True
|
52
|
-
# False
|
53
|
-
# Symbol
|
54
|
-
# nil
|
55
|
-
# Regular Expression
|
56
|
-
#
|
57
|
-
# Note: Date is not supported, convert it to a UTC time
|
58
|
-
key :arguments, Array
|
34
|
+
field :destroy_on_complete, type: Boolean, default: true, class_attribute: true
|
59
35
|
|
60
36
|
# Whether to store the results from this job
|
61
|
-
|
37
|
+
field :collect_output, type: Boolean, default: false, class_attribute: true
|
38
|
+
|
39
|
+
# Run this job no earlier than this time
|
40
|
+
field :run_at, type: Time
|
41
|
+
|
42
|
+
# If a job has not started by this time, destroy it
|
43
|
+
field :expires_at, type: Time
|
62
44
|
|
63
45
|
# Raise or lower the log level when calling the job
|
64
46
|
# Can be used to reduce log noise, especially during high volume calls
|
65
47
|
# For debugging a single job can be logged at a low level such as :trace
|
66
48
|
# Levels supported: :trace, :debug, :info, :warn, :error, :fatal
|
67
|
-
|
49
|
+
field :log_level, type: Symbol, user_editable: true
|
68
50
|
|
69
51
|
#
|
70
52
|
# Read-only attributes
|
71
53
|
#
|
72
54
|
|
73
55
|
# Current state, as set by the state machine. Do not modify this value directly.
|
74
|
-
|
56
|
+
field :state, type: Symbol, default: :queued
|
75
57
|
|
76
58
|
# When the job was created
|
77
|
-
|
59
|
+
field :created_at, type: Time, default: -> { Time.now }
|
78
60
|
|
79
61
|
# When processing started on this job
|
80
|
-
|
62
|
+
field :started_at, type: Time
|
81
63
|
|
82
64
|
# When the job completed processing
|
83
|
-
|
65
|
+
field :completed_at, type: Time
|
84
66
|
|
85
67
|
# Number of times that this job has failed to process
|
86
|
-
|
68
|
+
field :failure_count, type: Integer, default: 0
|
87
69
|
|
88
70
|
# This name of the worker that this job is being processed by, or was processed by
|
89
|
-
|
71
|
+
field :worker_name, type: String
|
90
72
|
|
91
73
|
#
|
92
74
|
# Values that jobs can update during processing
|
@@ -94,38 +76,37 @@ module RocketJob
|
|
94
76
|
|
95
77
|
# Allow a job to updates its estimated progress
|
96
78
|
# Any integer from 0 to 100
|
97
|
-
|
79
|
+
field :percent_complete, type: Integer, default: 0
|
98
80
|
|
99
81
|
# Store the last exception for this job
|
100
|
-
|
82
|
+
embeds_one :exception, class_name: 'RocketJob::JobException'
|
101
83
|
|
102
84
|
# Store the Hash result from this job if collect_output is true,
|
103
85
|
# and the job returned actually returned a Hash, otherwise nil
|
104
86
|
# Not applicable to SlicedJob jobs, since its output is stored in a
|
105
87
|
# separate collection
|
106
|
-
|
88
|
+
field :result, type: Hash
|
107
89
|
|
108
|
-
|
109
|
-
|
110
|
-
# Store all job types in this collection
|
111
|
-
set_collection_name 'rocket_job.jobs'
|
90
|
+
index({state: 1, priority: 1, _id: 1}, background: true)
|
112
91
|
|
113
92
|
validates_presence_of :state, :failure_count, :created_at
|
114
93
|
validates :priority, inclusion: 1..100
|
115
94
|
validates :log_level, inclusion: SemanticLogger::LEVELS + [nil]
|
95
|
+
end
|
116
96
|
|
97
|
+
module ClassMethods
|
117
98
|
# Returns [String] the singular name for this job class
|
118
99
|
#
|
119
100
|
# Example:
|
120
101
|
# job = DataStudyJob.new
|
121
102
|
# job.underscore_name
|
122
103
|
# # => "data_study"
|
123
|
-
def
|
104
|
+
def underscore_name
|
124
105
|
@underscore_name ||= name.sub(/Job$/, '').underscore
|
125
106
|
end
|
126
107
|
|
127
108
|
# Allow the collective name for this job class to be overridden
|
128
|
-
def
|
109
|
+
def underscore_name=(underscore_name)
|
129
110
|
@underscore_name = underscore_name
|
130
111
|
end
|
131
112
|
|
@@ -135,12 +116,12 @@ module RocketJob
|
|
135
116
|
# job = DataStudyJob.new
|
136
117
|
# job.human_name
|
137
118
|
# # => "Data Study"
|
138
|
-
def
|
119
|
+
def human_name
|
139
120
|
@human_name ||= name.sub(/Job$/, '').titleize
|
140
121
|
end
|
141
122
|
|
142
123
|
# Allow the human readable job name for this job class to be overridden
|
143
|
-
def
|
124
|
+
def human_name=(human_name)
|
144
125
|
@human_name = human_name
|
145
126
|
end
|
146
127
|
|
@@ -150,49 +131,40 @@ module RocketJob
|
|
150
131
|
# job = DataStudyJob.new
|
151
132
|
# job.collective_name
|
152
133
|
# # => "data_studies"
|
153
|
-
def
|
134
|
+
def collective_name
|
154
135
|
@collective_name ||= name.sub(/Job$/, '').pluralize.underscore
|
155
136
|
end
|
156
137
|
|
157
138
|
# Allow the collective name for this job class to be overridden
|
158
|
-
def
|
139
|
+
def collective_name=(collective_name)
|
159
140
|
@collective_name = collective_name
|
160
141
|
end
|
161
142
|
|
162
143
|
# Scope for jobs scheduled to run in the future
|
163
|
-
def
|
164
|
-
queued.where(run_at
|
144
|
+
def scheduled
|
145
|
+
queued.where(:run_at.gt => Time.now)
|
165
146
|
end
|
166
147
|
|
167
148
|
# Scope for queued jobs that can run now
|
168
149
|
# I.e. Queued jobs excluding scheduled jobs
|
169
|
-
def
|
170
|
-
queued.
|
171
|
-
|
172
|
-
|
173
|
-
{run_at: {'$lte' => Time.now}}
|
174
|
-
]
|
150
|
+
def queued_now
|
151
|
+
queued.or(
|
152
|
+
{:run_at.exists => false},
|
153
|
+
{:run_at.lte => Time.now}
|
175
154
|
)
|
176
155
|
end
|
177
156
|
|
178
|
-
#
|
179
|
-
def
|
180
|
-
|
157
|
+
# DEPRECATED
|
158
|
+
def rocket_job
|
159
|
+
warn 'Replace calls to .rocket_job with calls to set class instance variables. For example: self.priority = 50'
|
160
|
+
yield(self)
|
181
161
|
end
|
182
162
|
|
183
|
-
#
|
184
|
-
def
|
185
|
-
|
163
|
+
# DEPRECATED
|
164
|
+
def public_rocket_job_properties(*args)
|
165
|
+
warn "Replace calls to .public_rocket_job_properties by adding `user_editable: true` option to the field declaration in #{name} for: #{args.inspect}"
|
166
|
+
self.user_editable_fields += args.collect(&:to_sym)
|
186
167
|
end
|
187
|
-
|
188
|
-
# Add to user definable properties in Dirmon Entry
|
189
|
-
def self.public_rocket_job_properties(*properties)
|
190
|
-
properties.each { |property| raise("Invalid public_rocket_job_property: #{property.inspect}") unless key?(property)}
|
191
|
-
rocket_job_properties.concat(properties).uniq!
|
192
|
-
end
|
193
|
-
|
194
|
-
# User definable properties in Dirmon Entry
|
195
|
-
public_rocket_job_properties :description, :priority, :log_level, :arguments
|
196
168
|
end
|
197
169
|
|
198
170
|
# Returns [true|false] whether to collect nil results from running this batch
|