navvy 0.0.0 → 0.1.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.
- 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
@@ -0,0 +1,200 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'sequel'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Navvy
|
6
|
+
class Job < Sequel::Model
|
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 (Time.now + keep) >= 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
|
37
|
+
# run
|
38
|
+
# @param [*] arguments optional arguments you want to pass to the method
|
39
|
+
#
|
40
|
+
# @return [true, false]
|
41
|
+
|
42
|
+
def self.enqueue(object, method_name, *args)
|
43
|
+
create(
|
44
|
+
:object => object.to_s,
|
45
|
+
:method_name => method_name.to_s,
|
46
|
+
:arguments => YAML::dump(args),
|
47
|
+
:run_at => Time.now,
|
48
|
+
:created_at => Time.now
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
##
|
53
|
+
# Find the next available jobs in the queue. This will not include failed
|
54
|
+
# jobs (where :failed_at is not nil) and jobs that should run in the future
|
55
|
+
# (where :run_at is greater than the current time).
|
56
|
+
#
|
57
|
+
# @param [Integer] limit the limit of jobs to be fetched. Defaults to
|
58
|
+
# Navvy::Job.limit
|
59
|
+
#
|
60
|
+
# @return [array, nil] the next available jobs in an array or nil if no
|
61
|
+
# jobs were found.
|
62
|
+
|
63
|
+
def self.next(limit = self.limit)
|
64
|
+
filter(
|
65
|
+
'`failed_at` IS NULL AND `completed_at` IS NULL AND `run_at` <= ?',
|
66
|
+
Time.now
|
67
|
+
).order(:created_at).first(limit)
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Clean up jobs that we don't need to keep anymore. If Navvy::Job.keep is
|
72
|
+
# false it'll delete every completed job, if it's a timestamp it'll only
|
73
|
+
# delete completed jobs that have passed their keeptime.
|
74
|
+
#
|
75
|
+
# @return [true, false] delete_all the result of the delete_all call
|
76
|
+
|
77
|
+
def self.cleanup
|
78
|
+
if keep.is_a? Fixnum
|
79
|
+
filter('`completed_at` <= ?', (Time.now - keep)).delete
|
80
|
+
else
|
81
|
+
filter('`completed_at` IS NOT NULL').delete unless keep?
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
##
|
86
|
+
# Run the job. Will delete the Navvy::Job record and return its return
|
87
|
+
# value if it runs successfully unless Navvy::Job.keep is set. If a job
|
88
|
+
# fails, it'll update the Navvy::Job record to include the exception
|
89
|
+
# message it sent back and set the :failed_at date. Failed jobs never get
|
90
|
+
# deleted.
|
91
|
+
#
|
92
|
+
# @example
|
93
|
+
# job = Navvy::Job.next # finds the next available job in the queue
|
94
|
+
# job.run # runs the job and returns the job's return value
|
95
|
+
#
|
96
|
+
# @return [String] return value of the called method.
|
97
|
+
|
98
|
+
def run
|
99
|
+
begin
|
100
|
+
update(:started_at => Time.now)
|
101
|
+
result = Kernel.const_get(object).send(method_name, *args)
|
102
|
+
Navvy::Job.keep? ? completed : destroy
|
103
|
+
result
|
104
|
+
rescue Exception => exception
|
105
|
+
failed(exception.message)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
##
|
110
|
+
# Mark the job as completed. Will set completed_at to the current time and
|
111
|
+
# optionally add the return value if provided.
|
112
|
+
#
|
113
|
+
# @param [String] return_value the return value you want to store.
|
114
|
+
#
|
115
|
+
# @return [true, false] update_attributes the result of the
|
116
|
+
# update_attributes call
|
117
|
+
|
118
|
+
def completed(return_value = nil)
|
119
|
+
update({
|
120
|
+
:completed_at => Time.now,
|
121
|
+
:return => return_value
|
122
|
+
})
|
123
|
+
end
|
124
|
+
|
125
|
+
##
|
126
|
+
# Mark the job as failed. Will set failed_at to the current time and
|
127
|
+
# optionally add the exception message if provided.
|
128
|
+
#
|
129
|
+
# @param [String] exception the exception message you want to store.
|
130
|
+
#
|
131
|
+
# @return [true, false] update_attributes the result of the
|
132
|
+
# update_attributes call
|
133
|
+
|
134
|
+
def failed(message = nil)
|
135
|
+
update({
|
136
|
+
:failed_at => Time.now,
|
137
|
+
:exception => message
|
138
|
+
})
|
139
|
+
end
|
140
|
+
|
141
|
+
##
|
142
|
+
# Check if the job has been run.
|
143
|
+
#
|
144
|
+
# @return [true, false] ran
|
145
|
+
|
146
|
+
def ran?
|
147
|
+
completed? || failed?
|
148
|
+
end
|
149
|
+
|
150
|
+
##
|
151
|
+
# Check how long it took for a job to complete or fail
|
152
|
+
#
|
153
|
+
# @return [Time, Integer] time the time it took
|
154
|
+
|
155
|
+
def duration
|
156
|
+
ran? ? (completed_at || failed_at) - started_at : 0
|
157
|
+
end
|
158
|
+
|
159
|
+
##
|
160
|
+
# Check if completed_at is set
|
161
|
+
#
|
162
|
+
# @return [true, false] set?
|
163
|
+
|
164
|
+
def completed_at?
|
165
|
+
!completed_at.nil?
|
166
|
+
end
|
167
|
+
|
168
|
+
##
|
169
|
+
# Check if failed_at is set
|
170
|
+
#
|
171
|
+
# @return [true, false] set?
|
172
|
+
|
173
|
+
def failed_at?
|
174
|
+
!failed_at.nil?
|
175
|
+
end
|
176
|
+
|
177
|
+
##
|
178
|
+
# Get the job arguments as an array
|
179
|
+
#
|
180
|
+
# @return [array] arguments
|
181
|
+
|
182
|
+
def args
|
183
|
+
arguments.first.is_a?(Array) ? arguments : YAML.load(arguments)
|
184
|
+
end
|
185
|
+
|
186
|
+
##
|
187
|
+
# Get the job status
|
188
|
+
#
|
189
|
+
# @return [:pending, :completed, :failed] status
|
190
|
+
|
191
|
+
def status
|
192
|
+
return :completed if completed?
|
193
|
+
return :failed if failed?
|
194
|
+
:pending
|
195
|
+
end
|
196
|
+
|
197
|
+
alias_method :completed?, :completed_at?
|
198
|
+
alias_method :failed?, :failed_at?
|
199
|
+
end
|
200
|
+
end
|
data/lib/navvy/log.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
module Navvy
|
2
|
+
class Log
|
3
|
+
class << self
|
4
|
+
attr_writer :logger
|
5
|
+
attr_accessor :quiet
|
6
|
+
end
|
7
|
+
|
8
|
+
class LoggerNotFound < StandardError; end
|
9
|
+
|
10
|
+
def self.logger
|
11
|
+
@logger
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# Pass a log to the logger. It will check if self.logger is an array. If it
|
16
|
+
# is, it'll loop through it and log to every logger. If it's not, it'll
|
17
|
+
# just log once.
|
18
|
+
#
|
19
|
+
# @param [String] message the message you want to log
|
20
|
+
# @param [Integer] color an optional color code to use in the terminal
|
21
|
+
# output
|
22
|
+
|
23
|
+
def self.info(message, color = nil)
|
24
|
+
if logger.is_a? Array
|
25
|
+
logger.each do |logger|
|
26
|
+
write(logger, message, color)
|
27
|
+
end
|
28
|
+
else
|
29
|
+
write(logger, message, color)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Actually write the log to the logger. It'll check self.logger and use
|
35
|
+
# that to define a logger
|
36
|
+
#
|
37
|
+
# @param [Symbol] logger the logger you want to use
|
38
|
+
# @param [String] message the message you want to log
|
39
|
+
# @param [Integer] color an optional color code to use in the terminal
|
40
|
+
# output
|
41
|
+
|
42
|
+
def self.write(logger, message, color = nil)
|
43
|
+
puts "\e[#{color}m#{message}\e[0m" unless quiet
|
44
|
+
case logger
|
45
|
+
when :justlogging
|
46
|
+
raise(
|
47
|
+
LoggerNotFound,
|
48
|
+
'JustLogging could not be found. No logs were created.'
|
49
|
+
) unless defined? Justlogging.log
|
50
|
+
Justlogging.log(message)
|
51
|
+
when :rails
|
52
|
+
raise(
|
53
|
+
LoggerNotFound,
|
54
|
+
'RAILS_DEFAULT_LOGGER could not be found. No logs were created.'
|
55
|
+
) unless defined? RAILS_DEFAULT_LOGGER.info
|
56
|
+
RAILS_DEFAULT_LOGGER.info(message)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/navvy/tasks.rb
ADDED
data/lib/navvy/worker.rb
CHANGED
@@ -1,22 +1,37 @@
|
|
1
1
|
module Navvy
|
2
2
|
class Worker
|
3
|
-
|
3
|
+
|
4
4
|
##
|
5
5
|
# Start the worker.
|
6
|
-
|
6
|
+
|
7
7
|
def self.start
|
8
|
+
Navvy::Log.info '*** Starting ***'
|
9
|
+
trap('TERM') { Navvy::Log.info '*** Exiting ***'; $exit = true }
|
10
|
+
trap('INT') { Navvy::Log.info '*** Exiting ***'; $exit = true }
|
11
|
+
|
8
12
|
loop do
|
9
13
|
fetch_and_run_jobs
|
14
|
+
|
15
|
+
if $exit
|
16
|
+
Navvy::Log.info '*** Cleaning up ***'
|
17
|
+
Navvy::Job.cleanup
|
18
|
+
break
|
19
|
+
end
|
10
20
|
sleep 5
|
11
21
|
end
|
12
22
|
end
|
13
|
-
|
23
|
+
|
14
24
|
##
|
15
|
-
# Fetch jobs
|
16
|
-
|
25
|
+
# Fetch jobs and run them.
|
26
|
+
|
17
27
|
def self.fetch_and_run_jobs
|
18
28
|
Job.next.each do |job|
|
19
|
-
job.run
|
29
|
+
result = job.run
|
30
|
+
Navvy::Log.info(
|
31
|
+
"* #{job.object.to_s}.#{job.method_name}" <<
|
32
|
+
"(#{job.args.join(', ')}) => #{(job.exception || result).to_s}",
|
33
|
+
job.failed? ? 31 : 32
|
34
|
+
)
|
20
35
|
end
|
21
36
|
end
|
22
37
|
end
|
data/navvy.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{navvy}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.1.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jeff Kreeftmeijer"]
|
12
|
-
s.date = %q{2010-01-
|
12
|
+
s.date = %q{2010-01-21}
|
13
13
|
s.description = %q{Simple background job processor inspired by delayed_job, but aiming for database agnosticism.}
|
14
14
|
s.email = %q{jeff@kreeftmeijer.nl}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -23,14 +23,24 @@ Gem::Specification.new do |s|
|
|
23
23
|
"README.textile",
|
24
24
|
"Rakefile",
|
25
25
|
"VERSION",
|
26
|
-
"
|
26
|
+
"generators/navvy/navvy_generator.rb",
|
27
|
+
"generators/navvy/templates/migration.rb",
|
28
|
+
"lib/generators/navvy_generator.rb",
|
27
29
|
"lib/navvy.rb",
|
28
|
-
"lib/navvy/job.rb",
|
30
|
+
"lib/navvy/job/active_record.rb",
|
29
31
|
"lib/navvy/job/mongo_mapper.rb",
|
32
|
+
"lib/navvy/job/sequel.rb",
|
33
|
+
"lib/navvy/log.rb",
|
34
|
+
"lib/navvy/tasks.rb",
|
30
35
|
"lib/navvy/worker.rb",
|
31
36
|
"navvy.gemspec",
|
37
|
+
"spec/job/active_record_spec.rb",
|
32
38
|
"spec/job/mongo_mapper_spec.rb",
|
39
|
+
"spec/job/sequel_spec.rb",
|
40
|
+
"spec/log_spec.rb",
|
41
|
+
"spec/setup/active_record.rb",
|
33
42
|
"spec/setup/mongo_mapper.rb",
|
43
|
+
"spec/setup/sequel.rb",
|
34
44
|
"spec/spec_helper.rb",
|
35
45
|
"spec/worker_spec.rb"
|
36
46
|
]
|
@@ -40,8 +50,13 @@ Gem::Specification.new do |s|
|
|
40
50
|
s.rubygems_version = %q{1.3.5}
|
41
51
|
s.summary = %q{Simple background job processor inspired by delayed_job, but aiming for database agnosticism.}
|
42
52
|
s.test_files = [
|
43
|
-
"spec/job/
|
53
|
+
"spec/job/active_record_spec.rb",
|
54
|
+
"spec/job/mongo_mapper_spec.rb",
|
55
|
+
"spec/job/sequel_spec.rb",
|
56
|
+
"spec/log_spec.rb",
|
57
|
+
"spec/setup/active_record.rb",
|
44
58
|
"spec/setup/mongo_mapper.rb",
|
59
|
+
"spec/setup/sequel.rb",
|
45
60
|
"spec/spec_helper.rb",
|
46
61
|
"spec/worker_spec.rb"
|
47
62
|
]
|
@@ -51,26 +66,29 @@ Gem::Specification.new do |s|
|
|
51
66
|
s.specification_version = 3
|
52
67
|
|
53
68
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
54
|
-
s.add_runtime_dependency(%q<mongo_mapper>, [">= 0.6.10"])
|
55
69
|
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
56
70
|
s.add_development_dependency(%q<yard>, [">= 0.5.2"])
|
57
71
|
s.add_development_dependency(%q<metric_fu>, [">= 1.1.6"])
|
58
72
|
s.add_development_dependency(%q<machinist>, [">= 1.0.6"])
|
73
|
+
s.add_development_dependency(%q<mongo_mapper>, [">= 0.6.10"])
|
59
74
|
s.add_development_dependency(%q<machinist_mongomapper>, [">= 0.9.7"])
|
75
|
+
s.add_development_dependency(%q<sequel>, [">= 3.8.0"])
|
60
76
|
else
|
61
|
-
s.add_dependency(%q<mongo_mapper>, [">= 0.6.10"])
|
62
77
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
63
78
|
s.add_dependency(%q<yard>, [">= 0.5.2"])
|
64
79
|
s.add_dependency(%q<metric_fu>, [">= 1.1.6"])
|
65
80
|
s.add_dependency(%q<machinist>, [">= 1.0.6"])
|
81
|
+
s.add_dependency(%q<mongo_mapper>, [">= 0.6.10"])
|
66
82
|
s.add_dependency(%q<machinist_mongomapper>, [">= 0.9.7"])
|
83
|
+
s.add_dependency(%q<sequel>, [">= 3.8.0"])
|
67
84
|
end
|
68
85
|
else
|
69
|
-
s.add_dependency(%q<mongo_mapper>, [">= 0.6.10"])
|
70
86
|
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
71
87
|
s.add_dependency(%q<yard>, [">= 0.5.2"])
|
72
88
|
s.add_dependency(%q<metric_fu>, [">= 1.1.6"])
|
73
89
|
s.add_dependency(%q<machinist>, [">= 1.0.6"])
|
90
|
+
s.add_dependency(%q<mongo_mapper>, [">= 0.6.10"])
|
74
91
|
s.add_dependency(%q<machinist_mongomapper>, [">= 0.9.7"])
|
92
|
+
s.add_dependency(%q<sequel>, [">= 3.8.0"])
|
75
93
|
end
|
76
94
|
end
|
@@ -0,0 +1,325 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe 'Navvy::Job' do
|
4
|
+
before do
|
5
|
+
require File.expand_path(File.dirname(__FILE__) + '/../setup/active_record')
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '.enqueue' do
|
9
|
+
before(:each) do
|
10
|
+
Navvy::Job.delete_all
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should enqueue a job' do
|
14
|
+
Navvy::Job.enqueue(Cow, :speak)
|
15
|
+
Navvy::Job.count.should == 1
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should set the object and the method_name' do
|
19
|
+
Navvy::Job.enqueue(Cow, :speak)
|
20
|
+
job = Navvy::Job.first
|
21
|
+
job.object.should == 'Cow'
|
22
|
+
job.method_name.should == 'speak'
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should turn the method_name into a symbol' do
|
26
|
+
Navvy::Job.enqueue(Cow, 'speak')
|
27
|
+
job = Navvy::Job.first
|
28
|
+
job.method_name.should == 'speak'
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should set the arguments' do
|
32
|
+
Navvy::Job.enqueue(Cow, :speak, true, false)
|
33
|
+
job = Navvy::Job.first
|
34
|
+
YAML.load(job.arguments).should == [true, false]
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should set the created_at date' do
|
38
|
+
Navvy::Job.enqueue(Cow, :speak, true, false)
|
39
|
+
job = Navvy::Job.first
|
40
|
+
job.created_at.should be_instance_of Time
|
41
|
+
job.created_at.should <= Time.now
|
42
|
+
job.created_at.should > 10.seconds.ago
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should set the run_at date' do
|
46
|
+
Navvy::Job.enqueue(Cow, :speak, true, false)
|
47
|
+
job = Navvy::Job.first
|
48
|
+
job.run_at.should be_instance_of Time
|
49
|
+
job.run_at.should <= Time.now
|
50
|
+
job.created_at.should > 10.seconds.ago
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should return the enqueued job' do
|
54
|
+
Navvy::Job.enqueue(Cow, :speak, true, false).
|
55
|
+
should be_instance_of Navvy::Job
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '.next' do
|
60
|
+
before(:each) do
|
61
|
+
Navvy::Job.delete_all
|
62
|
+
Navvy::Job.create(
|
63
|
+
:object => 'Cow',
|
64
|
+
:method_name => :last,
|
65
|
+
:created_at => Time.now + 1.day,
|
66
|
+
:run_at => Time.now
|
67
|
+
)
|
68
|
+
Navvy::Job.create(
|
69
|
+
:object => 'Cow',
|
70
|
+
:method_name => :break,
|
71
|
+
:completed_at => Time.now,
|
72
|
+
:run_at => Time.now
|
73
|
+
)
|
74
|
+
Navvy::Job.create(
|
75
|
+
:object => 'Cow',
|
76
|
+
:method_name => :break,
|
77
|
+
:failed_at => Time.now,
|
78
|
+
:run_at => Time.now
|
79
|
+
)
|
80
|
+
Navvy::Job.create(
|
81
|
+
:object => 'Cow',
|
82
|
+
:method_name => :tomorrow,
|
83
|
+
:run_at => Time.now + 1.day
|
84
|
+
)
|
85
|
+
120.times do
|
86
|
+
Navvy::Job.enqueue(Cow, :speak)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should find the next 10 available jobs' do
|
91
|
+
jobs = Navvy::Job.next
|
92
|
+
jobs.count.should == 100
|
93
|
+
jobs.each do |job|
|
94
|
+
job.should be_instance_of Navvy::Job
|
95
|
+
job.method_name.should == 'speak'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should find the next 2 available jobs' do
|
100
|
+
Navvy::Job.next(2).count.should == 2
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'should find the next 4 available jobs' do
|
104
|
+
Navvy::Job.limit = 4
|
105
|
+
Navvy::Job.next.count.should == 4
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe '.cleanup' do
|
110
|
+
before(:each) do
|
111
|
+
Navvy::Job.delete_all
|
112
|
+
Navvy::Job.create(
|
113
|
+
:object => 'Cow',
|
114
|
+
:method_name => :speak,
|
115
|
+
:completed_at => Time.now - 2.days
|
116
|
+
)
|
117
|
+
Navvy::Job.create(
|
118
|
+
:object => 'Cow',
|
119
|
+
:method_name => :speak,
|
120
|
+
:completed_at => Time.now
|
121
|
+
)
|
122
|
+
Navvy::Job.create(
|
123
|
+
:object => 'Cow',
|
124
|
+
:method_name => :speak
|
125
|
+
)
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'should delete all complete jobs when "keep" is false' do
|
129
|
+
Navvy::Job.cleanup
|
130
|
+
Navvy::Job.count.should == 1
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'should not delete any complete jobs when "keep" is true' do
|
134
|
+
Navvy::Job.keep = true
|
135
|
+
Navvy::Job.cleanup
|
136
|
+
Navvy::Job.count.should == 3
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'should delete all complete jobs where "keep" has passed' do
|
140
|
+
Navvy::Job.keep = 1.day
|
141
|
+
Navvy::Job.cleanup
|
142
|
+
Navvy::Job.count.should == 2
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
describe '#run' do
|
147
|
+
|
148
|
+
it 'should pass the arguments' do
|
149
|
+
Navvy::Job.delete_all
|
150
|
+
job = Navvy::Job.enqueue(Cow, :name, 'Betsy')
|
151
|
+
Cow.should_receive(:name).with('Betsy')
|
152
|
+
job.run
|
153
|
+
end
|
154
|
+
|
155
|
+
describe 'when everything goes well' do
|
156
|
+
before(:each) do
|
157
|
+
Navvy::Job.delete_all
|
158
|
+
Navvy::Job.enqueue(Cow, :speak)
|
159
|
+
Navvy::Job.keep = false
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'should run the job and delete it' do
|
163
|
+
jobs = Navvy::Job.next
|
164
|
+
jobs.first.run.should == 'moo'
|
165
|
+
Navvy::Job.count.should == 0
|
166
|
+
end
|
167
|
+
|
168
|
+
describe 'when Navvy::Job.keep is set' do
|
169
|
+
it 'should mark the job as complete when keep is true' do
|
170
|
+
Navvy::Job.keep = true
|
171
|
+
jobs = Navvy::Job.next
|
172
|
+
jobs.first.run
|
173
|
+
Navvy::Job.count.should == 1
|
174
|
+
jobs.first.started_at.should be_instance_of Time
|
175
|
+
jobs.first.completed_at.should be_instance_of Time
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'should mark the job as complete when keep has not passed yer' do
|
179
|
+
Navvy::Job.keep = 1.day
|
180
|
+
jobs = Navvy::Job.next
|
181
|
+
jobs.first.run
|
182
|
+
Navvy::Job.count.should == 1
|
183
|
+
jobs.first.started_at.should be_instance_of Time
|
184
|
+
jobs.first.completed_at.should be_instance_of Time
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'should delete the job when the "keep" flag has passed' do
|
188
|
+
Navvy::Job.keep = -1.day
|
189
|
+
jobs = Navvy::Job.next
|
190
|
+
jobs.first.run
|
191
|
+
Navvy::Job.count.should == 0
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
describe 'when a job fails' do
|
197
|
+
before(:each) do
|
198
|
+
Navvy::Job.delete_all
|
199
|
+
Navvy::Job.enqueue(Cow, :broken)
|
200
|
+
end
|
201
|
+
|
202
|
+
it 'should store the exception and current time' do
|
203
|
+
jobs = Navvy::Job.next
|
204
|
+
jobs.first.run
|
205
|
+
Navvy::Job.count.should == 1
|
206
|
+
jobs.first.exception.should == 'this method is broken'
|
207
|
+
jobs.first.started_at.should be_instance_of Time
|
208
|
+
jobs.first.failed_at.should be_instance_of Time
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
describe '#completed' do
|
214
|
+
before(:each) do
|
215
|
+
Navvy::Job.delete_all
|
216
|
+
Navvy::Job.enqueue(Cow, :speak)
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'should update the jobs completed_at date' do
|
220
|
+
jobs = Navvy::Job.next
|
221
|
+
jobs.first.completed
|
222
|
+
jobs.first.completed_at.should_not be_nil
|
223
|
+
end
|
224
|
+
|
225
|
+
it 'should set the return if provided' do
|
226
|
+
jobs = Navvy::Job.next
|
227
|
+
jobs.first.completed('woo!')
|
228
|
+
jobs.first.return.should == 'woo!'
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
describe '#failed' do
|
233
|
+
before(:each) do
|
234
|
+
Navvy::Job.delete_all
|
235
|
+
Navvy::Job.enqueue(Cow, :speak)
|
236
|
+
end
|
237
|
+
|
238
|
+
it 'should update the jobs failed_at date' do
|
239
|
+
jobs = Navvy::Job.next
|
240
|
+
jobs.first.failed
|
241
|
+
jobs.first.failed_at.should_not be_nil
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'should set the exception message if provided' do
|
245
|
+
jobs = Navvy::Job.next
|
246
|
+
jobs.first.failed('broken')
|
247
|
+
jobs.first.exception.should == 'broken'
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
describe '#ran?' do
|
252
|
+
it 'should return false when failed_at? and completed_at? are false' do
|
253
|
+
job = Navvy::Job.create
|
254
|
+
job.ran?.should be_false
|
255
|
+
end
|
256
|
+
|
257
|
+
it 'should return true when failed_at? or completed_at? is true' do
|
258
|
+
[
|
259
|
+
Navvy::Job.create(:failed_at => Time.now),
|
260
|
+
Navvy::Job.create(:completed_at => Time.now)
|
261
|
+
].each do |job|
|
262
|
+
job.ran?.should be_true
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
describe '#duration' do
|
268
|
+
it 'should return a duration if started_at and completed_at are set' do
|
269
|
+
job = Navvy::Job.create(
|
270
|
+
:started_at => 2.seconds.ago,
|
271
|
+
:completed_at => Time.now
|
272
|
+
)
|
273
|
+
|
274
|
+
job.duration.should >= 2.seconds
|
275
|
+
end
|
276
|
+
|
277
|
+
it 'should return a duration if started_at and failed_at are set' do
|
278
|
+
job = Navvy::Job.create(
|
279
|
+
:started_at => 3.seconds.ago,
|
280
|
+
:failed_at => Time.now
|
281
|
+
)
|
282
|
+
|
283
|
+
job.duration.should >= 3.seconds
|
284
|
+
end
|
285
|
+
|
286
|
+
it 'should return 0 if only started_at is set' do
|
287
|
+
job = Navvy::Job.create(
|
288
|
+
:started_at => 4.seconds.ago
|
289
|
+
)
|
290
|
+
|
291
|
+
job.duration.should == 0
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
describe '#args' do
|
296
|
+
it 'should return an array of arguments' do
|
297
|
+
job = Navvy::Job.enqueue(Cow, :speak, true, false)
|
298
|
+
job.args.should be_instance_of Array
|
299
|
+
job.args.count.should == 2
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
describe '#status' do
|
304
|
+
before(:each) do
|
305
|
+
Navvy::Job.delete_all
|
306
|
+
end
|
307
|
+
|
308
|
+
it 'should return :pending' do
|
309
|
+
job = Navvy::Job.enqueue(Cow, :speak)
|
310
|
+
job.status.should == :pending
|
311
|
+
end
|
312
|
+
|
313
|
+
it 'should return :completed' do
|
314
|
+
job = Navvy::Job.enqueue(Cow, :speak)
|
315
|
+
job.completed
|
316
|
+
job.status.should == :completed
|
317
|
+
end
|
318
|
+
|
319
|
+
it 'should return :failed' do
|
320
|
+
job = Navvy::Job.enqueue(Cow, :speak)
|
321
|
+
job.failed
|
322
|
+
job.status.should == :failed
|
323
|
+
end
|
324
|
+
end
|
325
|
+
end
|