resque_manager 3.3.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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +21 -0
- data/README.markdown +417 -0
- data/Rakefile +41 -0
- data/app/assets/images/resque_manager/idle.png +0 -0
- data/app/assets/images/resque_manager/poll.png +0 -0
- data/app/assets/images/resque_manager/working.png +0 -0
- data/app/assets/javascripts/resque_manager/application.js +15 -0
- data/app/assets/javascripts/resque_manager/jquery-1.3.2.min.js +19 -0
- data/app/assets/javascripts/resque_manager/jquery.relatize_date.js +95 -0
- data/app/assets/javascripts/resque_manager/ranger.js +24 -0
- data/app/assets/stylesheets/resque_manager/application.css +14 -0
- data/app/assets/stylesheets/resque_manager/resque/resque.css +93 -0
- data/app/assets/stylesheets/resque_manager/resque/resque_reset.css +48 -0
- data/app/assets/stylesheets/resque_manager/resque_cleaner/cleaner.css +62 -0
- data/app/controllers/resque_manager/resque_controller.rb +313 -0
- data/app/helpers/resque_manager/application_helper.rb +4 -0
- data/app/helpers/resque_manager/resque_helper.rb +142 -0
- data/app/models/resque_manager/paginate.rb +54 -0
- data/app/views/layouts/resque_manager/application.html.erb +37 -0
- data/app/views/resque_manager/resque/_key.html.erb +17 -0
- data/app/views/resque_manager/resque/_limiter.html.erb +12 -0
- data/app/views/resque_manager/resque/_next_more.html.erb +10 -0
- data/app/views/resque_manager/resque/_paginate.html.erb +53 -0
- data/app/views/resque_manager/resque/_queues.html.erb +59 -0
- data/app/views/resque_manager/resque/_status_styles.erb +98 -0
- data/app/views/resque_manager/resque/_workers.html.erb +138 -0
- data/app/views/resque_manager/resque/_working.html.erb +69 -0
- data/app/views/resque_manager/resque/cleaner.html.erb +41 -0
- data/app/views/resque_manager/resque/cleaner_exec.html.erb +6 -0
- data/app/views/resque_manager/resque/cleaner_list.html.erb +172 -0
- data/app/views/resque_manager/resque/delayed.html.erb +35 -0
- data/app/views/resque_manager/resque/delayed_timestamp.html.erb +26 -0
- data/app/views/resque_manager/resque/error.erb +1 -0
- data/app/views/resque_manager/resque/overview.html.erb +4 -0
- data/app/views/resque_manager/resque/schedule.html.erb +96 -0
- data/app/views/resque_manager/resque/stats.html.erb +62 -0
- data/app/views/resque_manager/resque/status.html.erb +57 -0
- data/app/views/resque_manager/resque/statuses.html.erb +72 -0
- data/app/views/resque_manager/resque/workers.html.erb +1 -0
- data/config/routes.rb +38 -0
- data/config/sample_redis.yml +43 -0
- data/config/sample_resque_manager.yml +23 -0
- data/lib/resque_manager/engine.rb +9 -0
- data/lib/resque_manager/overrides/resque/failure/redis.rb +11 -0
- data/lib/resque_manager/overrides/resque/job.rb +69 -0
- data/lib/resque_manager/overrides/resque/resque.rb +8 -0
- data/lib/resque_manager/overrides/resque/worker.rb +291 -0
- data/lib/resque_manager/overrides/resque_scheduler/resque_scheduler.rb +58 -0
- data/lib/resque_manager/overrides/resque_status/chained_status.rb +46 -0
- data/lib/resque_manager/overrides/resque_status/hash.rb +12 -0
- data/lib/resque_manager/overrides/resque_status/status.rb +161 -0
- data/lib/resque_manager/recipes.rb +185 -0
- data/lib/resque_manager/version.rb +3 -0
- data/lib/resque_manager.rb +47 -0
- data/lib/tasks/failure.rake +8 -0
- data/lib/tasks/scheduler.rake +11 -0
- data/lib/tasks/worker.rake +129 -0
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +15 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config/application.rb +65 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +67 -0
- data/test/dummy/config/environments/test.rb +37 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/log/development.log +5045 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/dummy/tmp/cache/assets/C2A/A10/sprockets%2Fb2e622954654f415590723e9b882063e +0 -0
- data/test/dummy/tmp/cache/assets/C60/1D0/sprockets%2F8ed12e4193473760f95b973567a8c206 +0 -0
- data/test/dummy/tmp/cache/assets/CA1/970/sprockets%2Fc387148880e015d1eab0dc838b326022 +0 -0
- data/test/dummy/tmp/cache/assets/CAE/930/sprockets%2Fe227278d3c65d8aa1159da720263f771 +0 -0
- data/test/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
- data/test/dummy/tmp/cache/assets/CDC/E30/sprockets%2Fe1207380d69eeee3284e02636c26f24a +0 -0
- data/test/dummy/tmp/cache/assets/CF1/720/sprockets%2Fd91a5918f5aa43a43c8135a67c78e989 +0 -0
- data/test/dummy/tmp/cache/assets/D0E/820/sprockets%2F00c6cc9dc46bf64347b3775d7d15541b +0 -0
- data/test/dummy/tmp/cache/assets/D16/180/sprockets%2F73d6fa09352cb76ac81e1683e832b93f +0 -0
- data/test/dummy/tmp/cache/assets/D27/170/sprockets%2Fec164819553e2e5b28f1efc9bd970978 +0 -0
- data/test/dummy/tmp/cache/assets/D2B/DA0/sprockets%2F989465d3ea8575dd0b54981a9e8add38 +0 -0
- data/test/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/test/dummy/tmp/cache/assets/D37/1F0/sprockets%2F97119b908ebed2633edfd00ac90d9011 +0 -0
- data/test/dummy/tmp/cache/assets/D38/FB0/sprockets%2F74e5ba1cca7a1470d53c54fb60368b78 +0 -0
- data/test/dummy/tmp/cache/assets/D42/4E0/sprockets%2F0fa6e3c14356aa527d68a8d56fa37f28 +0 -0
- data/test/dummy/tmp/cache/assets/D43/C20/sprockets%2F1efd074fd1074b3dc88145b480ff961f +0 -0
- data/test/dummy/tmp/cache/assets/D46/CD0/sprockets%2F67f1ef70e7ede542318b8d55e25b16c3 +0 -0
- data/test/dummy/tmp/cache/assets/D4E/1B0/sprockets%2Ff7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/test/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/test/dummy/tmp/cache/assets/D68/080/sprockets%2Fa26f2ae225aa4b87c462d540c7cf43f9 +0 -0
- data/test/dummy/tmp/cache/assets/D9A/B20/sprockets%2F0eddc19d46318e2e286cc171ae4cc73e +0 -0
- data/test/dummy/tmp/cache/assets/DA4/900/sprockets%2F515bf984438c6ec4b8a515fcc13baf8e +0 -0
- data/test/dummy/tmp/cache/assets/DBD/070/sprockets%2F60ffef45ddefd5c7746d17977fff0717 +0 -0
- data/test/dummy/tmp/cache/assets/DD7/AC0/sprockets%2Fc7c983c5c607dbfdb726eecc36146ca9 +0 -0
- data/test/dummy/tmp/cache/assets/DDC/400/sprockets%2Fcffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/test/dummy/tmp/cache/assets/DF5/480/sprockets%2Fea4f3c726fc1046cad1ad243faf84e7d +0 -0
- data/test/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/test/dummy/tmp/cache/assets/E2B/7A0/sprockets%2Fd44ef07be0aa6d5b5dea4d37d7f72b4f +0 -0
- data/test/functional/resque_manager/resque_controller_test.rb +9 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/resque_manager_test.rb +7 -0
- data/test/test_helper.rb +15 -0
- data/test/unit/helpers/resque_manager/resque_helper_test.rb +6 -0
- metadata +307 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<% @partial ||= partial -%>
|
|
2
|
+
|
|
3
|
+
<% @subtabs = resque.queues unless partial? %>
|
|
4
|
+
|
|
5
|
+
<% if queue = params[:id] %>
|
|
6
|
+
|
|
7
|
+
<h1>Pending jobs on <span class='hl'><%= queue %></span></h1>
|
|
8
|
+
<p class='sub'>Showing <%= start = params[:start].to_i %> to <%= start + 20 %> of
|
|
9
|
+
<b><%= size = resque.size(queue) %></b> jobs</p>
|
|
10
|
+
<table class='jobs'>
|
|
11
|
+
<tr>
|
|
12
|
+
<th>Class</th>
|
|
13
|
+
<th>Args</th>
|
|
14
|
+
<% if ResqueManager.applications.blank? %>
|
|
15
|
+
<th> </th>
|
|
16
|
+
<% end %>
|
|
17
|
+
</tr>
|
|
18
|
+
<% for job in (jobs = resque.peek(queue, start, 20)) %>
|
|
19
|
+
<tr>
|
|
20
|
+
<td class='class'><%= job['class'] %></td>
|
|
21
|
+
<td class='args'><%= job['args'].inspect.html_safe %></td>
|
|
22
|
+
<% if ResqueManager.applications.blank? %>
|
|
23
|
+
<td>
|
|
24
|
+
<%= button_to "Remove", {:controller => 'resque', :action => 'remove_job', :class => job['class'], :args => Resque.encode(job['args'])}, :class => 'clear-failed', :method => :post %>
|
|
25
|
+
</td>
|
|
26
|
+
<% end %>
|
|
27
|
+
</tr>
|
|
28
|
+
<% end %>
|
|
29
|
+
<% if jobs.empty? %>
|
|
30
|
+
<tr>
|
|
31
|
+
<td class='no-data' colspan='3'>There are no pending jobs in this queue</td>
|
|
32
|
+
</tr>
|
|
33
|
+
<% end %>
|
|
34
|
+
</table>
|
|
35
|
+
<%= render(:partial => 'next_more', :locals => {:start => start, :size => size}) %>
|
|
36
|
+
<% else %>
|
|
37
|
+
|
|
38
|
+
<h1 class='wi'>Queues</h1>
|
|
39
|
+
|
|
40
|
+
<p class='intro'>The list below contains all the registered queues with the number of jobs currently in the
|
|
41
|
+
queue. Select a queue from above to view all jobs currently pending on the queue.</p>
|
|
42
|
+
<table class='queues'>
|
|
43
|
+
<tr>
|
|
44
|
+
<th>Name</th>
|
|
45
|
+
<th>Jobs</th>
|
|
46
|
+
</tr>
|
|
47
|
+
<% for queue in resque.queues.sort_by { |q| q.to_s } %>
|
|
48
|
+
<tr>
|
|
49
|
+
<td class='queue'><%= link_to(queue, {:action => "queues", :id => queue}, :class => 'queue') %></td>
|
|
50
|
+
<td class='size'><%= resque.size queue %></td>
|
|
51
|
+
</tr>
|
|
52
|
+
<% end %>
|
|
53
|
+
<tr class='failed'>
|
|
54
|
+
<td class='queue failed'><%= link_to('failed', {:action => "cleaner"}, :class => 'queue') %></td>
|
|
55
|
+
<td class='size'><%= Resque::Failure.count %></td>
|
|
56
|
+
</tr>
|
|
57
|
+
</table>
|
|
58
|
+
|
|
59
|
+
<% end %>
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<style type="text/css" media="screen">
|
|
2
|
+
th.progress {
|
|
3
|
+
width: 100px;
|
|
4
|
+
}
|
|
5
|
+
td.progress {
|
|
6
|
+
position: relative;
|
|
7
|
+
width: 100px;
|
|
8
|
+
display:block;
|
|
9
|
+
}
|
|
10
|
+
td.status {
|
|
11
|
+
font-weight: bold;
|
|
12
|
+
}
|
|
13
|
+
td.progress .progress-bar {
|
|
14
|
+
position: absolute;
|
|
15
|
+
top: 0px;
|
|
16
|
+
left: 0px;
|
|
17
|
+
background: #999;
|
|
18
|
+
display:block;
|
|
19
|
+
height: 100%;
|
|
20
|
+
z-index: 0;
|
|
21
|
+
opacity: 0.5;
|
|
22
|
+
-moz-opacity: 0.5;
|
|
23
|
+
-webkit-opacity: 0.5;
|
|
24
|
+
}
|
|
25
|
+
td.progress .progress-pct {
|
|
26
|
+
z-index: 10;
|
|
27
|
+
color: #333;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.status-holder {
|
|
31
|
+
background: #F7F7F7;
|
|
32
|
+
border: 1px solid #E5E5E5;
|
|
33
|
+
padding: 20px;
|
|
34
|
+
font-size: 110%;
|
|
35
|
+
margin-bottom: 40px;
|
|
36
|
+
}
|
|
37
|
+
.status-progress {
|
|
38
|
+
width: 100%;
|
|
39
|
+
height: 30px;
|
|
40
|
+
border: 1px solid #CCC;
|
|
41
|
+
background: #E5E5E5;
|
|
42
|
+
position:relative;
|
|
43
|
+
margin: 5px 0px;
|
|
44
|
+
}
|
|
45
|
+
.status-progress-bar {
|
|
46
|
+
position:absolute;
|
|
47
|
+
top: 0px;
|
|
48
|
+
left: 0px;
|
|
49
|
+
height: 30px;
|
|
50
|
+
background: #CCC;
|
|
51
|
+
}
|
|
52
|
+
.status-progress p {
|
|
53
|
+
position:absolute;
|
|
54
|
+
top: 5px;
|
|
55
|
+
left: 10px;
|
|
56
|
+
z-index: 15;
|
|
57
|
+
display:block;
|
|
58
|
+
color: #FFF;
|
|
59
|
+
padding: 0px;
|
|
60
|
+
font-weight: bold;
|
|
61
|
+
}
|
|
62
|
+
.status-message {
|
|
63
|
+
font-weight: bold;
|
|
64
|
+
}
|
|
65
|
+
.status-time {
|
|
66
|
+
font-size: 70%;
|
|
67
|
+
padding: 10px 0px;
|
|
68
|
+
color: #999;
|
|
69
|
+
}
|
|
70
|
+
.status-progress-bar.status-completed {
|
|
71
|
+
background:#61BF55;
|
|
72
|
+
}
|
|
73
|
+
.status-progress-bar.status-failed {
|
|
74
|
+
background: #E47E74;
|
|
75
|
+
}
|
|
76
|
+
.status-progress-bar.status-working {
|
|
77
|
+
background: #528499;
|
|
78
|
+
}
|
|
79
|
+
.status-progress-bar.status-killed {
|
|
80
|
+
background: #B84F16;
|
|
81
|
+
}
|
|
82
|
+
.status-completed {
|
|
83
|
+
color:#61BF55;
|
|
84
|
+
}
|
|
85
|
+
.status-failed {
|
|
86
|
+
color: #E47E74;
|
|
87
|
+
}
|
|
88
|
+
.status-working {
|
|
89
|
+
color: #528499;
|
|
90
|
+
}
|
|
91
|
+
.status-killed {
|
|
92
|
+
color: #B84F16;
|
|
93
|
+
}
|
|
94
|
+
#main a.kill:link, #main a.kill:visited {
|
|
95
|
+
color: #B84F16;
|
|
96
|
+
font-weight: bold;
|
|
97
|
+
}
|
|
98
|
+
</style>
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
<% if params[:id] && worker = find_worker(params[:id]) %>
|
|
2
|
+
|
|
3
|
+
<h1>Worker <%= worker %></h1>
|
|
4
|
+
<table class='workers'>
|
|
5
|
+
<tr>
|
|
6
|
+
<th> </th>
|
|
7
|
+
<th>Host</th>
|
|
8
|
+
<th>Path</th>
|
|
9
|
+
<th>Pid</th>
|
|
10
|
+
<th>Thread</th>
|
|
11
|
+
<th>Started</th>
|
|
12
|
+
<th>Paused</th>
|
|
13
|
+
<th>Queues</th>
|
|
14
|
+
<th>Processed</th>
|
|
15
|
+
<th>Failed</th>
|
|
16
|
+
<th>Processing</th>
|
|
17
|
+
</tr>
|
|
18
|
+
<tr>
|
|
19
|
+
<td class='icon'>
|
|
20
|
+
<img src="<%= "/assets/resque_manager/#{state = worker.state}" %>.png" alt="<%= state %>" title="<%= state %>">
|
|
21
|
+
</td>
|
|
22
|
+
|
|
23
|
+
<% host, pid, thread, path, queues = worker.to_s.split(':') %>
|
|
24
|
+
<td><%= host %></td>
|
|
25
|
+
<td><%= path %></td>
|
|
26
|
+
<td><%= pid %></td>
|
|
27
|
+
<td><%= thread %></td>
|
|
28
|
+
<td><span class="time"><%= format_time(Time.zone.parse(worker.started)) %></span></td>
|
|
29
|
+
<td>
|
|
30
|
+
<% if worker.paused? %>
|
|
31
|
+
<span class="time"><%= format_time(Time.zone.parse(worker.paused)) %></span>
|
|
32
|
+
<% else %>
|
|
33
|
+
<span>Not Paused</span>
|
|
34
|
+
<% end %>
|
|
35
|
+
</td>
|
|
36
|
+
<td class='queues'><%= queues.split(',').map { |q| link_to(q, {:action => 'queues', :id => q}, :class => 'queue-tag') }.join('').html_safe %></td>
|
|
37
|
+
<td><%= worker.processed %></td>
|
|
38
|
+
<td><%= worker.failed %></td>
|
|
39
|
+
<td class='process'>
|
|
40
|
+
<% data = worker.processing || {} %>
|
|
41
|
+
<% if data['queue'] %>
|
|
42
|
+
<code><%= data['payload']['class'] %></code>
|
|
43
|
+
<small><%= link_to(format_time(Time.zone.parse(data['run_at'])), {:action => 'working', :id => worker.to_s.gsub(/\./, '_')}, :class => "queue time") %></small>
|
|
44
|
+
<br>
|
|
45
|
+
<small><%= worker.overview_message %></small>
|
|
46
|
+
<% else %>
|
|
47
|
+
<span class='waiting'>Waiting for a job...</span>
|
|
48
|
+
<% end %>
|
|
49
|
+
</td>
|
|
50
|
+
</tr>
|
|
51
|
+
</table>
|
|
52
|
+
|
|
53
|
+
<% elsif params[:id] %>
|
|
54
|
+
|
|
55
|
+
<h1>Worker doesn't exist</h1>
|
|
56
|
+
|
|
57
|
+
<% else %>
|
|
58
|
+
|
|
59
|
+
<h1 class='wi'><%= pluralize resque.workers.size, 'Worker' %></h1>
|
|
60
|
+
<p class='intro'>The workers listed below are all registered as active on your system.</p>
|
|
61
|
+
<table class='workers'>
|
|
62
|
+
<tr>
|
|
63
|
+
<th> </th>
|
|
64
|
+
<th>Where (ip):pid:thread:path</th>
|
|
65
|
+
<th>Queues</th>
|
|
66
|
+
<th>Processing</th>
|
|
67
|
+
<th> </th>
|
|
68
|
+
</tr>
|
|
69
|
+
<% upid = '' %>
|
|
70
|
+
<% for worker in (workers = resque.workers.sort_by { |w| w.to_s }) %>
|
|
71
|
+
<tr class="<%= state = worker.state %>">
|
|
72
|
+
<td class='icon'>
|
|
73
|
+
<img src="<%="/assets/resque_manager/#{state}" %>.png" alt="<%= state %>" title="<%= state %>"></td>
|
|
74
|
+
|
|
75
|
+
<% host, pid, thread, path, queues = worker.to_s.split(':') %>
|
|
76
|
+
<td class='where'><%= link_to("#{host}:#{pid}:#{thread}:#{path}", :action => 'workers', :id => worker.to_s.gsub(/\./, '_')) %></td>
|
|
77
|
+
<td class='queues'><%= queues.split(',').map { |q| link_to(q, {:action => 'queues', :id => q}, :class => 'queue-tag') }.join('').html_safe %></td>
|
|
78
|
+
|
|
79
|
+
<td class='process'>
|
|
80
|
+
<% data = worker.processing || {} %>
|
|
81
|
+
<% if data['queue'] %>
|
|
82
|
+
<code><%= data['payload']['class'] %></code>
|
|
83
|
+
<small><%= link_to(format_time(Time.zone.parse(data['run_at'])), {:action => 'working', :id => worker.to_s.gsub(/\./, '_')}, :class => "queue time") %></small>
|
|
84
|
+
<br/>
|
|
85
|
+
<small><%= worker.overview_message %></small>
|
|
86
|
+
<% else %>
|
|
87
|
+
<span class='waiting'>Waiting for a job...</span>
|
|
88
|
+
<% end %>
|
|
89
|
+
</td>
|
|
90
|
+
<td>
|
|
91
|
+
<% if upid != pid %>
|
|
92
|
+
<%= 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 %>
|
|
93
|
+
<% if worker.paused? %>
|
|
94
|
+
<%= 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 %>
|
|
95
|
+
<% else %>
|
|
96
|
+
<%= 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 %>
|
|
97
|
+
<% end %>
|
|
98
|
+
<%= 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 %>
|
|
99
|
+
<% upid = pid %>
|
|
100
|
+
<% end %>
|
|
101
|
+
</td>
|
|
102
|
+
</tr>
|
|
103
|
+
<% end %>
|
|
104
|
+
<% if workers.empty? %>
|
|
105
|
+
<tr>
|
|
106
|
+
<td colspan='5' class='no-data'>There are no registered workers</td>
|
|
107
|
+
</tr>
|
|
108
|
+
<% end %>
|
|
109
|
+
</table>
|
|
110
|
+
<%= poll %>
|
|
111
|
+
<br/>
|
|
112
|
+
<hr/>
|
|
113
|
+
<h1 class='wi'>Start New Workers</h1>
|
|
114
|
+
<%= form_tag :action => 'start_worker' do -%>
|
|
115
|
+
<ul class='new_worker'>
|
|
116
|
+
<li>
|
|
117
|
+
<dl>
|
|
118
|
+
<dt>Queue(s)</dt>
|
|
119
|
+
<dd><%= text_field_tag :queues, nil, :size => 125 %>
|
|
120
|
+
<br/> Prefix each worker with a '#', comma separate the list of queues you want each worker to monitor.
|
|
121
|
+
No Spaces. #queue1,queue2#queue3#queue2 will produce 3 workers in 3 threads.
|
|
122
|
+
</dd>
|
|
123
|
+
<dt>Host(s)/IP(s)</dt>
|
|
124
|
+
<dd><%= text_field_tag :hosts, nil, :size => 125 %>
|
|
125
|
+
<br/> Comma separate the IP address of the servers where you want your worker to run.
|
|
126
|
+
</dd>
|
|
127
|
+
<% if ResqueManager.applications.present? %>
|
|
128
|
+
<dt>Application</dt>
|
|
129
|
+
<dd><%= select_tag :application_path, options_for_select(ResqueManager.applications.to_a), :include_blank => true %>
|
|
130
|
+
<br/> The application where the workers are if not in the same application as the UI.
|
|
131
|
+
</dd>
|
|
132
|
+
<% end %>
|
|
133
|
+
<dt><%= submit_tag "Start", :id => "submit" %></dt>
|
|
134
|
+
</dl>
|
|
135
|
+
</li>
|
|
136
|
+
</ul>
|
|
137
|
+
<% end -%>
|
|
138
|
+
<% end %>
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
<% if params[:id] && (worker = find_worker(params[:id])) && !worker.job.empty? %>
|
|
2
|
+
<h1><%= worker %>'s job</h1>
|
|
3
|
+
|
|
4
|
+
<table>
|
|
5
|
+
<tr>
|
|
6
|
+
<th> </th>
|
|
7
|
+
<th>Where (ip):pid:thread:path</th>
|
|
8
|
+
<th>Queue</th>
|
|
9
|
+
<th>Started</th>
|
|
10
|
+
<th>Class</th>
|
|
11
|
+
<th>Args</th>
|
|
12
|
+
</tr>
|
|
13
|
+
<tr>
|
|
14
|
+
<td><img src="<%='assets/resque_manager/working.png' %>" alt="working" title="working"></td>
|
|
15
|
+
<% host, pid,thread, path, _ = worker.to_s.split(':') %>
|
|
16
|
+
<td><%= link_to("#{host}:#{pid}:#{thread}:#{path}", {:action => 'workers', :id => worker.to_s.gsub(/\./,'_')}) %></td>
|
|
17
|
+
<% data = worker.job %>
|
|
18
|
+
<% queue = data['queue'] %>
|
|
19
|
+
<td><%= link_to(queue, {:action => 'queues', :id => queue}, :class => 'queue') %></td>
|
|
20
|
+
<td><span class="time"><%= format_time(Time.zone.parse(data['run_at'].to_s)) %></span></td>
|
|
21
|
+
<td>
|
|
22
|
+
<code><%= data['payload']['class'] %></code>
|
|
23
|
+
</td>
|
|
24
|
+
<td><%= data['payload']['args'].inspect.html_safe %></td>
|
|
25
|
+
</tr>
|
|
26
|
+
</table>
|
|
27
|
+
|
|
28
|
+
<% else %>
|
|
29
|
+
|
|
30
|
+
<% workers = resque.working %>
|
|
31
|
+
<h1 class='wi'><%= workers.size %> of <%= resque.workers.size %> Workers Working</h1>
|
|
32
|
+
<p class='intro'>The list below contains all workers which are currently running a job.</p>
|
|
33
|
+
<table class='workers'>
|
|
34
|
+
<tr>
|
|
35
|
+
<th> </th>
|
|
36
|
+
<th>Where (ip):pid:thread:path</th>
|
|
37
|
+
<th>Queue</th>
|
|
38
|
+
<th>Processing</th>
|
|
39
|
+
</tr>
|
|
40
|
+
<% if workers.empty? %>
|
|
41
|
+
<tr>
|
|
42
|
+
<td colspan="4" class='no-data'>Nothing is happening right now...</td>
|
|
43
|
+
</tr>
|
|
44
|
+
<% end %>
|
|
45
|
+
|
|
46
|
+
<% for worker in workers.sort_by { |w| w.job['run_at'].to_s } %>
|
|
47
|
+
<% job = worker.job %>
|
|
48
|
+
<tr>
|
|
49
|
+
<td class='icon'><img src="<%="/assets/resque_manager/#{state = worker.state}" %>.png" alt="<%= state %>" title="<%= state %>"></td>
|
|
50
|
+
<% host, pid, thread, path, queues = worker.to_s.split(':') %>
|
|
51
|
+
<td class='where'><%= link_to("#{host}:#{pid}:#{thread}:#{path}", {:action => 'workers', :id => worker.to_s.gsub(/\./,'_')}) %></td>
|
|
52
|
+
<td class='queues queue'>
|
|
53
|
+
<%= link_to(job['queue'], {:action => 'queues', :id => job['queue']}, :class => 'queue-tag') %>
|
|
54
|
+
</td>
|
|
55
|
+
<td class='process'>
|
|
56
|
+
<% if job['queue'] %>
|
|
57
|
+
<code><%= job['payload']['class'] %></code>
|
|
58
|
+
<small><%= link_to(format_time(Time.zone.parse(job['run_at'].to_s)), {:action => 'working', :id => worker.to_s.gsub(/\./,'_')}, :class => 'queue time') %></small>
|
|
59
|
+
<br/>
|
|
60
|
+
<small><%=worker.overview_message%></small>
|
|
61
|
+
<% else %>
|
|
62
|
+
<span class='waiting'>Waiting for a job...</span>
|
|
63
|
+
<% end %>
|
|
64
|
+
</td>
|
|
65
|
+
</tr>
|
|
66
|
+
<% end %>
|
|
67
|
+
</table>
|
|
68
|
+
|
|
69
|
+
<% end %>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<div class="cleaner">
|
|
2
|
+
<div class="title clearfix">
|
|
3
|
+
<h1>Job Classes Failed</h1>
|
|
4
|
+
</div>
|
|
5
|
+
|
|
6
|
+
<table class="class_list">
|
|
7
|
+
<tr>
|
|
8
|
+
<th>Class</th>
|
|
9
|
+
<th>Failed</th>
|
|
10
|
+
<th>In last 1 hour</th>
|
|
11
|
+
<th>In last 3 hours</th>
|
|
12
|
+
<th>In last 24 hours</th>
|
|
13
|
+
<th>In last 3 days</th>
|
|
14
|
+
<th>In last 7 days</th>
|
|
15
|
+
</tr>
|
|
16
|
+
<% @stats.each do |klass, count| %>
|
|
17
|
+
<tr>
|
|
18
|
+
<td><%= klass %></td>
|
|
19
|
+
<td class="number"><a href="cleaner_list?c=<%= klass %>"><%= count["total"] %></a></td>
|
|
20
|
+
<td class="number"><a href="cleaner_list?c=<%= klass %>&f=1"><%= count["1h"] %></a></td>
|
|
21
|
+
<td class="number"><a href="cleaner_list?c=<%= klass %>&f=3"><%= count["3h"] %></a></td>
|
|
22
|
+
<td class="number"><a href="cleaner_list?c=<%= klass %>&f=24"><%= count["1d"] %></a></td>
|
|
23
|
+
<td class="number"><a href="cleaner_list?c=<%= klass %>&f=72"><%= count["3d"] %></a></td>
|
|
24
|
+
<td class="number"><a href="cleaner_list?c=<%= klass %>&f=168"><%= count["7d"] %></a></td>
|
|
25
|
+
</tr>
|
|
26
|
+
<% end %>
|
|
27
|
+
<tr class="total">
|
|
28
|
+
<td>Total</td>
|
|
29
|
+
<td class="number"><a href="cleaner_list"><%= @total["total"] %></a></td>
|
|
30
|
+
<td class="number"><a href="cleaner_list?f=1"><%= @total["1h"] %></a></td>
|
|
31
|
+
<td class="number"><a href="cleaner_list?f=3"><%= @total["3h"] %></a></td>
|
|
32
|
+
<td class="number"><a href="cleaner_list?f=24"><%= @total["1d"] %></a></td>
|
|
33
|
+
<td class="number"><a href="cleaner_list?f=72"><%= @total["3d"] %></a></td>
|
|
34
|
+
<td class="number"><a href="cleaner_list?f=168"><%= @total["7d"] %></a></td>
|
|
35
|
+
</tr>
|
|
36
|
+
</table>
|
|
37
|
+
|
|
38
|
+
<% if @cleaner.limiter.on? %>
|
|
39
|
+
<%= render :partial => 'limiter' %>
|
|
40
|
+
<% end %>
|
|
41
|
+
</div>
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
<!-- Many code was copied from failed.erb of the original resque -->
|
|
2
|
+
<div class="cleaner">
|
|
3
|
+
<div class="title clearfix">
|
|
4
|
+
<h1>Failed Jobs</h1>
|
|
5
|
+
</div>
|
|
6
|
+
|
|
7
|
+
<div class="clearfix">
|
|
8
|
+
<div class="control_panel sub_header">
|
|
9
|
+
<form method="get">
|
|
10
|
+
<span class="class_filter">
|
|
11
|
+
Class: <%= class_filter("filter_class","c",@klasses,@klass)%>
|
|
12
|
+
</span>
|
|
13
|
+
<span class="exception_filter">
|
|
14
|
+
Exception: <%= exception_filter("filter_class","ex",@exceptions,@exception)%>
|
|
15
|
+
</span>
|
|
16
|
+
<span class="time_filter">
|
|
17
|
+
From: <%= time_filter("filter_from","f",@from)%>
|
|
18
|
+
</span>
|
|
19
|
+
<span class="time_filter">
|
|
20
|
+
To: <%= time_filter("filter_to","t",@to)%>
|
|
21
|
+
</span>
|
|
22
|
+
<input type="submit" value="Filter" />
|
|
23
|
+
</form>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<% if @count > 0 %>
|
|
28
|
+
<div class="clearfix">
|
|
29
|
+
<div class="control_panel sub_header">
|
|
30
|
+
<%= form_tag('cleaner_exec', id: 'exec') do %>
|
|
31
|
+
<input type="hidden" name="c" value="<%=@klass%>" />
|
|
32
|
+
<input type="hidden" name="f" value="<%=@from%>" />
|
|
33
|
+
<input type="hidden" name="t" value="<%=@to%>" />
|
|
34
|
+
<input type="hidden" name="p" value="<%=@paginate.page%>" />
|
|
35
|
+
<input type="hidden" name="ex" value="<%=@exception%>" />
|
|
36
|
+
<select id="form_action" name="form_action">
|
|
37
|
+
<option id="default_option" value="" selected="selected">-- Select Action --</option>
|
|
38
|
+
<option value="clear">Clear</option>
|
|
39
|
+
<option value="retry_and_clear">Retry and Clear</option>
|
|
40
|
+
<option value="retry">Retry</option>
|
|
41
|
+
</select>
|
|
42
|
+
<a href="#" id="select_all">select all</a>
|
|
43
|
+
<a href="#" id="reset_all">reset</a>
|
|
44
|
+
|
|
45
|
+
<% if @paginate.max_page > 1 %>
|
|
46
|
+
<input type="checkbox" name="select_all_pages" value="1" id="select_all_pages" />Select all <%=@count%> jobs
|
|
47
|
+
<% end %>
|
|
48
|
+
<input type="hidden" name="sha1" id="sha1_list" />
|
|
49
|
+
|
|
50
|
+
<% end -%>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
<% end %>
|
|
54
|
+
|
|
55
|
+
<% start = 0 %>
|
|
56
|
+
<% failed = @paginate.paginated_jobs%>
|
|
57
|
+
<% index = 0 %>
|
|
58
|
+
<% date_format = "%Y/%m/%d %T %z" %>
|
|
59
|
+
|
|
60
|
+
<% if @paginate.max_page > 0 %>
|
|
61
|
+
<%= render :partial => 'paginate' %>
|
|
62
|
+
<ul class='failed'>
|
|
63
|
+
<%for job in failed%>
|
|
64
|
+
<% index += 1 %>
|
|
65
|
+
<li>
|
|
66
|
+
<dl>
|
|
67
|
+
<% if job.nil? %>
|
|
68
|
+
<dt>Error</dt>
|
|
69
|
+
<dd>Job <%= index%> could not be parsed; perhaps it contains invalid JSON?</dd>
|
|
70
|
+
<% else %>
|
|
71
|
+
<dt>
|
|
72
|
+
<input type="checkbox" id="<%=Digest::SHA1.hexdigest job.to_json %>" />
|
|
73
|
+
</dt>
|
|
74
|
+
<dd> </dd>
|
|
75
|
+
<dt>Worker</dt>
|
|
76
|
+
<dd>
|
|
77
|
+
<a href="<%= u(:workers, job['worker']) %>"><%= job['worker'].split(':')[0...2].join(':') %></a> on <b class='queue-tag'><%= job['queue'] %></b > at <b><span class="time"><%= Time.parse(job['failed_at']).strftime(date_format) %></span></b>
|
|
78
|
+
<% if job['retried_at'] %>
|
|
79
|
+
<div class='retried'>
|
|
80
|
+
Retried <b><span class="time"><%= Time.parse(job['retried_at']).strftime(date_format) %></span></b>
|
|
81
|
+
</div>
|
|
82
|
+
<% end %>
|
|
83
|
+
</dd>
|
|
84
|
+
<dt>Class</dt>
|
|
85
|
+
<dd><code><%= job['payload'] ? job['payload']['class'] : 'nil' %></code></dd>
|
|
86
|
+
<dt>Arguments</dt>
|
|
87
|
+
<dd><pre><%= job['payload'] ? show_args(job['payload']['args']).html_safe : 'nil' %></pre></dd>
|
|
88
|
+
<dt>Exception</dt>
|
|
89
|
+
<dd><code><%= job['exception'] %></code></dd>
|
|
90
|
+
<dt>Error</dt>
|
|
91
|
+
<dd class='error'>
|
|
92
|
+
<% if job['backtrace'].present? %>
|
|
93
|
+
<a href="#" class="backtrace"><%= h(job['error']) %></a>
|
|
94
|
+
<pre style='display:none'><%= job['backtrace'].join("\n").html_safe %></pre>
|
|
95
|
+
<% else %>
|
|
96
|
+
<%= job['error'].to_s.html_safe %>
|
|
97
|
+
<% end %>
|
|
98
|
+
</dd>
|
|
99
|
+
<% end %>
|
|
100
|
+
</dl>
|
|
101
|
+
<div class='r'>
|
|
102
|
+
</div>
|
|
103
|
+
</li>
|
|
104
|
+
<%end%>
|
|
105
|
+
</ul>
|
|
106
|
+
<%= render :partial => 'paginate' %>
|
|
107
|
+
<% else %>
|
|
108
|
+
Clean!
|
|
109
|
+
<% end %>
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
<script>
|
|
113
|
+
$(document).ready(function(){
|
|
114
|
+
$('#select_all_pages').click(function() {
|
|
115
|
+
updateCheckboxStaus();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
$('#select_all').click(function() {
|
|
119
|
+
if (!$(this).hasClass('disabled')) {
|
|
120
|
+
$('.failed input').attr('checked','checked');
|
|
121
|
+
}
|
|
122
|
+
return false;
|
|
123
|
+
});
|
|
124
|
+
$('#reset_all').click(function() {
|
|
125
|
+
if (!$(this).hasClass('disabled')) {
|
|
126
|
+
$('.failed input').removeAttr('checked');
|
|
127
|
+
}
|
|
128
|
+
return false;
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
$('#form_action').change( function() {
|
|
132
|
+
if ($('#form_action option:selected').val()=='') return;
|
|
133
|
+
|
|
134
|
+
if ($('#select_all_pages:checked, .failed input:checked').length==0) {
|
|
135
|
+
alert('Please select jobs.');
|
|
136
|
+
$('#default_option').attr('selected','selected');
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (!confirm('Do you really want to proceed?')) {
|
|
141
|
+
$('#default_option').attr('selected','selected');
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if ($('#select_all_pages:checked').length==0) {
|
|
146
|
+
setSha1();
|
|
147
|
+
}
|
|
148
|
+
$('#exec').submit();
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
function setSha1() {
|
|
153
|
+
var sha1 = "";
|
|
154
|
+
$('.failed input:checked').each( function() {
|
|
155
|
+
if (sha1.length>0) sha1 += ",";
|
|
156
|
+
sha1 += $(this).attr("id");
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
$('#sha1_list').val(sha1);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function updateCheckboxStaus() {
|
|
163
|
+
if ($('#select_all_pages:checked').length==1) {
|
|
164
|
+
$('#exec a').addClass('disabled');
|
|
165
|
+
$('.failed input').attr('disabled','disabled');
|
|
166
|
+
} else {
|
|
167
|
+
$('#exec a').removeClass('disabled');
|
|
168
|
+
$('.failed input').removeAttr('disabled');
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
</script>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<h1>Delayed Jobs</h1>
|
|
2
|
+
|
|
3
|
+
<p class='intro'>
|
|
4
|
+
This list below contains the timestamps for scheduled delayed jobs.
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p class='sub'>
|
|
8
|
+
Showing <%= start = params[:start].to_i %> to <%= start + 20 %> of <b><%=size = resque.delayed_queue_schedule_size %></b> timestamps
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
<table>
|
|
12
|
+
<tr>
|
|
13
|
+
<th>Timestamp</th>
|
|
14
|
+
<th>Job count</th>
|
|
15
|
+
<th>Class</th>
|
|
16
|
+
<th>Args</th>
|
|
17
|
+
</tr>
|
|
18
|
+
<% resque.delayed_queue_peek(start, start+20).each do |timestamp| %>
|
|
19
|
+
<tr>
|
|
20
|
+
<td><a href="<%= url "delayed/#{timestamp}" %>"><%= format_time(Time.at(timestamp)) %></a></td>
|
|
21
|
+
<td><%= delayed_timestamp_size = resque.delayed_timestamp_size(timestamp) %></td>
|
|
22
|
+
<% job = resque.delayed_timestamp_peek(timestamp, 0, 1).first %>
|
|
23
|
+
<td>
|
|
24
|
+
<% if job && delayed_timestamp_size == 1 %>
|
|
25
|
+
<%= h(job['class']) %>
|
|
26
|
+
<% else %>
|
|
27
|
+
<a href="<%= url "delayed/#{timestamp}" %>">see details</a>
|
|
28
|
+
<% end %>
|
|
29
|
+
</td>
|
|
30
|
+
<td><%= h(job['args'].inspect) if job && delayed_timestamp_size == 1 %></td>
|
|
31
|
+
</tr>
|
|
32
|
+
<% end %>
|
|
33
|
+
</table>
|
|
34
|
+
|
|
35
|
+
<%= render(:partial => 'next_more', :locals => {:start => start, :size => size}) %>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<% timestamp = params[:timestamp].to_i %>
|
|
2
|
+
|
|
3
|
+
<h1>Delayed jobs scheduled for <%= format_time(Time.at(timestamp)) %></h1>
|
|
4
|
+
|
|
5
|
+
<p class='sub'>Showing <%= start = params[:start].to_i %> to <%= start + 20 %> of <b><%=size = resque.delayed_timestamp_size(timestamp)%></b> jobs</p>
|
|
6
|
+
|
|
7
|
+
<table class='jobs'>
|
|
8
|
+
<tr>
|
|
9
|
+
<th>Class</th>
|
|
10
|
+
<th>Args</th>
|
|
11
|
+
</tr>
|
|
12
|
+
<% jobs = resque.delayed_timestamp_peek(timestamp, start, 20) %>
|
|
13
|
+
<% jobs.each do |job| %>
|
|
14
|
+
<tr>
|
|
15
|
+
<td class='class'><%= job['class'] %></td>
|
|
16
|
+
<td class='args'><%= job['args'].inspect.html_safe %></td>
|
|
17
|
+
</tr>
|
|
18
|
+
<% end %>
|
|
19
|
+
<% if jobs.empty? %>
|
|
20
|
+
<tr>
|
|
21
|
+
<td class='no-data' colspan='2'>There are no pending jobs scheduled for this time.</td>
|
|
22
|
+
</tr>
|
|
23
|
+
<% end %>
|
|
24
|
+
</table>
|
|
25
|
+
|
|
26
|
+
<%= partial :next_more, :start => start, :size => size %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<h1 style="font-size:110%;font-family:Arial, sans-serif;"><%= error %></h1>
|