navvy 0.0.0 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +9 -1
- data/Rakefile +21 -5
- data/VERSION +1 -1
- data/generators/navvy/navvy_generator.rb +15 -0
- data/generators/navvy/templates/migration.rb +20 -0
- data/lib/generators/navvy_generator.rb +20 -0
- data/lib/navvy.rb +2 -2
- data/lib/navvy/job/active_record.rb +212 -0
- data/lib/navvy/job/mongo_mapper.rb +146 -27
- data/lib/navvy/job/sequel.rb +200 -0
- data/lib/navvy/log.rb +60 -0
- data/lib/navvy/tasks.rb +13 -0
- data/lib/navvy/worker.rb +21 -6
- data/navvy.gemspec +26 -8
- data/spec/job/active_record_spec.rb +325 -0
- data/spec/job/mongo_mapper_spec.rb +232 -18
- data/spec/job/sequel_spec.rb +324 -0
- data/spec/log_spec.rb +71 -0
- data/spec/setup/active_record.rb +20 -0
- data/spec/setup/sequel.rb +21 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/worker_spec.rb +5 -5
- metadata +39 -14
- data/lib/job/mongo_mapper.rb +0 -74
- data/lib/navvy/job.rb +0 -16
data/README.textile
CHANGED
@@ -1,9 +1,17 @@
|
|
1
1
|
h1. Navvy
|
2
2
|
|
3
|
-
Navvy is a simple background job processor inspired by "delayed_job":http://github.com/tobi/delayed_job, but aiming for database agnosticism.
|
3
|
+
Navvy is a simple background job processor inspired by "delayed_job":http://github.com/tobi/delayed_job, but aiming for database agnosticism. Currently Navvy supports ActiveRecord, MongoMapper and Sequel but it's extremely easy to write an adapter for your favorite ORM. Also, It completely supports Rails Edge.
|
4
4
|
|
5
5
|
??“Navvy is a shorter form of navigator (UK) or navigational engineer (USA) and is particularly applied to describe the manual labourers working on major civil engineering projects. The term was coined in the late 18th century in Britain when numerous canals were being built, which were also sometimes known as "navigations". Canal navvies typically worked with shovels, pickaxes and barrows.”?? - "Wikipedia":http://en.wikipedia.org/wiki/Navvy
|
6
6
|
|
7
|
+
h2. Using Navvy
|
8
|
+
|
9
|
+
There's an "Installation Guide":http://wiki.github.com/jeffkreeftmeijer/navvy/installation (also for "Rails 3":http://wiki.github.com/jeffkreeftmeijer/navvy/installation-on-rails-edge) and a "Getting Started Guide":http://wiki.github.com/jeffkreeftmeijer/navvy/getting-started to put you on the right track. Any questions? Don't hesitate to "ask":http://github.com/inbox/new/jeffkreeftmeijer.
|
10
|
+
|
11
|
+
h2. Contributing
|
12
|
+
|
13
|
+
Found any issues? Have a great idea? Want to help? Great! Create an issue "issue":http://github.com/jeffkreeftmeijer/navvy/issues for it, or even better; "fork the project":http://github.com/jeffkreeftmeijer/navvy/fork. Pull requests are always welcome. :)
|
14
|
+
|
7
15
|
h2. License
|
8
16
|
|
9
17
|
Copyright (c) 2009 Jeff Kreeftmeijer, released under the MIT license
|
data/Rakefile
CHANGED
@@ -10,12 +10,13 @@ begin
|
|
10
10
|
gem.email = "jeff@kreeftmeijer.nl"
|
11
11
|
gem.homepage = "http://github.com/jeffkreeftmeijer/navvy"
|
12
12
|
gem.authors = ["Jeff Kreeftmeijer"]
|
13
|
-
gem.add_dependency "mongo_mapper", ">= 0.6.10"
|
14
13
|
gem.add_development_dependency "rspec", ">= 1.2.9"
|
15
14
|
gem.add_development_dependency "yard", ">= 0.5.2"
|
16
15
|
gem.add_development_dependency "metric_fu", ">= 1.1.6"
|
17
16
|
gem.add_development_dependency "machinist", ">= 1.0.6"
|
17
|
+
gem.add_development_dependency "mongo_mapper", ">= 0.6.10"
|
18
18
|
gem.add_development_dependency "machinist_mongomapper", ">= 0.9.7"
|
19
|
+
gem.add_development_dependency "sequel", ">= 3.8.0"
|
19
20
|
end
|
20
21
|
Jeweler::GemcutterTasks.new
|
21
22
|
rescue LoadError
|
@@ -23,9 +24,25 @@ rescue LoadError
|
|
23
24
|
end
|
24
25
|
|
25
26
|
require 'spec/rake/spectask'
|
26
|
-
|
27
|
-
|
28
|
-
spec
|
27
|
+
|
28
|
+
task :spec do
|
29
|
+
['spec:active_record', 'spec:mongo_mapper', 'spec:sequel'].each do |spec|
|
30
|
+
Rake::Task[spec].invoke
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
namespace :spec do
|
35
|
+
Spec::Rake::SpecTask.new(:active_record) do |spec|
|
36
|
+
spec.spec_files = FileList['spec/job/active_record_spec.rb', 'spec/*_spec.rb']
|
37
|
+
end
|
38
|
+
|
39
|
+
Spec::Rake::SpecTask.new(:mongo_mapper) do |spec|
|
40
|
+
spec.spec_files = FileList['spec/job/mongo_mapper_spec.rb', 'spec/*_spec.rb']
|
41
|
+
end
|
42
|
+
|
43
|
+
Spec::Rake::SpecTask.new(:sequel) do |spec|
|
44
|
+
spec.spec_files = FileList['spec/job/sequel_spec.rb', 'spec/*_spec.rb']
|
45
|
+
end
|
29
46
|
end
|
30
47
|
|
31
48
|
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
@@ -35,7 +52,6 @@ Spec::Rake::SpecTask.new(:rcov) do |spec|
|
|
35
52
|
end
|
36
53
|
|
37
54
|
task :spec => :check_dependencies
|
38
|
-
|
39
55
|
task :default => :spec
|
40
56
|
|
41
57
|
begin
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.1.0
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class NavvyGenerator < Rails::Generator::Base
|
2
|
+
def manifest
|
3
|
+
record do |m|
|
4
|
+
options = {
|
5
|
+
:migration_file_name => 'create_jobs'
|
6
|
+
}
|
7
|
+
|
8
|
+
m.migration_template 'migration.rb', 'db/migrate', options
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def banner
|
13
|
+
"Usage: #{$0} #{spec.name}"
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class CreateJobs < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :jobs, :force => true do |t|
|
4
|
+
t.string :object
|
5
|
+
t.string :method_name
|
6
|
+
t.text :arguments
|
7
|
+
t.string :return
|
8
|
+
t.string :exception
|
9
|
+
t.datetime :created_at
|
10
|
+
t.datetime :run_at
|
11
|
+
t.datetime :started_at
|
12
|
+
t.datetime :completed_at
|
13
|
+
t.datetime :failed_at
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.down
|
18
|
+
drop_table :jobs
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rails/generators/migration'
|
2
|
+
class NavvyGenerator < Rails::Generators::Base
|
3
|
+
include Rails::Generators::Migration
|
4
|
+
|
5
|
+
def self.source_root
|
6
|
+
File.join(File.dirname(__FILE__), '..', '..', 'generators', 'navvy', 'templates')
|
7
|
+
end
|
8
|
+
|
9
|
+
def install_navvy
|
10
|
+
migration_template(
|
11
|
+
'migration.rb',
|
12
|
+
'db/migrate/create_navvy_table.rb'
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
def next_migration_number(dirname) #:nodoc:
|
18
|
+
"%.3d" % (current_migration_number(dirname) + 1)
|
19
|
+
end
|
20
|
+
end
|
data/lib/navvy.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/navvy/
|
2
|
-
require File.expand_path(File.dirname(__FILE__) + '/navvy/
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/navvy/worker')
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + '/navvy/log')
|
@@ -0,0 +1,212 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_record'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Navvy
|
6
|
+
class Job < ActiveRecord::Base
|
7
|
+
class << self
|
8
|
+
attr_writer :limit
|
9
|
+
attr_accessor :keep
|
10
|
+
end
|
11
|
+
|
12
|
+
##
|
13
|
+
# Default limit of jobs to be fetched
|
14
|
+
#
|
15
|
+
# @return [Integer] limit
|
16
|
+
|
17
|
+
def self.limit
|
18
|
+
@limit || 100
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
# Should the job be kept?
|
23
|
+
#
|
24
|
+
# @return [true, false] keep
|
25
|
+
|
26
|
+
def self.keep?
|
27
|
+
keep = (@keep || false)
|
28
|
+
return keep.from_now >= Time.now if keep.is_a? Fixnum
|
29
|
+
keep
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Add a job to the job queue.
|
34
|
+
#
|
35
|
+
# @param [Object] object the object you want to run a method from
|
36
|
+
# @param [Symbol, String] method_name the name of the method you want to run
|
37
|
+
# @param [*] arguments optional arguments you want to pass to the method
|
38
|
+
#
|
39
|
+
# @return [true, false]
|
40
|
+
|
41
|
+
def self.enqueue(object, method_name, *args)
|
42
|
+
create(
|
43
|
+
:object => object.to_s,
|
44
|
+
:method_name => method_name.to_s,
|
45
|
+
:arguments => args,
|
46
|
+
:run_at => Time.now,
|
47
|
+
:created_at => Time.now
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
51
|
+
##
|
52
|
+
# Find the next available jobs in the queue. This will not include failed
|
53
|
+
# jobs (where :failed_at is not nil) and jobs that should run in the future
|
54
|
+
# (where :run_at is greater than the current time).
|
55
|
+
#
|
56
|
+
# @param [Integer] limit the limit of jobs to be fetched. Defaults to
|
57
|
+
# Navvy::Job.limit
|
58
|
+
#
|
59
|
+
# @return [array, nil] the next available jobs in an array or nil if no
|
60
|
+
# jobs were found.
|
61
|
+
|
62
|
+
def self.next(limit = self.limit)
|
63
|
+
all(
|
64
|
+
:conditions => [
|
65
|
+
'`failed_at` IS NULL AND `completed_at` IS NULL AND `run_at` <= ?',
|
66
|
+
Time.now
|
67
|
+
],
|
68
|
+
:limit => limit,
|
69
|
+
:order => 'created_at'
|
70
|
+
)
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# Clean up jobs that we don't need to keep anymore. If Navvy::Job.keep is
|
75
|
+
# false it'll delete every completed job, if it's a timestamp it'll only
|
76
|
+
# delete completed jobs that have passed their keeptime.
|
77
|
+
#
|
78
|
+
# @return [true, false] delete_all the result of the delete_all call
|
79
|
+
|
80
|
+
def self.cleanup
|
81
|
+
if keep.is_a? Fixnum
|
82
|
+
delete_all([
|
83
|
+
'`completed_at` <= ?',
|
84
|
+
keep.ago
|
85
|
+
])
|
86
|
+
else
|
87
|
+
delete_all(
|
88
|
+
'`completed_at` IS NOT NULL'
|
89
|
+
) unless keep?
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
##
|
94
|
+
# Run the job. Will delete the Navvy::Job record and return its return
|
95
|
+
# value if it runs successfully unless Navvy::Job.keep is set. If a job
|
96
|
+
# fails, it'll update the Navvy::Job record to include the exception
|
97
|
+
# message it sent back and set the :failed_at date. Failed jobs never get
|
98
|
+
# deleted.
|
99
|
+
#
|
100
|
+
# @example
|
101
|
+
# job = Navvy::Job.next # finds the next available job in the queue
|
102
|
+
# job.run # runs the job and returns the job's return value
|
103
|
+
#
|
104
|
+
# @return [String] return value of the called method.
|
105
|
+
|
106
|
+
def run
|
107
|
+
begin
|
108
|
+
update_attributes(:started_at => Time.now)
|
109
|
+
if args.empty?
|
110
|
+
result = object.constantize.send(method_name)
|
111
|
+
else
|
112
|
+
result = object.constantize.send(method_name, *args)
|
113
|
+
end
|
114
|
+
Navvy::Job.keep? ? completed : destroy
|
115
|
+
result
|
116
|
+
rescue Exception => exception
|
117
|
+
failed(exception.message)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
##
|
122
|
+
# Mark the job as completed. Will set completed_at to the current time and
|
123
|
+
# optionally add the return value if provided.
|
124
|
+
#
|
125
|
+
# @param [String] return_value the return value you want to store.
|
126
|
+
#
|
127
|
+
# @return [true, false] update_attributes the result of the
|
128
|
+
# update_attributes call
|
129
|
+
|
130
|
+
def completed(return_value = nil)
|
131
|
+
update_attributes({
|
132
|
+
:completed_at => Time.now,
|
133
|
+
:return => return_value
|
134
|
+
})
|
135
|
+
end
|
136
|
+
|
137
|
+
##
|
138
|
+
# Mark the job as failed. Will set failed_at to the current time and
|
139
|
+
# optionally add the exception message if provided.
|
140
|
+
#
|
141
|
+
# @param [String] exception the exception message you want to store.
|
142
|
+
#
|
143
|
+
# @return [true, false] update_attributes the result of the
|
144
|
+
# update_attributes call
|
145
|
+
|
146
|
+
def failed(message = nil)
|
147
|
+
update_attributes({
|
148
|
+
:failed_at => Time.now,
|
149
|
+
:exception => message
|
150
|
+
})
|
151
|
+
end
|
152
|
+
|
153
|
+
##
|
154
|
+
# Check if the job has been run.
|
155
|
+
#
|
156
|
+
# @return [true, false] ran
|
157
|
+
|
158
|
+
def ran?
|
159
|
+
completed? || failed?
|
160
|
+
end
|
161
|
+
|
162
|
+
##
|
163
|
+
# Check how long it took for a job to complete or fail
|
164
|
+
#
|
165
|
+
# @return [Time, Integer] time the time it took
|
166
|
+
|
167
|
+
def duration
|
168
|
+
ran? ? (completed_at || failed_at) - started_at : 0
|
169
|
+
end
|
170
|
+
|
171
|
+
##
|
172
|
+
# Check if completed_at is set
|
173
|
+
#
|
174
|
+
# @return [true, false] set?
|
175
|
+
|
176
|
+
def completed_at?
|
177
|
+
!completed_at.nil?
|
178
|
+
end
|
179
|
+
|
180
|
+
##
|
181
|
+
# Check if failed_at is set
|
182
|
+
#
|
183
|
+
# @return [true, false] set?
|
184
|
+
|
185
|
+
def failed_at?
|
186
|
+
!failed_at.nil?
|
187
|
+
end
|
188
|
+
|
189
|
+
##
|
190
|
+
# Get the job arguments as an array
|
191
|
+
#
|
192
|
+
# @return [array] arguments
|
193
|
+
|
194
|
+
def args
|
195
|
+
arguments.is_a?(Array) ? arguments : YAML.load(arguments)
|
196
|
+
end
|
197
|
+
|
198
|
+
##
|
199
|
+
# Get the job status
|
200
|
+
#
|
201
|
+
# @return [:pending, :completed, :failed] status
|
202
|
+
|
203
|
+
def status
|
204
|
+
return :completed if completed?
|
205
|
+
return :failed if failed?
|
206
|
+
:pending
|
207
|
+
end
|
208
|
+
|
209
|
+
alias_method :completed?, :completed_at?
|
210
|
+
alias_method :failed?, :failed_at?
|
211
|
+
end
|
212
|
+
end
|
@@ -4,29 +4,59 @@ require 'mongo_mapper'
|
|
4
4
|
module Navvy
|
5
5
|
class Job
|
6
6
|
include MongoMapper::Document
|
7
|
+
class << self
|
8
|
+
attr_writer :limit
|
9
|
+
attr_accessor :keep
|
10
|
+
end
|
7
11
|
|
8
|
-
key :object,
|
9
|
-
key :
|
10
|
-
key :arguments,
|
11
|
-
key :
|
12
|
-
key :
|
13
|
-
key :
|
12
|
+
key :object, String
|
13
|
+
key :method_name, Symbol
|
14
|
+
key :arguments, Array
|
15
|
+
key :return, String
|
16
|
+
key :exception, String
|
17
|
+
key :created_at, Time
|
18
|
+
key :run_at, Time
|
19
|
+
key :started_at, Time
|
20
|
+
key :completed_at, Time
|
21
|
+
key :failed_at, Time
|
22
|
+
|
23
|
+
##
|
24
|
+
# Default limit of jobs to be fetched
|
25
|
+
#
|
26
|
+
# @return [Integer] limit
|
27
|
+
|
28
|
+
def self.limit
|
29
|
+
@limit || 100
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Should the job be kept?
|
34
|
+
#
|
35
|
+
# @return [true, false] keep
|
36
|
+
|
37
|
+
def self.keep?
|
38
|
+
keep = (@keep || false)
|
39
|
+
return keep.from_now >= Time.now if keep.is_a? Fixnum
|
40
|
+
keep
|
41
|
+
end
|
14
42
|
|
15
43
|
##
|
16
44
|
# Add a job to the job queue.
|
17
45
|
#
|
18
46
|
# @param [Object] object the object you want to run a method from
|
19
|
-
# @param [Symbol, String]
|
47
|
+
# @param [Symbol, String] method_name the name of the method you want to
|
48
|
+
# run
|
20
49
|
# @param [*] arguments optional arguments you want to pass to the method
|
21
50
|
#
|
22
|
-
# @return [true, false]
|
51
|
+
# @return [true, false]
|
23
52
|
|
24
|
-
def self.enqueue(object,
|
53
|
+
def self.enqueue(object, method_name, *args)
|
25
54
|
create(
|
26
|
-
:object =>
|
27
|
-
:
|
28
|
-
:
|
29
|
-
:
|
55
|
+
:object => object.to_s,
|
56
|
+
:method_name => method_name.to_sym,
|
57
|
+
:arguments => args,
|
58
|
+
:run_at => Time.now,
|
59
|
+
:created_at => Time.now
|
30
60
|
)
|
31
61
|
end
|
32
62
|
|
@@ -35,25 +65,47 @@ module Navvy
|
|
35
65
|
# jobs (where :failed_at is not nil) and jobs that should run in the future
|
36
66
|
# (where :run_at is greater than the current time).
|
37
67
|
#
|
38
|
-
# @param [Integer] limit the limit of jobs to be fetched. Defaults to
|
68
|
+
# @param [Integer] limit the limit of jobs to be fetched. Defaults to
|
39
69
|
# Navvy::Job.limit
|
40
70
|
#
|
41
71
|
# @return [array, nil] the next available jobs in an array or nil if no
|
42
|
-
#
|
72
|
+
# jobs were found.
|
43
73
|
|
44
74
|
def self.next(limit = self.limit)
|
45
75
|
all(
|
46
|
-
:failed_at =>
|
47
|
-
:
|
48
|
-
:
|
76
|
+
:failed_at => nil,
|
77
|
+
:completed_at => nil,
|
78
|
+
:run_at => {'$lte', Time.now},
|
79
|
+
:limit => limit,
|
80
|
+
:order => 'created_at'
|
49
81
|
)
|
50
82
|
end
|
51
83
|
|
84
|
+
##
|
85
|
+
# Clean up jobs that we don't need to keep anymore. If Navvy::Job.keep is
|
86
|
+
# false it'll delete every completed job, if it's a timestamp it'll only
|
87
|
+
# delete completed jobs that have passed their keeptime.
|
88
|
+
#
|
89
|
+
# @return [true, false] delete_all the result of the delete_all call
|
90
|
+
|
91
|
+
def self.cleanup
|
92
|
+
if keep.is_a? Fixnum
|
93
|
+
delete_all(
|
94
|
+
:completed_at => {'$lte' => keep.ago}
|
95
|
+
)
|
96
|
+
else
|
97
|
+
delete_all(
|
98
|
+
:completed_at => {'$ne' => nil}
|
99
|
+
) unless keep?
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
52
103
|
##
|
53
104
|
# Run the job. Will delete the Navvy::Job record and return its return
|
54
|
-
# value if it runs successfully. If a job
|
55
|
-
# Navvy::Job record to include the exception
|
56
|
-
# the :failed_at date. Failed jobs
|
105
|
+
# value if it runs successfully unless Navvy::Job.keep is set. If a job
|
106
|
+
# fails, it'll update the Navvy::Job record to include the exception
|
107
|
+
# message it sent back and set the :failed_at date. Failed jobs never get
|
108
|
+
# deleted.
|
57
109
|
#
|
58
110
|
# @example
|
59
111
|
# job = Navvy::Job.next # finds the next available job in the queue
|
@@ -63,15 +115,82 @@ module Navvy
|
|
63
115
|
|
64
116
|
def run
|
65
117
|
begin
|
66
|
-
|
67
|
-
|
118
|
+
update_attributes(:started_at => Time.now)
|
119
|
+
if args.empty?
|
120
|
+
result = object.constantize.send(method_name)
|
121
|
+
else
|
122
|
+
result = object.constantize.send(method_name, *args)
|
123
|
+
end
|
124
|
+
Navvy::Job.keep? ? completed : destroy
|
68
125
|
result
|
69
126
|
rescue Exception => exception
|
70
|
-
|
71
|
-
:exception => exception.message,
|
72
|
-
:failed_at => Time.now
|
73
|
-
})
|
127
|
+
failed(exception.message)
|
74
128
|
end
|
75
129
|
end
|
130
|
+
|
131
|
+
##
|
132
|
+
# Mark the job as completed. Will set completed_at to the current time and
|
133
|
+
# optionally add the return value if provided.
|
134
|
+
#
|
135
|
+
# @param [String] return_value the return value you want to store.
|
136
|
+
#
|
137
|
+
# @return [true, false] update_attributes the result of the
|
138
|
+
# update_attributes call
|
139
|
+
|
140
|
+
def completed(return_value = nil)
|
141
|
+
update_attributes({
|
142
|
+
:completed_at => Time.now,
|
143
|
+
:return => return_value
|
144
|
+
})
|
145
|
+
end
|
146
|
+
|
147
|
+
##
|
148
|
+
# Mark the job as failed. Will set failed_at to the current time and
|
149
|
+
# optionally add the exception message if provided.
|
150
|
+
#
|
151
|
+
# @param [String] exception the exception message you want to store.
|
152
|
+
#
|
153
|
+
# @return [true, false] update_attributes the result of the
|
154
|
+
# update_attributes call
|
155
|
+
|
156
|
+
def failed(message = nil)
|
157
|
+
update_attributes({
|
158
|
+
:failed_at => Time.now,
|
159
|
+
:exception => message
|
160
|
+
})
|
161
|
+
end
|
162
|
+
|
163
|
+
##
|
164
|
+
# Check if the job has been run.
|
165
|
+
#
|
166
|
+
# @return [true, false] ran
|
167
|
+
|
168
|
+
def ran?
|
169
|
+
completed? || failed?
|
170
|
+
end
|
171
|
+
|
172
|
+
##
|
173
|
+
# Check how long it took for a job to complete or fail
|
174
|
+
#
|
175
|
+
# @return [Time, Integer] time the time it took
|
176
|
+
|
177
|
+
def duration
|
178
|
+
ran? ? (completed_at || failed_at) - started_at : 0
|
179
|
+
end
|
180
|
+
|
181
|
+
##
|
182
|
+
# Get the job status
|
183
|
+
#
|
184
|
+
# @return [:pending, :completed, :failed] status
|
185
|
+
|
186
|
+
def status
|
187
|
+
return :completed if completed?
|
188
|
+
return :failed if failed?
|
189
|
+
:pending
|
190
|
+
end
|
191
|
+
|
192
|
+
alias_method :completed?, :completed_at?
|
193
|
+
alias_method :failed?, :failed_at?
|
194
|
+
alias_method :args, :arguments
|
76
195
|
end
|
77
196
|
end
|