job_boss 0.5.8 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +6 -0
- data/job_boss.gemspec +1 -1
- data/lib/job_boss/boss.rb +7 -1
- data/lib/job_boss/job.rb +22 -3
- data/test/unit/job_test.rb +37 -0
- metadata +4 -4
data/README.markdown
CHANGED
@@ -84,6 +84,12 @@ job_boss also makes it easy to wait for the jobs to be done and to collect the r
|
|
84
84
|
|
85
85
|
Job.result_hash(jobs) # => {[0]=>false, [1]=>false, [2]=>true, [3]=>true, [4]=>false, ... }
|
86
86
|
|
87
|
+
You can even define a block to provide updates on progress (the value which is passed into the block is a float between 0.0 and 100.0):
|
88
|
+
|
89
|
+
Job.wait_for_jobs(jobs) do |progress|
|
90
|
+
puts "We're now at #{progress}%"
|
91
|
+
end
|
92
|
+
|
87
93
|
For performance, it is recommended that you keep your jobs table clean scheduling execution of the `delete_jobs_before` command on the Job model, which will clean all jobs completed before the specified time:
|
88
94
|
|
89
95
|
Job.delete_jobs_before(2.days.ago)
|
data/job_boss.gemspec
CHANGED
data/lib/job_boss/boss.rb
CHANGED
@@ -124,7 +124,10 @@ private
|
|
124
124
|
@running_jobs = Job.running.where('id in (?)', @running_jobs)
|
125
125
|
|
126
126
|
cancelled_jobs = @running_jobs.select(&:cancelled?)
|
127
|
-
cancelled_jobs.each
|
127
|
+
cancelled_jobs.each do |job|
|
128
|
+
logger.warn "Cancelling job ##{job.id}"
|
129
|
+
kill_job(job)
|
130
|
+
end
|
128
131
|
@running_jobs -= cancelled_jobs
|
129
132
|
|
130
133
|
# Clean out any jobs whos processes have stopped running for some reason
|
@@ -132,6 +135,8 @@ private
|
|
132
135
|
begin
|
133
136
|
Process.kill(0, job.employee_pid.to_i)
|
134
137
|
rescue Errno::ESRCH
|
138
|
+
logger.warn "Job ##{job.id} MIA!"
|
139
|
+
job.mark_as_mia
|
135
140
|
nil
|
136
141
|
end
|
137
142
|
end
|
@@ -174,6 +179,7 @@ private
|
|
174
179
|
begin
|
175
180
|
Process.kill("TERM", job.employee_pid.to_i)
|
176
181
|
rescue Errno::ESRCH
|
182
|
+
logger.error "Could not kill job ##{job.id}!"
|
177
183
|
nil
|
178
184
|
end
|
179
185
|
end
|
data/lib/job_boss/job.rb
CHANGED
@@ -10,15 +10,20 @@ module JobBoss
|
|
10
10
|
scope :pending, where('started_at IS NULL AND cancelled_at IS NULL')
|
11
11
|
scope :running, where('started_at IS NOT NULL AND completed_at IS NULL')
|
12
12
|
scope :completed, where('completed_at IS NOT NULL')
|
13
|
+
scope :mia, where("completed_at IS NOT NULL AND status = 'mia'")
|
14
|
+
|
15
|
+
def prototype
|
16
|
+
self.path + "(#{self.args.join(', ')})"
|
17
|
+
end
|
13
18
|
|
14
19
|
# Method used by the boss to dispatch an employee
|
15
20
|
def dispatch(boss)
|
16
21
|
mark_as_started
|
17
|
-
boss.logger.info "Dispatching Job ##{self.id}"
|
22
|
+
boss.logger.info "Dispatching Job ##{self.id}: #{self.prototype}"
|
18
23
|
|
19
24
|
pid = fork do
|
20
25
|
ActiveRecord::Base.connection.reconnect!
|
21
|
-
$0 = "[job_boss employee] job ##{self.id} #{self.
|
26
|
+
$0 = "[job_boss employee] job ##{self.id} #{self.prototype})"
|
22
27
|
Process.setpriority(Process::PRIO_PROCESS, 0, 19)
|
23
28
|
|
24
29
|
begin
|
@@ -35,7 +40,7 @@ module JobBoss
|
|
35
40
|
sleep(1)
|
36
41
|
end
|
37
42
|
|
38
|
-
|
43
|
+
boss.logger.info "Job ##{self.id} completed in #{self.time_taken} seconds, exiting..."
|
39
44
|
Kernel.exit
|
40
45
|
end
|
41
46
|
end
|
@@ -94,6 +99,16 @@ module JobBoss
|
|
94
99
|
completed_at && (status == 'success')
|
95
100
|
end
|
96
101
|
|
102
|
+
def mark_as_mia
|
103
|
+
self.completed_at = Time.now
|
104
|
+
self.status = 'mia'
|
105
|
+
self.save
|
106
|
+
end
|
107
|
+
|
108
|
+
def mia?
|
109
|
+
completed_at && (status == 'mia')
|
110
|
+
end
|
111
|
+
|
97
112
|
# Has the job been assigned to an employee?
|
98
113
|
def assigned?
|
99
114
|
# If the #assigned? method is being called for but the job hasn't been completed, reload
|
@@ -137,6 +152,10 @@ module JobBoss
|
|
137
152
|
Job.uncached do
|
138
153
|
until Job.completed.find_all_by_id(ids).count == jobs.size
|
139
154
|
sleep(sleep_interval)
|
155
|
+
|
156
|
+
if block_given?
|
157
|
+
yield ((Job.where('id in (?)', ids).completed.count.to_f / jobs.size.to_f) * 100.0)
|
158
|
+
end
|
140
159
|
end
|
141
160
|
end
|
142
161
|
|
data/test/unit/job_test.rb
CHANGED
@@ -76,6 +76,43 @@ class DaemonTest < ActiveSupport::TestCase
|
|
76
76
|
assert job.cancelled?
|
77
77
|
assert_not_nil job.cancelled_at
|
78
78
|
|
79
|
+
|
80
|
+
# Test recording of MIA jobs
|
81
|
+
job = Boss.queue.sleep.sleep_for(20)
|
82
|
+
|
83
|
+
wait_until_job_assigned(job)
|
84
|
+
|
85
|
+
assert_pid_running(job.employee_pid)
|
86
|
+
|
87
|
+
Process.kill(9, job.employee_pid)
|
88
|
+
|
89
|
+
sleep(1)
|
90
|
+
|
91
|
+
assert_pid_not_running(job.employee_pid)
|
92
|
+
|
93
|
+
job.reload
|
94
|
+
assert job.mia?
|
95
|
+
assert_equal [job.id], Job.mia.collect(&:id)
|
96
|
+
|
97
|
+
jobs = (0..10).collect do |i|
|
98
|
+
job = Boss.queue.sleep.sleep_for(1)
|
99
|
+
end
|
100
|
+
|
101
|
+
progresses = []
|
102
|
+
Job.wait_for_jobs(jobs) do |progress|
|
103
|
+
# puts progress
|
104
|
+
progresses << progress
|
105
|
+
end
|
106
|
+
|
107
|
+
assert_equal progresses, progresses.sort
|
108
|
+
assert progresses.all? {|progress| 0.0 <= progress && progress <= 100.0 }
|
109
|
+
assert progresses.any? {|progress| progress > 1.0 }
|
110
|
+
|
111
|
+
# Test deleting of old jobs
|
112
|
+
|
113
|
+
# Sleep for 1 second so that the upcoming deletions work correctly
|
114
|
+
sleep(1)
|
115
|
+
|
79
116
|
Job.delete_jobs_before(20.seconds.ago)
|
80
117
|
assert Job.completed.count > 0
|
81
118
|
Job.delete_jobs_before(1.second.ago)
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 6
|
8
|
+
- 0
|
9
|
+
version: 0.6.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Brian Underwood
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-12-
|
17
|
+
date: 2010-12-22 00:00:00 -05:00
|
18
18
|
default_executable: job_boss
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|