resque_ui 3.1.7 → 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.
- data/History.txt +6 -0
- data/README.markdown +93 -4
- data/VERSION.yml +2 -2
- data/app/controllers/resque_controller.rb +12 -0
- data/app/views/resque/_workers.html.erb +115 -95
- data/lib/resque_ui/cap_recipes.rb +21 -1
- data/lib/resque_ui/overrides/resque/job.rb +66 -2
- data/lib/resque_ui/overrides/resque/worker.rb +72 -10
- data/lib/resque_ui/overrides/resque_status/job_with_status.rb +45 -1
- data/lib/resque_ui/overrides/resque_status/status.rb +5 -0
- data/rdoc/Resque/Job.html +68 -4
- data/rdoc/Resque/JobWithStatus.html +161 -7
- data/rdoc/Resque/Status.html +47 -5
- data/rdoc/Resque/Worker.html +313 -64
- data/rdoc/created.rid +8 -8
- data/rdoc/index.html +27 -7
- data/rdoc/lib/resque_ui/cap_rb.html +1 -1
- data/rdoc/lib/resque_ui/cap_recipes_rb.html +2 -2
- data/rdoc/lib/resque_ui/overrides/resque/job_rb.html +2 -2
- data/rdoc/lib/resque_ui/overrides/resque/resque_rb.html +1 -1
- data/rdoc/lib/resque_ui/overrides/resque/worker_rb.html +2 -2
- data/rdoc/lib/resque_ui/overrides/resque_scheduler/resque_scheduler_rb.html +1 -1
- data/rdoc/lib/resque_ui/overrides/resque_status/chained_job_with_status_rb.html +1 -1
- data/rdoc/lib/resque_ui/overrides/resque_status/job_with_status_rb.html +2 -2
- data/rdoc/lib/resque_ui/overrides/resque_status/status_rb.html +2 -2
- data/rdoc/lib/resque_ui_rb.html +2 -2
- data/resque_ui.gemspec +2 -2
- metadata +2 -2
data/History.txt
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
== 3.2.0 2011-11-14
|
2
|
+
|
3
|
+
* Added the ability to pause workers from the UI.
|
4
|
+
* If the worker is processing a job, it will pause the job on the next call to tick.
|
5
|
+
* JobWithStatus class now exposed the worker so the job can manually inspect the worker's status if necessary.
|
6
|
+
|
1
7
|
== 3.1.7 2011-11-03
|
2
8
|
|
3
9
|
* It seems that when jruby workers are started in server mode, they don't accept the -INT signal.
|
data/README.markdown
CHANGED
@@ -49,15 +49,16 @@ Display Process Status
|
|
49
49
|
----------------------
|
50
50
|
|
51
51
|
Added the ability to display process status in the worker "Processing" column on the workers and working pages.
|
52
|
-
To do this, yield the status message back in your perform method.
|
52
|
+
To do this, yield the status message back in your perform method. You should check that a block was sent. If you
|
53
|
+
set Resque.inline = true in development, then the block is not passed.
|
53
54
|
|
54
55
|
Class YourClass
|
55
56
|
|
56
57
|
self.perform(arg)
|
57
58
|
...your code here
|
58
|
-
yield "Your status message"
|
59
|
+
yield "Your status message" if block_given?
|
59
60
|
...more code
|
60
|
-
yield "Another status message"
|
61
|
+
yield "Another status message" if block_given?
|
61
62
|
...more code
|
62
63
|
end
|
63
64
|
end
|
@@ -128,7 +129,7 @@ the chained job from the preceding job, you just need to pass {'uuid' => uuid} a
|
|
128
129
|
end
|
129
130
|
|
130
131
|
So now, the data_contribution worker and the single_record_loader workers will update the same status on the status page.
|
131
|
-
You can call tick or set_status to add messages along the way too.
|
132
|
+
You can call #tick or #set_status to add messages along the way too.
|
132
133
|
|
133
134
|
You will want to override the completed method so that it isn't called until the very end of the entire process.
|
134
135
|
|
@@ -141,6 +142,94 @@ symbol to read the integer back. The redis entries created by these methods all
|
|
141
142
|
|
142
143
|
When you kill a job on the UI, it will kill all the workers in the chain.
|
143
144
|
|
145
|
+
Pause a Worker
|
146
|
+
--------------
|
147
|
+
|
148
|
+
The workers page now has a button for every worker to pause that worker.
|
149
|
+
|
150
|
+
### Regular Workers
|
151
|
+
|
152
|
+
For workers that do not inherit from JobWithStatus, this will pause the worker, but not the job. So if the worker is in
|
153
|
+
the middle of a job when it is paused, it will finish it's process, but then will not pick anything else up off the queue.
|
154
|
+
|
155
|
+
You can manually pause the processing though.
|
156
|
+
|
157
|
+
yield, which is used to set the workers status, as described above, now returns the worker.
|
158
|
+
|
159
|
+
Class YourClass
|
160
|
+
|
161
|
+
self.perform(arg)
|
162
|
+
...your code here
|
163
|
+
worker = yield "Your status message" if block_given?
|
164
|
+
|
165
|
+
if worker && worker.paused?
|
166
|
+
loop do
|
167
|
+
break unless worker.paused?
|
168
|
+
sleep 60
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
...continue
|
174
|
+
end
|
175
|
+
|
176
|
+
Remember to check that a block was sent. If you set Resque.inline = true in development, then the block is not passed.
|
177
|
+
|
178
|
+
|
179
|
+
### JobWithStatus Workers
|
180
|
+
|
181
|
+
For workers that do inherit from JobWithStatus or ChainedJobWithStatus, this will pause the worker, and will automatically pause the job it is processing
|
182
|
+
on the next call to #tick. The worker is also available to JobWithStatus so you can manually check it's status as well.
|
183
|
+
|
184
|
+
Class YourClass << Resque::JobWithStatus
|
185
|
+
|
186
|
+
def perform
|
187
|
+
...your code here
|
188
|
+
tick "Retrieving file." #You're process with pause here automatically and the status on the Status tab will be set to paused if the worker is paused.
|
189
|
+
|
190
|
+
#Alternatively, you have access to the worker, so you can pause the process yourself too.
|
191
|
+
if worker && worker.paused?
|
192
|
+
# There could be workers in a chained job still doing work.
|
193
|
+
loop do
|
194
|
+
pause! unless status.paused?
|
195
|
+
break unless worker.paused?
|
196
|
+
sleep 60
|
197
|
+
end
|
198
|
+
tick("Job resumed at #{Time.now}")
|
199
|
+
end
|
200
|
+
|
201
|
+
...continue
|
202
|
+
end
|
203
|
+
|
204
|
+
This will only pause the work being processed by the worker that was paused. If the job is paused by the call to #tick,
|
205
|
+
the job will sleep for 60 seconds before checking the status again.
|
206
|
+
|
207
|
+
You may have a series of ChainedJobWithStatus and you want all processing in the chain stopped.
|
208
|
+
|
209
|
+
Class YourClass << Resque::ChainedJobWithStatus
|
210
|
+
|
211
|
+
def perform
|
212
|
+
...your code here
|
213
|
+
tick "Retrieving file." #You're process with pause here automatically and the status on the Status tab will be set to paused if the worker is paused.
|
214
|
+
|
215
|
+
#Alternatively, you have access to the worker, so you can pause the process yourself too.
|
216
|
+
if (worker && worker.paused?) || status.paused?
|
217
|
+
# There could be workers in a chained job still doing work.
|
218
|
+
loop do
|
219
|
+
pause! unless status.paused?
|
220
|
+
break unless worker.paused?
|
221
|
+
sleep 60
|
222
|
+
end
|
223
|
+
tick("Job resumed at #{Time.now}")
|
224
|
+
end
|
225
|
+
|
226
|
+
...continue
|
227
|
+
end
|
228
|
+
|
229
|
+
By looking at the status.paused? method too, this process will stop, even if it's worker has not been paused.
|
230
|
+
But be aware, if this worker does other jobs, it will not process anything else and it's queue could get backed up.
|
231
|
+
This is where pausing one worker, could affect other, unrelated workers and jobs from getting backed up as well.
|
232
|
+
|
144
233
|
Throttle a Queue
|
145
234
|
----------------
|
146
235
|
|
data/VERSION.yml
CHANGED
@@ -58,6 +58,18 @@ class ResqueController < ApplicationController
|
|
58
58
|
redirect_to(:action => "workers")
|
59
59
|
end
|
60
60
|
|
61
|
+
def pause_worker
|
62
|
+
worker = find_worker(params[:worker])
|
63
|
+
worker.pause if worker
|
64
|
+
redirect_to(:action => "workers")
|
65
|
+
end
|
66
|
+
|
67
|
+
def continue_worker
|
68
|
+
worker = find_worker(params[:worker])
|
69
|
+
worker.continue if worker
|
70
|
+
redirect_to(:action => "workers")
|
71
|
+
end
|
72
|
+
|
61
73
|
def restart_worker
|
62
74
|
worker = find_worker(params[:worker])
|
63
75
|
worker.restart if worker
|
@@ -1,110 +1,130 @@
|
|
1
|
-
|
2
1
|
<% if params[:id] && worker = find_worker(params[:id]) %>
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
<
|
3
|
+
<h1>Worker <%= worker %></h1>
|
4
|
+
<table class='workers'>
|
5
|
+
<tr>
|
6
|
+
<th> </th>
|
7
|
+
<th>Host</th>
|
8
|
+
<th>Pid</th>
|
9
|
+
<th>Thread</th>
|
10
|
+
<th>Started</th>
|
11
|
+
<th>Paused</th>
|
12
|
+
<th>Queues</th>
|
13
|
+
<th>Processed</th>
|
14
|
+
<th>Failed</th>
|
15
|
+
<th>Processing</th>
|
16
|
+
</tr>
|
17
|
+
<tr>
|
18
|
+
<td class='icon'>
|
19
|
+
<img src="<%= u "../../images/resque/#{state = worker.state}" %>.png" alt="<%= state %>" title="<%= state %>">
|
20
|
+
</td>
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
<td class='process'>
|
29
|
-
<% data = worker.processing || {} %>
|
30
|
-
<% if data['queue'] %>
|
31
|
-
<code><%= data['payload']['class'] %></code>
|
32
|
-
<small><%= link_to(format_time(Time.zone.parse(data['run_at'])), {:action => 'working', :id => worker.to_s.gsub(/\./,'_')}, :class => "queue time") %></small>
|
33
|
-
<br>
|
34
|
-
<small><%=worker.status%></small>
|
22
|
+
<% host, pid, thread, queues = worker.to_s.split(':') %>
|
23
|
+
<td><%= host %></td>
|
24
|
+
<td><%= pid %></td>
|
25
|
+
<td><%= thread %></td>
|
26
|
+
<td><span class="time"><%= format_time(Time.zone.parse(worker.started)) %></span></td>
|
27
|
+
<td>
|
28
|
+
<% if worker.paused? %>
|
29
|
+
<span class="time"><%= format_time(Time.zone.parse(worker.paused)) %></span>
|
35
30
|
<% else %>
|
36
|
-
|
31
|
+
<span>Not Paused</span>
|
37
32
|
<% end %>
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
<% elsif params[:id] %>
|
43
|
-
|
44
|
-
<h1>Worker doesn't exist</h1>
|
45
|
-
|
46
|
-
<% else %>
|
47
|
-
|
48
|
-
<h1 class='wi'><%= pluralize resque.workers.size, 'Worker' %></h1>
|
49
|
-
<p class='intro'>The workers listed below are all registered as active on your system.</p>
|
50
|
-
<table class='workers'>
|
51
|
-
<tr>
|
52
|
-
<th> </th>
|
53
|
-
<th>Where (ip):pid:thread</th>
|
54
|
-
<th>Queues</th>
|
55
|
-
<th>Processing</th>
|
56
|
-
<th> </th>
|
57
|
-
</tr>
|
58
|
-
<% upid = ''%>
|
59
|
-
<% for worker in (workers = resque.workers.sort_by { |w| w.to_s }) %>
|
60
|
-
<tr class="<%=state = worker.state%>">
|
61
|
-
<td class='icon'><img src="<%=u "../../images/resque/#{state}" %>.png" alt="<%= state %>" title="<%= state %>"></td>
|
62
|
-
|
63
|
-
<% host, pid, thread, queues = worker.to_s.split(':') %>
|
64
|
-
<td class='where'><%=link_to("#{host}:#{pid}:#{thread}",:action => 'workers', :id => worker.to_s.gsub(/\./,'_'))%></td>
|
65
|
-
<td class='queues'><%= queues.split(',').map { |q| link_to(q, {:action => 'queues', :id => q}, :class => 'queue-tag')}.join('').html_safe %></td>
|
66
|
-
|
33
|
+
</td>
|
34
|
+
<td class='queues'><%= queues.split(',').map { |q| link_to(q, {:action => 'queues', :id => q}, :class => 'queue-tag') }.join('').html_safe %></td>
|
35
|
+
<td><%= worker.processed %></td>
|
36
|
+
<td><%= worker.failed %></td>
|
67
37
|
<td class='process'>
|
68
38
|
<% data = worker.processing || {} %>
|
69
39
|
<% if data['queue'] %>
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
40
|
+
<code><%= data['payload']['class'] %></code>
|
41
|
+
<small><%= link_to(format_time(Time.zone.parse(data['run_at'])), {:action => 'working', :id => worker.to_s.gsub(/\./, '_')}, :class => "queue time") %></small>
|
42
|
+
<br>
|
43
|
+
<small><%= worker.status %></small>
|
74
44
|
<% else %>
|
75
|
-
|
76
|
-
<% end %>
|
77
|
-
</td>
|
78
|
-
<td>
|
79
|
-
<% if upid != pid %>
|
80
|
-
<%= button_to "Stop", {:controller=>'resque', :action=> 'stop_worker', :worker => worker.to_s}, :class => 'clear-failed', :title => "This will stop all workers on #{host} in pid #{pid}: #{worker.workers_in_pid.collect{|w| w.to_s}.join(', ')}", :method => :post %>
|
81
|
-
<%= button_to "Restart", {:controller=>'resque', :action=> 'restart_worker', :worker => worker.to_s}, :class => 'clear-failed', :title => "This will restart all workers on #{host} in pid #{pid}: #{worker.workers_in_pid.collect{|w| w.to_s}.join(', ')}", :method => :post %>
|
82
|
-
<% upid = pid %>
|
45
|
+
<span class='waiting'>Waiting for a job...</span>
|
83
46
|
<% end %>
|
84
47
|
</td>
|
85
48
|
</tr>
|
86
|
-
|
87
|
-
|
49
|
+
</table>
|
50
|
+
|
51
|
+
<% elsif params[:id] %>
|
52
|
+
|
53
|
+
<h1>Worker doesn't exist</h1>
|
54
|
+
|
55
|
+
<% else %>
|
56
|
+
|
57
|
+
<h1 class='wi'><%= pluralize resque.workers.size, 'Worker' %></h1>
|
58
|
+
<p class='intro'>The workers listed below are all registered as active on your system.</p>
|
59
|
+
<table class='workers'>
|
88
60
|
<tr>
|
89
|
-
<
|
61
|
+
<th> </th>
|
62
|
+
<th>Where (ip):pid:thread</th>
|
63
|
+
<th>Queues</th>
|
64
|
+
<th>Processing</th>
|
65
|
+
<th> </th>
|
90
66
|
</tr>
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
67
|
+
<% upid = '' %>
|
68
|
+
<% for worker in (workers = resque.workers.sort_by { |w| w.to_s }) %>
|
69
|
+
<tr class="<%= state = worker.state %>">
|
70
|
+
<td class='icon'>
|
71
|
+
<img src="<%= u "../../images/resque/#{state}" %>.png" alt="<%= state %>" title="<%= state %>"></td>
|
72
|
+
|
73
|
+
<% host, pid, thread, queues = worker.to_s.split(':') %>
|
74
|
+
<td class='where'><%= link_to("#{host}:#{pid}:#{thread}", :action => 'workers', :id => worker.to_s.gsub(/\./, '_')) %></td>
|
75
|
+
<td class='queues'><%= queues.split(',').map { |q| link_to(q, {:action => 'queues', :id => q}, :class => 'queue-tag') }.join('').html_safe %></td>
|
76
|
+
|
77
|
+
<td class='process'>
|
78
|
+
<% data = worker.processing || {} %>
|
79
|
+
<% if data['queue'] %>
|
80
|
+
<code><%= data['payload']['class'] %></code>
|
81
|
+
<small><%= link_to(format_time(Time.zone.parse(data['run_at'])), {:action => 'working', :id => worker.to_s.gsub(/\./, '_')}, :class => "queue time") %></small>
|
82
|
+
<br/>
|
83
|
+
<small><%= worker.status %></small>
|
84
|
+
<% else %>
|
85
|
+
<span class='waiting'>Waiting for a job...</span>
|
86
|
+
<% end %>
|
87
|
+
</td>
|
88
|
+
<td>
|
89
|
+
<% if upid != pid %>
|
90
|
+
<%= button_to "Stop", {:controller=>'resque', :action=> 'stop_worker', :worker => worker.to_s}, :class => 'clear-failed', :title => "This will stop all workers on #{host} in pid #{pid}: #{worker.workers_in_pid.collect { |w| w.to_s }.join(', ')}", :method => :post %>
|
91
|
+
<% if worker.paused? %>
|
92
|
+
<%= button_to "Unpause", {:controller=>'resque', :action=> 'continue_worker', :worker => worker.to_s}, :class => 'clear-failed', :title => "This will unpause all workers on #{host} in pid #{pid}: #{worker.workers_in_pid.collect { |w| w.to_s }.join(', ')}", :method => :post %>
|
93
|
+
<% else %>
|
94
|
+
<%= button_to "Pause", {:controller=>'resque', :action=> 'pause_worker', :worker => worker.to_s}, :class => 'clear-failed', :title => "This will pause all workers on #{host} in pid #{pid}: #{worker.workers_in_pid.collect { |w| w.to_s }.join(', ')}", :method => :post %>
|
95
|
+
<% end %>
|
96
|
+
<%= button_to "Restart", {:controller=>'resque', :action=> 'restart_worker', :worker => worker.to_s}, :class => 'clear-failed', :title => "This will restart all workers on #{host} in pid #{pid}: #{worker.workers_in_pid.collect { |w| w.to_s }.join(', ')}", :method => :post %>
|
97
|
+
<% upid = pid %>
|
98
|
+
<% end %>
|
99
|
+
</td>
|
100
|
+
</tr>
|
101
|
+
<% end %>
|
102
|
+
<% if workers.empty? %>
|
103
|
+
<tr>
|
104
|
+
<td colspan='5' class='no-data'>There are no registered workers</td>
|
105
|
+
</tr>
|
106
|
+
<% end %>
|
107
|
+
</table>
|
108
|
+
<%= poll %>
|
109
|
+
<br/>
|
110
|
+
<hr/>
|
111
|
+
<h1 class='wi'>Start New Workers</h1>
|
112
|
+
<%= form_tag :action => 'start_worker' do -%>
|
113
|
+
<ul class='new_worker'>
|
114
|
+
<li>
|
115
|
+
<dl>
|
116
|
+
<dt>Queue(s)</dt>
|
117
|
+
<dd><%= text_field_tag :queues, nil, :size => 125 %>
|
118
|
+
<br/> Prefix each worker with a '#', comma separate the list of queues you want each worker to monitor.
|
119
|
+
No Spaces. #queue1,queue2#queue3#queue2 will produce 3 workers in 3 threads.
|
120
|
+
</dd>
|
121
|
+
<dt>Host(s)/IP(s)</dt>
|
122
|
+
<dd><%= text_field_tag :hosts, nil, :size => 125 %>
|
123
|
+
<br/> Comma separate the IP address of the servers where you want your worker to run.
|
124
|
+
</dd>
|
125
|
+
<dt><%= submit_tag "Start", :id => "submit" %></dt>
|
126
|
+
</dl>
|
127
|
+
</li>
|
128
|
+
</ul>
|
129
|
+
<% end -%>
|
110
130
|
<% end %>
|
@@ -68,7 +68,7 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
68
68
|
desc "Gracefully kill a worker. If the worker is working, it will finish before shutting down. arg: host=ip pid=pid"
|
69
69
|
task :quit_worker, :roles => :resque do
|
70
70
|
if ENV['host'].nil? || ENV['host'].empty? || ENV['pid'].nil? || ENV['pid'].empty?
|
71
|
-
puts 'You must enter the host and pid to kill..cap resque:
|
71
|
+
puts 'You must enter the host and pid to kill..cap resque:quit_worker host=ip pid=pid'
|
72
72
|
else
|
73
73
|
hosts = ENV['host'] || find_servers_for_task(current_task).collect { |s| s.host }
|
74
74
|
if RUBY_PLATFORM =~ /java/
|
@@ -82,6 +82,26 @@ Capistrano::Configuration.instance(:must_exist).load do
|
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
85
|
+
desc "Pause all workers in a single process. arg: host=ip pid=pid"
|
86
|
+
task :pause_worker, :roles => :resque do
|
87
|
+
if ENV['host'].nil? || ENV['host'].empty? || ENV['pid'].nil? || ENV['pid'].empty?
|
88
|
+
puts 'You must enter the host and pid to kill..cap resque:pause_worker host=ip pid=pid'
|
89
|
+
else
|
90
|
+
hosts = ENV['host'] || find_servers_for_task(current_task).collect { |s| s.host }
|
91
|
+
run("kill -USR2 #{ENV['pid']}", :hosts => hosts)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
desc "Continue all workers in a single process that have been paused. arg: host=ip pid=pid"
|
96
|
+
task :continue_worker, :roles => :resque do
|
97
|
+
if ENV['host'].nil? || ENV['host'].empty? || ENV['pid'].nil? || ENV['pid'].empty?
|
98
|
+
puts 'You must enter the host and pid to kill..cap resque:continue_worker host=ip pid=pid'
|
99
|
+
else
|
100
|
+
hosts = ENV['host'] || find_servers_for_task(current_task).collect { |s| s.host }
|
101
|
+
run("kill -CONT #{ENV['pid']}", :hosts => hosts)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
85
105
|
desc "Gracefully kill all workers on all servers. If the worker is working, it will finish before shutting down."
|
86
106
|
task :quit_workers, :roles => :resque do
|
87
107
|
default_run_options[:pty] = true
|
@@ -3,9 +3,73 @@ module Resque
|
|
3
3
|
# Attempts to perform the work represented by this job instance.
|
4
4
|
# Calls #perform on the class given in the payload with the
|
5
5
|
# arguments given in the payload.
|
6
|
-
#
|
6
|
+
# A block is sent so a message can be yielded back to be set in the worker.
|
7
7
|
def perform
|
8
|
-
|
8
|
+
job = payload_class
|
9
|
+
job_args = args || []
|
10
|
+
job_was_performed = false
|
11
|
+
|
12
|
+
before_hooks = Plugin.before_hooks(job)
|
13
|
+
around_hooks = Plugin.around_hooks(job)
|
14
|
+
after_hooks = Plugin.after_hooks(job)
|
15
|
+
failure_hooks = Plugin.failure_hooks(job)
|
16
|
+
|
17
|
+
begin
|
18
|
+
# Execute before_perform hook. Abort the job gracefully if
|
19
|
+
# Resque::DontPerform is raised.
|
20
|
+
begin
|
21
|
+
before_hooks.each do |hook|
|
22
|
+
job.send(hook, *job_args)
|
23
|
+
end
|
24
|
+
rescue DontPerform
|
25
|
+
return false
|
26
|
+
end
|
27
|
+
|
28
|
+
# Execute the job. Do it in an around_perform hook if available.
|
29
|
+
if around_hooks.empty?
|
30
|
+
job.perform(*job_args) do |status|
|
31
|
+
self.worker.status = status if status.present?
|
32
|
+
self.worker
|
33
|
+
end
|
34
|
+
job_was_performed = true
|
35
|
+
else
|
36
|
+
# We want to nest all around_perform plugins, with the last one
|
37
|
+
# finally calling perform
|
38
|
+
stack = around_hooks.reverse.inject(nil) do |last_hook, hook|
|
39
|
+
if last_hook
|
40
|
+
lambda do
|
41
|
+
job.send(hook, *job_args) { last_hook.call }
|
42
|
+
end
|
43
|
+
else
|
44
|
+
lambda do
|
45
|
+
job.send(hook, *job_args) do
|
46
|
+
result = job.perform(*job_args) do |status|
|
47
|
+
self.worker.status = status if status.present?
|
48
|
+
self.worker
|
49
|
+
end
|
50
|
+
job_was_performed = true
|
51
|
+
result
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
stack.call
|
57
|
+
end
|
58
|
+
|
59
|
+
# Execute after_perform hook
|
60
|
+
after_hooks.each do |hook|
|
61
|
+
job.send(hook, *job_args)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Return true if the job was performed
|
65
|
+
return job_was_performed
|
66
|
+
|
67
|
+
# If an exception occurs during the job execution, look for an
|
68
|
+
# on_failure hook then re-raise.
|
69
|
+
rescue Object => e
|
70
|
+
failure_hooks.each { |hook| job.send(hook, e, *job_args) }
|
71
|
+
raise e
|
72
|
+
end
|
9
73
|
end
|
10
74
|
|
11
75
|
end
|