resque_ui 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +6 -0
- data/Gemfile.lock +102 -0
- data/History.txt +5 -0
- data/MIT-LICENSE +21 -0
- data/README.markdown +279 -0
- data/Rakefile +49 -0
- data/VERSION.yml +5 -0
- data/app/assets/images/idle.png +0 -0
- data/app/assets/images/poll.png +0 -0
- data/app/assets/images/working.png +0 -0
- data/app/assets/javascripts/resque/jquery-1.3.2.min.js +19 -0
- data/app/assets/javascripts/resque/jquery.relatize_date.js +95 -0
- data/app/assets/javascripts/resque/ranger.js +24 -0
- data/app/assets/stylesheets/resque/resque.css +93 -0
- data/app/assets/stylesheets/resque/resque_reset.css +48 -0
- data/app/controllers/resque_controller.rb +236 -0
- data/app/helpers/resque_helper.rb +107 -0
- data/app/views/layouts/resque.html.erb +39 -0
- data/app/views/resque/_key.html.erb +17 -0
- data/app/views/resque/_next_more.html.erb +10 -0
- data/app/views/resque/_queues.html.erb +52 -0
- data/app/views/resque/_status_styles.erb +98 -0
- data/app/views/resque/_workers.html.erb +110 -0
- data/app/views/resque/_working.html.erb +69 -0
- data/app/views/resque/delayed.html.erb +35 -0
- data/app/views/resque/delayed_timestamp.html.erb +26 -0
- data/app/views/resque/error.erb +1 -0
- data/app/views/resque/failed.html.erb +54 -0
- data/app/views/resque/overview.html.erb +4 -0
- data/app/views/resque/schedule.html.erb +96 -0
- data/app/views/resque/stats.html.erb +62 -0
- data/app/views/resque/status.html.erb +57 -0
- data/app/views/resque/statuses.html.erb +72 -0
- data/app/views/resque/workers.html.erb +1 -0
- data/lib/resque_ui/cap.rb +6 -0
- data/lib/resque_ui/cap_recipes.rb +106 -0
- data/lib/resque_ui/overrides/resque/failure/failure.rb +22 -0
- data/lib/resque_ui/overrides/resque/job.rb +12 -0
- data/lib/resque_ui/overrides/resque/resque.rb +8 -0
- data/lib/resque_ui/overrides/resque/worker.rb +230 -0
- data/lib/resque_ui/overrides/resque_scheduler/resque_scheduler.rb +58 -0
- data/lib/resque_ui/overrides/resque_status/chained_job_with_status.rb +24 -0
- data/lib/resque_ui/overrides/resque_status/job_with_status.rb +59 -0
- data/lib/resque_ui/overrides/resque_status/status.rb +53 -0
- data/lib/resque_ui.rb +26 -0
- data/lib/tasks/failure.rake +8 -0
- data/lib/tasks/scheduler.rake +11 -0
- data/lib/tasks/worker.rake +80 -0
- data/rdoc/Resque/ChainedJobWithStatus.html +284 -0
- data/rdoc/Resque/Failure/Base.html +229 -0
- data/rdoc/Resque/Failure.html +202 -0
- data/rdoc/Resque/Job.html +202 -0
- data/rdoc/Resque/JobWithStatus.html +410 -0
- data/rdoc/Resque/Status.html +368 -0
- data/rdoc/Resque/Worker.html +1104 -0
- data/rdoc/Resque.html +232 -0
- data/rdoc/ResqueScheduler.html +434 -0
- data/rdoc/ResqueUi/Cap.html +150 -0
- data/rdoc/ResqueUi/Engine.html +150 -0
- data/rdoc/ResqueUi.html +157 -0
- data/rdoc/created.rid +13 -0
- data/rdoc/images/brick.png +0 -0
- data/rdoc/images/brick_link.png +0 -0
- data/rdoc/images/bug.png +0 -0
- data/rdoc/images/bullet_black.png +0 -0
- data/rdoc/images/bullet_toggle_minus.png +0 -0
- data/rdoc/images/bullet_toggle_plus.png +0 -0
- data/rdoc/images/date.png +0 -0
- data/rdoc/images/find.png +0 -0
- data/rdoc/images/loadingAnimation.gif +0 -0
- data/rdoc/images/macFFBgHack.png +0 -0
- data/rdoc/images/package.png +0 -0
- data/rdoc/images/page_green.png +0 -0
- data/rdoc/images/page_white_text.png +0 -0
- data/rdoc/images/page_white_width.png +0 -0
- data/rdoc/images/plugin.png +0 -0
- data/rdoc/images/ruby.png +0 -0
- data/rdoc/images/tag_green.png +0 -0
- data/rdoc/images/wrench.png +0 -0
- data/rdoc/images/wrench_orange.png +0 -0
- data/rdoc/images/zoom.png +0 -0
- data/rdoc/index.html +163 -0
- data/rdoc/js/darkfish.js +116 -0
- data/rdoc/js/jquery.js +32 -0
- data/rdoc/js/quicksearch.js +114 -0
- data/rdoc/js/thickbox-compressed.js +10 -0
- data/rdoc/lib/resque_overrides_rb.html +54 -0
- data/rdoc/lib/resque_scheduler_overrides_rb.html +52 -0
- data/rdoc/lib/resque_status_overrides_rb.html +52 -0
- data/rdoc/lib/resque_ui/cap_rb.html +52 -0
- data/rdoc/lib/resque_ui/cap_recipes_rb.html +58 -0
- data/rdoc/lib/resque_ui/engine_rb.html +52 -0
- data/rdoc/lib/resque_ui/overrides/resque/failure/failure_rb.html +54 -0
- data/rdoc/lib/resque_ui/overrides/resque/job_rb.html +52 -0
- data/rdoc/lib/resque_ui/overrides/resque/resque_rb.html +52 -0
- data/rdoc/lib/resque_ui/overrides/resque/worker_rb.html +54 -0
- data/rdoc/lib/resque_ui/overrides/resque_scheduler/resque_scheduler_rb.html +52 -0
- data/rdoc/lib/resque_ui/overrides/resque_status/chained_job_with_status_rb.html +52 -0
- data/rdoc/lib/resque_ui/overrides/resque_status/job_with_status_rb.html +52 -0
- data/rdoc/lib/resque_ui/overrides/resque_status/status_rb.html +52 -0
- data/rdoc/lib/resque_ui/resque_ui_rb.html +52 -0
- data/rdoc/lib/resque_ui/tasks_rb.html +64 -0
- data/rdoc/lib/resque_ui_rb.html +76 -0
- data/rdoc/rdoc.css +763 -0
- data/resque_ui.gemspec +153 -0
- data/test/resque_ui_test.rb +8 -0
- data/test/test_helper.rb +3 -0
- metadata +205 -0
@@ -0,0 +1,52 @@
|
|
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 <b><%=size = resque.size(queue)%></b> jobs</p>
|
9
|
+
<table class='jobs'>
|
10
|
+
<tr>
|
11
|
+
<th>Class</th>
|
12
|
+
<th>Args</th>
|
13
|
+
<th> </th>
|
14
|
+
</tr>
|
15
|
+
<% for job in (jobs = resque.peek(queue, start, 20)) %>
|
16
|
+
<tr>
|
17
|
+
<td class='class'><%= job['class'] %></td>
|
18
|
+
<td class='args'><%=h job['args'].inspect %></td>
|
19
|
+
<td>
|
20
|
+
<%= button_to "Remove", {:controller=>'resque', :action=> 'remove_job',:class => job['class'], :args => Resque.encode(job['args'])}, :class => 'clear-failed', :method => :post %>
|
21
|
+
</td>
|
22
|
+
</tr>
|
23
|
+
<% end %>
|
24
|
+
<% if jobs.empty? %>
|
25
|
+
<tr>
|
26
|
+
<td class='no-data' colspan='3'>There are no pending jobs in this queue</td>
|
27
|
+
</tr>
|
28
|
+
<% end %>
|
29
|
+
</table>
|
30
|
+
<%= render(:partial => 'next_more', :locals => {:start => start, :size => size}) %>
|
31
|
+
<% else %>
|
32
|
+
|
33
|
+
<h1 class='wi'>Queues</h1>
|
34
|
+
<p class='intro'>The list below contains all the registered queues with the number of jobs currently in the queue. Select a queue from above to view all jobs currently pending on the queue.</p>
|
35
|
+
<table class='queues'>
|
36
|
+
<tr>
|
37
|
+
<th>Name</th>
|
38
|
+
<th>Jobs</th>
|
39
|
+
</tr>
|
40
|
+
<% for queue in resque.queues.sort_by { |q| q.to_s } %>
|
41
|
+
<tr>
|
42
|
+
<td class='queue'><%= link_to(queue, {:action => "queues", :id => queue}, :class => 'queue') %></td>
|
43
|
+
<td class='size'><%= resque.size queue %></td>
|
44
|
+
</tr>
|
45
|
+
<% end %>
|
46
|
+
<tr class='failed'>
|
47
|
+
<td class='queue failed'><%= link_to('failed', {:action => "failed"}, :class => 'queue') %></td>
|
48
|
+
<td class='size'><%= Resque::Failure.count %></td>
|
49
|
+
</tr>
|
50
|
+
</table>
|
51
|
+
|
52
|
+
<% 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,110 @@
|
|
1
|
+
|
2
|
+
<% if params[:id] && worker = find_worker(params[:id]) %>
|
3
|
+
|
4
|
+
<h1>Worker <%= worker %></h1>
|
5
|
+
<table class='workers'>
|
6
|
+
<tr>
|
7
|
+
<th> </th>
|
8
|
+
<th>Host</th>
|
9
|
+
<th>Pid</th>
|
10
|
+
<th>Thread</th>
|
11
|
+
<th>Started</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'><img src="<%=u "../../images/resque/#{state = worker.state}" %>.png" alt="<%= state %>" title="<%= state %>"></td>
|
19
|
+
|
20
|
+
<% host, pid, thread, queues = worker.to_s.split(':') %>
|
21
|
+
<td><%= host %></td>
|
22
|
+
<td><%= pid %></td>
|
23
|
+
<td><%= thread %></td>
|
24
|
+
<td><span class="time"><%= format_time(Time.zone.parse(worker.started)) %></span></td>
|
25
|
+
<td class='queues'><%= queues.split(',').map { |q| link_to(q, {:action => 'queues', :id => q}, :class => 'queue-tag')}.join('').html_safe %></td>
|
26
|
+
<td><%= worker.processed %></td>
|
27
|
+
<td><%= worker.failed %></td>
|
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>
|
35
|
+
<% else %>
|
36
|
+
<span class='waiting'>Waiting for a job...</span>
|
37
|
+
<% end %>
|
38
|
+
</td>
|
39
|
+
</tr>
|
40
|
+
</table>
|
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
|
+
|
67
|
+
<td class='process'>
|
68
|
+
<% data = worker.processing || {} %>
|
69
|
+
<% if data['queue'] %>
|
70
|
+
<code><%= data['payload']['class'] %></code>
|
71
|
+
<small><%= link_to(format_time(Time.zone.parse(data['run_at'])), {:action => 'working', :id => worker.to_s.gsub(/\./,'_')}, :class => "queue time") %></small>
|
72
|
+
<br/>
|
73
|
+
<small><%=worker.status%></small>
|
74
|
+
<% else %>
|
75
|
+
<span class='waiting'>Waiting for a job...</span>
|
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 %>
|
83
|
+
<% end %>
|
84
|
+
</td>
|
85
|
+
</tr>
|
86
|
+
<% end %>
|
87
|
+
<% if workers.empty? %>
|
88
|
+
<tr>
|
89
|
+
<td colspan='5' class='no-data'>There are no registered workers</td>
|
90
|
+
</tr>
|
91
|
+
<% end %>
|
92
|
+
</table>
|
93
|
+
<%=poll%>
|
94
|
+
<br/>
|
95
|
+
<hr />
|
96
|
+
<h1 class='wi'>Start New Workers</h1>
|
97
|
+
<%= form_tag :action => 'start_worker' do -%>
|
98
|
+
<ul class='new_worker'>
|
99
|
+
<li>
|
100
|
+
<dl>
|
101
|
+
<dt>Queue(s)</dt>
|
102
|
+
<dd><%=text_field_tag :queues, nil, :size => 125 %><br/> Prefix each worker with a '#', comma separate the list of queues you want each worker to monitor. No Spaces. #queue1,queue2#queue3#queue2 will produce 3 workers in 3 threads.</dd>
|
103
|
+
<dt>Host(s)/IP(s)</dt>
|
104
|
+
<dd><%=text_field_tag :hosts, nil, :size => 125 %><br/> Comma separate the IP address of the servers where you want your worker to run.</dd>
|
105
|
+
<dt><%= submit_tag "Start", :id => "submit" %></dt>
|
106
|
+
</dl>
|
107
|
+
</li>
|
108
|
+
</ul>
|
109
|
+
<%end-%>
|
110
|
+
<% 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</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="<%=u '../../images/resque/working.png' %>" alt="working" title="working"></td>
|
15
|
+
<% host, pid,thread, _ = worker.to_s.split(':') %>
|
16
|
+
<td><%= link_to("#{host}:#{pid}:#{thread}", {: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><%=h data['payload']['args'].inspect %></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</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="<%=u "../../images/resque/#{state = worker.state}" %>.png" alt="<%= state %>" title="<%= state %>"></td>
|
50
|
+
<% host, pid, thread, queues = worker.to_s.split(':') %>
|
51
|
+
<td class='where'><%= link_to("#{host}:#{pid}:#{thread}", {: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.status%></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,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'><%=h job['args'].inspect %></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>
|
@@ -0,0 +1,54 @@
|
|
1
|
+
<%start = params[:start].to_i %>
|
2
|
+
<%failed = Resque::Failure.all(start, 20)%>
|
3
|
+
|
4
|
+
<h1>Failed Jobs</h1>
|
5
|
+
<%unless failed.empty?%>
|
6
|
+
<form method="POST" action="clear_failures" class='clear-failed'>
|
7
|
+
<input type='submit' name='' value='Clear Failed Jobs' />
|
8
|
+
</form>
|
9
|
+
<%end%>
|
10
|
+
|
11
|
+
<% if classes_in_failure.present? -%>
|
12
|
+
<br/>
|
13
|
+
<table style="border:1px solid #CCCCCC">
|
14
|
+
<tr>
|
15
|
+
<h2>Restart all failed jobs in class:</h2>
|
16
|
+
<% classes_in_failure.each do |c| -%>
|
17
|
+
<td style="<%="width:#{100/classes_in_failure.size}%; border:none"%>"><%= button_to c, {:controller=>'resque', :action=> 'requeue_failures_in_class', :class => c}, :method => :post %></td>
|
18
|
+
<% end -%>
|
19
|
+
</tr>
|
20
|
+
</table>
|
21
|
+
<% end -%>
|
22
|
+
|
23
|
+
<p class='sub'>Showing <%=start%> to <%= start + 20 %> of <b><%= size = Resque::Failure.count %></b> jobs</p>
|
24
|
+
|
25
|
+
<ul class='failed'>
|
26
|
+
<%for job in failed%>
|
27
|
+
<li>
|
28
|
+
<dl>
|
29
|
+
<dt>Worker</dt>
|
30
|
+
<dd><%= link_to(job['worker'].split(':')[0...3].join(':'), :action => 'workers',:id => job['worker'].gsub(/\./,'_')) %> on <b class='queue-tag'><%= job['queue'] %></b > at <b><span class="time"><%= format_time(Time.zone.parse(job['failed_at'])) %></span></b></dd>
|
31
|
+
<dt>Class</dt>
|
32
|
+
<dd><code><%= job['payload']['class'] %></code></dd>
|
33
|
+
<dt>Arguments</dt>
|
34
|
+
<dd><pre><%=h show_args(job['payload']['args']) %></pre></dd>
|
35
|
+
<dt>Error</dt>
|
36
|
+
<dd class='error'>
|
37
|
+
<a href="#" class="backtrace"><%= h(job['error']) %></a>
|
38
|
+
<pre style='display:none'><%=h job['backtrace'].join("\n") %></pre>
|
39
|
+
</dd>
|
40
|
+
<dt>
|
41
|
+
<%= button_to "Restart Job", {:controller=>'resque', :action=> 'requeue_failure', :payload => job['payload'].to_json}, :method => :post %>
|
42
|
+
</dt>
|
43
|
+
<dt></dt>
|
44
|
+
<dd>
|
45
|
+
<%= button_to "Clear Job", {:controller=>'resque', :action=> 'clear_failure', :payload => job['payload'].to_json}, :method => :post %>
|
46
|
+
</dd>
|
47
|
+
</dl>
|
48
|
+
<div class='r'>
|
49
|
+
</div>
|
50
|
+
</li>
|
51
|
+
<%end%>
|
52
|
+
</ul>
|
53
|
+
|
54
|
+
<%= render(:partial => 'next_more', :locals => {:start => start, :size => size}) %>
|
@@ -0,0 +1,96 @@
|
|
1
|
+
|
2
|
+
<div id="schedule">
|
3
|
+
<h1>Schedule</h1>
|
4
|
+
|
5
|
+
<p class='intro'>
|
6
|
+
The list below contains all scheduled jobs. Click "Queue now" to queue
|
7
|
+
a job immediately.
|
8
|
+
</p>
|
9
|
+
|
10
|
+
<table>
|
11
|
+
<tr>
|
12
|
+
<th></th>
|
13
|
+
<th>Name</th>
|
14
|
+
<th>IP</th>
|
15
|
+
<th>Description</th>
|
16
|
+
<th>Cron</th>
|
17
|
+
<th>Class</th>
|
18
|
+
<th>Arguments</th>
|
19
|
+
<th></th>
|
20
|
+
</tr>
|
21
|
+
<% Resque.schedule.each do |name,config| %>
|
22
|
+
<tr>
|
23
|
+
<td>
|
24
|
+
<%= button_to "Queue now", {:controller=>'resque', :action=> 'schedule_requeue', :job_name => name}, :method => :post %>
|
25
|
+
</td>
|
26
|
+
<td><%= h name %></td>
|
27
|
+
<td><%= h config['ip'] %></td>
|
28
|
+
<td><%= h config['description'] %></td>
|
29
|
+
<td style="white-space:nowrap"><%= h config['cron'] %></td>
|
30
|
+
<td><%= h config['class'] %></td>
|
31
|
+
<td><%= h config['args'].inspect %></td>
|
32
|
+
<td><%= button_to "Remove", {:controller=>'resque', :action=> 'remove_from_schedule', :job_name => name, :ip => config['ip']}, :method => :post %></td>
|
33
|
+
</tr>
|
34
|
+
<%end%>
|
35
|
+
</table>
|
36
|
+
|
37
|
+
<h1>Add Job to Schedule</h1>
|
38
|
+
<div id='flash' class="flash">
|
39
|
+
<%flash_message = flash_helper%>
|
40
|
+
<% unless flash_message.blank? -%>
|
41
|
+
<p>
|
42
|
+
<%= flash_message %>
|
43
|
+
</p>
|
44
|
+
<%= javascript_tag "$('flash').show();" %>
|
45
|
+
<% end %>
|
46
|
+
</div>
|
47
|
+
<%= form_tag '/resque/add_scheduled_job' do -%>
|
48
|
+
<table>
|
49
|
+
<tr>
|
50
|
+
<th>Name</th>
|
51
|
+
<th>IP</th>
|
52
|
+
<th>Description</th>
|
53
|
+
<th>Cron</th>
|
54
|
+
<th>Class</th>
|
55
|
+
<th>Arguments</th>
|
56
|
+
<th></th>
|
57
|
+
</tr>
|
58
|
+
<tr>
|
59
|
+
<td><%= text_field_tag :name %></td>
|
60
|
+
<td><%= text_field_tag :ip %></td>
|
61
|
+
<td><%= text_field_tag :description %></td>
|
62
|
+
<td style="white-space:nowrap"><%= text_field_tag :cron %></td>
|
63
|
+
<td><%= text_field_tag :class %></td>
|
64
|
+
<td><%= text_area_tag :args, nil, :rows => 1, :cols => 40%></td>
|
65
|
+
<td>
|
66
|
+
<%= submit_tag 'Add Job', :id => 'add_job' %>
|
67
|
+
</td>
|
68
|
+
</tr>
|
69
|
+
</table>
|
70
|
+
<% end -%>
|
71
|
+
|
72
|
+
<h1>Farm Status</h1>
|
73
|
+
|
74
|
+
<table>
|
75
|
+
<tr>
|
76
|
+
<th>IP</th>
|
77
|
+
<th>Status</th>
|
78
|
+
<th></th>
|
79
|
+
</tr>
|
80
|
+
<%@farm_status.each do |ip,status| -%>
|
81
|
+
<tr>
|
82
|
+
<td>
|
83
|
+
<%= ip %>
|
84
|
+
</td>
|
85
|
+
<td><%= status %></td>
|
86
|
+
<td>
|
87
|
+
<% if status == 'Running' -%>
|
88
|
+
<%= button_to "Stop Scheduler", {:controller=>'resque', :action=> 'stop_scheduler', :ip => ip}, :method => :post %>
|
89
|
+
<% else -%>
|
90
|
+
<%= button_to "Start Scheduler", {:controller=>'resque', :action=> 'start_scheduler', :ip => ip}, :method => :post %>
|
91
|
+
<% end -%>
|
92
|
+
</td>
|
93
|
+
</tr>
|
94
|
+
<% end -%>
|
95
|
+
</table>
|
96
|
+
</div>
|
@@ -0,0 +1,62 @@
|
|
1
|
+
<% @subtabs = %w( resque redis keys ) %>
|
2
|
+
|
3
|
+
<% if params[:key] %>
|
4
|
+
|
5
|
+
<%= render(:partial => 'key') %>
|
6
|
+
|
7
|
+
<% elsif params[:id] == "resque" %>
|
8
|
+
|
9
|
+
<h1><%= resque %></h1>
|
10
|
+
<table class='stats'>
|
11
|
+
<% for key, value in resque.info.to_a.sort_by { |i| i[0].to_s } %>
|
12
|
+
<tr>
|
13
|
+
<th>
|
14
|
+
<%= key %>
|
15
|
+
</th>
|
16
|
+
<td>
|
17
|
+
<%= value %>
|
18
|
+
</td>
|
19
|
+
</tr>
|
20
|
+
<% end %>
|
21
|
+
</table>
|
22
|
+
|
23
|
+
<% elsif params[:id] == 'redis' %>
|
24
|
+
|
25
|
+
<h1><%= resque.redis_id %></h1>
|
26
|
+
<table class='stats'>
|
27
|
+
<% for key, value in resque.redis.info.to_a.sort_by { |i| i[0].to_s } %>
|
28
|
+
<tr>
|
29
|
+
<th>
|
30
|
+
<%= key %>
|
31
|
+
</th>
|
32
|
+
<td>
|
33
|
+
<%= value %>
|
34
|
+
</td>
|
35
|
+
</tr>
|
36
|
+
<% end %>
|
37
|
+
</table>
|
38
|
+
|
39
|
+
<% elsif params[:id] == 'keys' %>
|
40
|
+
|
41
|
+
<h1>Keys owned by <%= resque %></h1>
|
42
|
+
<p class='sub'>(All keys are actually prefixed with "resque:")</p>
|
43
|
+
<table class='stats'>
|
44
|
+
<tr>
|
45
|
+
<th>key</th>
|
46
|
+
<th>type</th>
|
47
|
+
<th>size</th>
|
48
|
+
</tr>
|
49
|
+
<% for key in resque.keys.sort %>
|
50
|
+
<tr>
|
51
|
+
<th>
|
52
|
+
<%= link_to(key, "/resque/stats/keys?key=#{key}") %>
|
53
|
+
</th>
|
54
|
+
<td><%= resque.redis.type key %></td>
|
55
|
+
<td><%= redis_get_size key %></td>
|
56
|
+
</tr>
|
57
|
+
<% end %>
|
58
|
+
</table>
|
59
|
+
|
60
|
+
<% else %>
|
61
|
+
|
62
|
+
<% end %>
|
@@ -0,0 +1,57 @@
|
|
1
|
+
<%= render(:partial => 'status_styles') %>
|
2
|
+
|
3
|
+
<h1 class='wi'>Statuses: <%= @status.uuid %>/<%= @status.name %></h1>
|
4
|
+
<p class='intro'>Viewing a specific job created with JobWithStatus. <%= link_to('Return to the list of statuses', :action => "statuses") %></p>
|
5
|
+
|
6
|
+
<div class="status-holder" rel="<%= @status.status %>" id="status_<%= @status.uuid %>">
|
7
|
+
<div class="status-progress">
|
8
|
+
<div class="status-progress-bar status-<%= @status.status %>" style="width: <%= @status.pct_complete %>%;"></div>
|
9
|
+
<p><%= @status.pct_complete %>%</p>
|
10
|
+
</div>
|
11
|
+
<div class="status-message"><%= @status.message %></div>
|
12
|
+
<div class="status-time"><%= @status.time? ? format_time(Time.zone.parse(@status.time.to_s)) : 'Not started' %></div>
|
13
|
+
</div>
|
14
|
+
|
15
|
+
<script type="text/javascript" charset="utf-8">
|
16
|
+
jQuery(function($) {
|
17
|
+
|
18
|
+
// itterate over the holders
|
19
|
+
$('.status-holder').each(function() {
|
20
|
+
checkStatus($(this));
|
21
|
+
});
|
22
|
+
|
23
|
+
function checkStatus($status) {
|
24
|
+
var status_id = $status.attr('id').replace('status_', '');
|
25
|
+
$.getJSON('<%= url(:statuses) %>/' + status_id + '.js', function(json) {
|
26
|
+
if (json) {
|
27
|
+
var pct = "0%";
|
28
|
+
if (json.pct_complete) {
|
29
|
+
var pct = json.pct_complete + "%";
|
30
|
+
}
|
31
|
+
$status.find('.status-progress-bar').animate({width: pct});
|
32
|
+
$status.find('.status-progress p').text(pct)
|
33
|
+
if (json.message) {
|
34
|
+
$status.find('.status-message').html(json.message)
|
35
|
+
}
|
36
|
+
if (json.status) {
|
37
|
+
$status
|
38
|
+
.attr('rel', json.status)
|
39
|
+
.find('.status-progress-bar')
|
40
|
+
.attr('class', '')
|
41
|
+
.addClass('status-progress-bar status-' + json.status);
|
42
|
+
}
|
43
|
+
if (json.time) {
|
44
|
+
$status.find('.status-time').text(new Date(json.time * 1000).toString())
|
45
|
+
}
|
46
|
+
};
|
47
|
+
var status = $status.attr('rel');
|
48
|
+
if (status == 'working' || status == 'queued' || status == "") {
|
49
|
+
setTimeout(function() {
|
50
|
+
checkStatus($status)
|
51
|
+
}, 1500);
|
52
|
+
}
|
53
|
+
});
|
54
|
+
};
|
55
|
+
|
56
|
+
});
|
57
|
+
</script>
|