resque_ui 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. data/Gemfile +6 -0
  2. data/Gemfile.lock +102 -0
  3. data/History.txt +5 -0
  4. data/MIT-LICENSE +21 -0
  5. data/README.markdown +279 -0
  6. data/Rakefile +49 -0
  7. data/VERSION.yml +5 -0
  8. data/app/assets/images/idle.png +0 -0
  9. data/app/assets/images/poll.png +0 -0
  10. data/app/assets/images/working.png +0 -0
  11. data/app/assets/javascripts/resque/jquery-1.3.2.min.js +19 -0
  12. data/app/assets/javascripts/resque/jquery.relatize_date.js +95 -0
  13. data/app/assets/javascripts/resque/ranger.js +24 -0
  14. data/app/assets/stylesheets/resque/resque.css +93 -0
  15. data/app/assets/stylesheets/resque/resque_reset.css +48 -0
  16. data/app/controllers/resque_controller.rb +236 -0
  17. data/app/helpers/resque_helper.rb +107 -0
  18. data/app/views/layouts/resque.html.erb +39 -0
  19. data/app/views/resque/_key.html.erb +17 -0
  20. data/app/views/resque/_next_more.html.erb +10 -0
  21. data/app/views/resque/_queues.html.erb +52 -0
  22. data/app/views/resque/_status_styles.erb +98 -0
  23. data/app/views/resque/_workers.html.erb +110 -0
  24. data/app/views/resque/_working.html.erb +69 -0
  25. data/app/views/resque/delayed.html.erb +35 -0
  26. data/app/views/resque/delayed_timestamp.html.erb +26 -0
  27. data/app/views/resque/error.erb +1 -0
  28. data/app/views/resque/failed.html.erb +54 -0
  29. data/app/views/resque/overview.html.erb +4 -0
  30. data/app/views/resque/schedule.html.erb +96 -0
  31. data/app/views/resque/stats.html.erb +62 -0
  32. data/app/views/resque/status.html.erb +57 -0
  33. data/app/views/resque/statuses.html.erb +72 -0
  34. data/app/views/resque/workers.html.erb +1 -0
  35. data/lib/resque_ui/cap.rb +6 -0
  36. data/lib/resque_ui/cap_recipes.rb +106 -0
  37. data/lib/resque_ui/overrides/resque/failure/failure.rb +22 -0
  38. data/lib/resque_ui/overrides/resque/job.rb +12 -0
  39. data/lib/resque_ui/overrides/resque/resque.rb +8 -0
  40. data/lib/resque_ui/overrides/resque/worker.rb +230 -0
  41. data/lib/resque_ui/overrides/resque_scheduler/resque_scheduler.rb +58 -0
  42. data/lib/resque_ui/overrides/resque_status/chained_job_with_status.rb +24 -0
  43. data/lib/resque_ui/overrides/resque_status/job_with_status.rb +59 -0
  44. data/lib/resque_ui/overrides/resque_status/status.rb +53 -0
  45. data/lib/resque_ui.rb +26 -0
  46. data/lib/tasks/failure.rake +8 -0
  47. data/lib/tasks/scheduler.rake +11 -0
  48. data/lib/tasks/worker.rake +80 -0
  49. data/rdoc/Resque/ChainedJobWithStatus.html +284 -0
  50. data/rdoc/Resque/Failure/Base.html +229 -0
  51. data/rdoc/Resque/Failure.html +202 -0
  52. data/rdoc/Resque/Job.html +202 -0
  53. data/rdoc/Resque/JobWithStatus.html +410 -0
  54. data/rdoc/Resque/Status.html +368 -0
  55. data/rdoc/Resque/Worker.html +1104 -0
  56. data/rdoc/Resque.html +232 -0
  57. data/rdoc/ResqueScheduler.html +434 -0
  58. data/rdoc/ResqueUi/Cap.html +150 -0
  59. data/rdoc/ResqueUi/Engine.html +150 -0
  60. data/rdoc/ResqueUi.html +157 -0
  61. data/rdoc/created.rid +13 -0
  62. data/rdoc/images/brick.png +0 -0
  63. data/rdoc/images/brick_link.png +0 -0
  64. data/rdoc/images/bug.png +0 -0
  65. data/rdoc/images/bullet_black.png +0 -0
  66. data/rdoc/images/bullet_toggle_minus.png +0 -0
  67. data/rdoc/images/bullet_toggle_plus.png +0 -0
  68. data/rdoc/images/date.png +0 -0
  69. data/rdoc/images/find.png +0 -0
  70. data/rdoc/images/loadingAnimation.gif +0 -0
  71. data/rdoc/images/macFFBgHack.png +0 -0
  72. data/rdoc/images/package.png +0 -0
  73. data/rdoc/images/page_green.png +0 -0
  74. data/rdoc/images/page_white_text.png +0 -0
  75. data/rdoc/images/page_white_width.png +0 -0
  76. data/rdoc/images/plugin.png +0 -0
  77. data/rdoc/images/ruby.png +0 -0
  78. data/rdoc/images/tag_green.png +0 -0
  79. data/rdoc/images/wrench.png +0 -0
  80. data/rdoc/images/wrench_orange.png +0 -0
  81. data/rdoc/images/zoom.png +0 -0
  82. data/rdoc/index.html +163 -0
  83. data/rdoc/js/darkfish.js +116 -0
  84. data/rdoc/js/jquery.js +32 -0
  85. data/rdoc/js/quicksearch.js +114 -0
  86. data/rdoc/js/thickbox-compressed.js +10 -0
  87. data/rdoc/lib/resque_overrides_rb.html +54 -0
  88. data/rdoc/lib/resque_scheduler_overrides_rb.html +52 -0
  89. data/rdoc/lib/resque_status_overrides_rb.html +52 -0
  90. data/rdoc/lib/resque_ui/cap_rb.html +52 -0
  91. data/rdoc/lib/resque_ui/cap_recipes_rb.html +58 -0
  92. data/rdoc/lib/resque_ui/engine_rb.html +52 -0
  93. data/rdoc/lib/resque_ui/overrides/resque/failure/failure_rb.html +54 -0
  94. data/rdoc/lib/resque_ui/overrides/resque/job_rb.html +52 -0
  95. data/rdoc/lib/resque_ui/overrides/resque/resque_rb.html +52 -0
  96. data/rdoc/lib/resque_ui/overrides/resque/worker_rb.html +54 -0
  97. data/rdoc/lib/resque_ui/overrides/resque_scheduler/resque_scheduler_rb.html +52 -0
  98. data/rdoc/lib/resque_ui/overrides/resque_status/chained_job_with_status_rb.html +52 -0
  99. data/rdoc/lib/resque_ui/overrides/resque_status/job_with_status_rb.html +52 -0
  100. data/rdoc/lib/resque_ui/overrides/resque_status/status_rb.html +52 -0
  101. data/rdoc/lib/resque_ui/resque_ui_rb.html +52 -0
  102. data/rdoc/lib/resque_ui/tasks_rb.html +64 -0
  103. data/rdoc/lib/resque_ui_rb.html +76 -0
  104. data/rdoc/rdoc.css +763 -0
  105. data/resque_ui.gemspec +153 -0
  106. data/test/resque_ui_test.rb +8 -0
  107. data/test/test_helper.rb +3 -0
  108. 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>&nbsp;</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>&nbsp;</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>&nbsp;</th>
53
+ <th>Where (ip):pid:thread</th>
54
+ <th>Queues</th>
55
+ <th>Processing</th>
56
+ <th>&nbsp;</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>&nbsp;</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>&nbsp;</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,4 @@
1
+ <%= render(:partial => 'queues', :locals => {:partial => true}) %>
2
+ <hr />
3
+ <%= render(:partial => 'working') %>
4
+ <%= poll %>
@@ -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 &quot;Queue now&quot; 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>