jerefrer-resque 1.1.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/.kick +26 -0
- data/HISTORY.md +10 -0
- data/LICENSE +20 -0
- data/README.markdown +703 -0
- data/Rakefile +61 -0
- data/bin/resque +69 -0
- data/bin/resque-web +47 -0
- data/config.ru +8 -0
- data/deps.rip +5 -0
- data/examples/async_helper.rb +31 -0
- data/examples/demo/README.markdown +71 -0
- data/examples/demo/Rakefile +3 -0
- data/examples/demo/app.rb +27 -0
- data/examples/demo/config.ru +19 -0
- data/examples/demo/job.rb +12 -0
- data/examples/god/resque.god +52 -0
- data/examples/god/stale.god +26 -0
- data/examples/instance.rb +11 -0
- data/examples/simple.rb +30 -0
- data/init.rb +1 -0
- data/lib/resque/errors.rb +7 -0
- data/lib/resque/failure/base.rb +58 -0
- data/lib/resque/failure/hoptoad.rb +88 -0
- data/lib/resque/failure/redis.rb +33 -0
- data/lib/resque/failure.rb +63 -0
- data/lib/resque/helpers.rb +57 -0
- data/lib/resque/job.rb +91 -0
- data/lib/resque/server/public/idle.png +0 -0
- data/lib/resque/server/public/jquery-1.3.2.min.js +19 -0
- data/lib/resque/server/public/jquery.relatize_date.js +95 -0
- data/lib/resque/server/public/poll.png +0 -0
- data/lib/resque/server/public/ranger.js +21 -0
- data/lib/resque/server/public/reset.css +48 -0
- data/lib/resque/server/public/style.css +75 -0
- data/lib/resque/server/public/working.png +0 -0
- data/lib/resque/server/views/error.erb +1 -0
- data/lib/resque/server/views/failed.erb +35 -0
- data/lib/resque/server/views/key.erb +17 -0
- data/lib/resque/server/views/layout.erb +41 -0
- data/lib/resque/server/views/next_more.erb +10 -0
- data/lib/resque/server/views/overview.erb +4 -0
- data/lib/resque/server/views/queues.erb +46 -0
- data/lib/resque/server/views/stats.erb +62 -0
- data/lib/resque/server/views/workers.erb +78 -0
- data/lib/resque/server/views/working.erb +67 -0
- data/lib/resque/server.rb +174 -0
- data/lib/resque/stat.rb +53 -0
- data/lib/resque/tasks.rb +24 -0
- data/lib/resque/version.rb +3 -0
- data/lib/resque/worker.rb +406 -0
- data/lib/resque.rb +184 -0
- data/tasks/redis.rake +125 -0
- data/tasks/resque.rake +2 -0
- data/test/redis-test.conf +132 -0
- data/test/resque_test.rb +160 -0
- data/test/test_helper.rb +90 -0
- data/test/worker_test.rb +220 -0
- metadata +121 -0
@@ -0,0 +1,35 @@
|
|
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="<%=u 'failed/clear'%>" class='clear-failed'>
|
7
|
+
<input type='submit' name='' value='Clear Failed Jobs' />
|
8
|
+
</form>
|
9
|
+
<%end%>
|
10
|
+
|
11
|
+
<p class='sub'>Showing <%=start%> to <%= start + 20 %> of <b><%= size = Resque::Failure.count %></b> jobs</p>
|
12
|
+
|
13
|
+
<ul class='failed'>
|
14
|
+
<%for job in failed%>
|
15
|
+
<li>
|
16
|
+
<dl>
|
17
|
+
<dt>Worker</dt>
|
18
|
+
<dd><a href="<%= url(:workers, job['worker']) %>"><%= job['worker'].split(':')[0...2].join(':') %></a> on <b class='queue-tag'><%= job['queue'] %></b > at <b><span class="time"><%= job['failed_at'] %></span></b></dd>
|
19
|
+
<dt>Class</dt>
|
20
|
+
<dd><code><%= job['payload']['class'] %></code></dd>
|
21
|
+
<dt>Arguments</dt>
|
22
|
+
<dd><pre><%=h show_args(job['payload']['args']) %></pre></dd>
|
23
|
+
<dt>Error</dt>
|
24
|
+
<dd class='error'>
|
25
|
+
<a href="#" class="backtrace"><%= h(job['error']) %></a>
|
26
|
+
<pre style='display:none'><%=h job['backtrace'].join("\n") %></pre>
|
27
|
+
</dd>
|
28
|
+
</dl>
|
29
|
+
<div class='r'>
|
30
|
+
</div>
|
31
|
+
</li>
|
32
|
+
<%end%>
|
33
|
+
</ul>
|
34
|
+
|
35
|
+
<%= partial :next_more, :start => start, :size => size %>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<% if key = params[:key] %>
|
2
|
+
|
3
|
+
<h1>Key "<%= key %>" is a <%= resque.redis.type key %></h1>
|
4
|
+
<h2>size: <%= redis_get_size(key) %></h2>
|
5
|
+
<table>
|
6
|
+
<% for row in redis_get_value_as_array(key) %>
|
7
|
+
<tr>
|
8
|
+
<td>
|
9
|
+
<%= row %>
|
10
|
+
</td>
|
11
|
+
</tr>
|
12
|
+
<% end %>
|
13
|
+
</table>
|
14
|
+
|
15
|
+
<% else %>
|
16
|
+
|
17
|
+
<% end %>
|
@@ -0,0 +1,41 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Resque.</title>
|
5
|
+
<link href="<%=u 'reset.css' %>" media="screen" rel="stylesheet" type="text/css">
|
6
|
+
<link href="<%=u 'style.css' %>" media="screen" rel="stylesheet" type="text/css">
|
7
|
+
<script src="<%=u 'jquery-1.3.2.min.js' %>" type="text/javascript"</script>
|
8
|
+
<script src="<%=u 'jquery.relatize_date.js' %>" type="text/javascript"</script>
|
9
|
+
<script src="<%=u 'ranger.js' %>" type="text/javascript"></script>
|
10
|
+
</head>
|
11
|
+
<body>
|
12
|
+
<div class="header">
|
13
|
+
<ul class='nav'>
|
14
|
+
<%= tab "Overview" %>
|
15
|
+
<%= tab "Working" %>
|
16
|
+
<%= tab "Failed" %>
|
17
|
+
<%= tab "Queues" %>
|
18
|
+
<%= tab "Workers" %>
|
19
|
+
<%= tab "Stats" %>
|
20
|
+
</ul>
|
21
|
+
</div>
|
22
|
+
|
23
|
+
<% if @subtabs %>
|
24
|
+
<ul class='subnav'>
|
25
|
+
<% for subtab in @subtabs %>
|
26
|
+
<li <%= class_if_current "#{current_section}/#{subtab}" %>><a href="<%= current_section %>/<%= subtab %>"><span><%= subtab %></span></a></li>
|
27
|
+
<% end %>
|
28
|
+
</ul>
|
29
|
+
<% end %>
|
30
|
+
|
31
|
+
<div id="main">
|
32
|
+
<%= yield %>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<div id="footer">
|
36
|
+
<p>Powered by <a href="http://github.com/defunkt/resque">Resque</a> v<%=Resque::Version%></p>
|
37
|
+
<p>Connected to Redis on <%=Resque.redis.server%></p>
|
38
|
+
</div>
|
39
|
+
|
40
|
+
</body>
|
41
|
+
</html>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<%if start - 20 >= 0 || start + 20 <= size%>
|
2
|
+
<p class='pagination'>
|
3
|
+
<% if start - 20 >= 0 %>
|
4
|
+
<a href="<%= current_page %>?start=<%= start - 20 %>" class='less'>« less</a>
|
5
|
+
<% end %>
|
6
|
+
<% if start + 20 <= size %>
|
7
|
+
<a href="<%= current_page %>?start=<%= start + 20 %>" class='more'>more »</a>
|
8
|
+
<% end %>
|
9
|
+
</p>
|
10
|
+
<%end%>
|
@@ -0,0 +1,46 @@
|
|
1
|
+
<% @subtabs = resque.queues unless partial? %>
|
2
|
+
|
3
|
+
<% if queue = params[:id] %>
|
4
|
+
|
5
|
+
<h1>Pending jobs on <span class='hl'><%= queue %></span></h1>
|
6
|
+
<p class='sub'>Showing <%= start = params[:start].to_i %> to <%= start + 20 %> of <b><%=size = resque.size(queue)%></b> jobs</p>
|
7
|
+
<table class='jobs'>
|
8
|
+
<tr>
|
9
|
+
<th>Class</th>
|
10
|
+
<th>Args</th>
|
11
|
+
</tr>
|
12
|
+
<% for job in (jobs = resque.peek(queue, start, 20)) %>
|
13
|
+
<tr>
|
14
|
+
<td class='class'><%= job['class'] %></td>
|
15
|
+
<td class='args'><%=h job['args'].inspect %></td>
|
16
|
+
</tr>
|
17
|
+
<% end %>
|
18
|
+
<% if jobs.empty? %>
|
19
|
+
<tr>
|
20
|
+
<td class='no-data' colspan='2'>There are no pending jobs in this queue</td>
|
21
|
+
</tr>
|
22
|
+
<% end %>
|
23
|
+
</table>
|
24
|
+
<%= partial :next_more, :start => start, :size => size %>
|
25
|
+
<% else %>
|
26
|
+
|
27
|
+
<h1 class='wi'>Queues</h1>
|
28
|
+
<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>
|
29
|
+
<table class='queues'>
|
30
|
+
<tr>
|
31
|
+
<th>Name</th>
|
32
|
+
<th>Jobs</th>
|
33
|
+
</tr>
|
34
|
+
<% for queue in resque.queues.sort_by { |q| q.to_s } %>
|
35
|
+
<tr>
|
36
|
+
<td class='queue'><a class="queue" href="<%= url "queues/#{queue}" %>"><%= queue %></a></td>
|
37
|
+
<td class='size'><%= resque.size queue %></td>
|
38
|
+
</tr>
|
39
|
+
<% end %>
|
40
|
+
<tr class='failed'>
|
41
|
+
<td class='queue failed'><a class="queue" href="<%= url :failed %>">failed</a></td>
|
42
|
+
<td class='size'><%= Resque::Failure.count %></td>
|
43
|
+
</tr>
|
44
|
+
</table>
|
45
|
+
|
46
|
+
<% end %>
|
@@ -0,0 +1,62 @@
|
|
1
|
+
<% @subtabs = %w( resque redis keys ) %>
|
2
|
+
|
3
|
+
<% if params[:key] %>
|
4
|
+
|
5
|
+
<%= 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.server %></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
|
+
<a href="/stats/keys/<%= key %>"><%= key %></a>
|
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,78 @@
|
|
1
|
+
<% if params[:id] && worker = Resque::Worker.find(params[:id]) %>
|
2
|
+
|
3
|
+
<h1>Worker <%= worker %></h1>
|
4
|
+
<table class='workers'>
|
5
|
+
<tr>
|
6
|
+
<th> </th>
|
7
|
+
<th>Host</th>
|
8
|
+
<th>Pid</th>
|
9
|
+
<th>Started</th>
|
10
|
+
<th>Queues</th>
|
11
|
+
<th>Processed</th>
|
12
|
+
<th>Failed</th>
|
13
|
+
<th>Processing</th>
|
14
|
+
</tr>
|
15
|
+
<tr>
|
16
|
+
<td class='icon'><img src="<%=u state = worker.state %>.png" alt="<%= state %>" title="<%= state %>"></td>
|
17
|
+
|
18
|
+
<% host, pid, queues = worker.to_s.split(':') %>
|
19
|
+
<td><%= host %></td>
|
20
|
+
<td><%= pid %></td>
|
21
|
+
<td><span class="time"><%= worker.started %></a></td>
|
22
|
+
<td class='queues'><%= queues.split(',').map { |q| '<a class="queue-tag" href="' + u("/queues/#{q}") + '">' + q + '</a>'}.join('') %></td>
|
23
|
+
<td><%= worker.processed %></td>
|
24
|
+
<td><%= worker.failed %></td>
|
25
|
+
<td class='process'>
|
26
|
+
<% data = worker.processing || {} %>
|
27
|
+
<% if data['queue'] %>
|
28
|
+
<code><%= data['payload']['class'] %></code>
|
29
|
+
<small><a class="queue time" href="<%=u "/working/#{worker}" %>"><%= data['run_at'] %></a></small>
|
30
|
+
<% else %>
|
31
|
+
<span class='waiting'>Waiting for a job...</span>
|
32
|
+
<% end %>
|
33
|
+
</td>
|
34
|
+
</tr>
|
35
|
+
</table>
|
36
|
+
|
37
|
+
<% elsif params[:id] %>
|
38
|
+
|
39
|
+
<h1>Worker doesn't exist</h1>
|
40
|
+
|
41
|
+
<% else %>
|
42
|
+
|
43
|
+
<h1 class='wi'><%= resque.workers.size %> Workers</h1>
|
44
|
+
<p class='intro'>The workers listed below are all registered as active on your system.</p>
|
45
|
+
<table class='workers'>
|
46
|
+
<tr>
|
47
|
+
<th> </th>
|
48
|
+
<th>Where</th>
|
49
|
+
<th>Queues</th>
|
50
|
+
<th>Processing</th>
|
51
|
+
</tr>
|
52
|
+
<% for worker in (workers = resque.workers.sort_by { |w| w.to_s }) %>
|
53
|
+
<tr class="<%=state = worker.state%>">
|
54
|
+
<td class='icon'><img src="<%=u state %>.png" alt="<%= state %>" title="<%= state %>"></td>
|
55
|
+
|
56
|
+
<% host, pid, queues = worker.to_s.split(':') %>
|
57
|
+
<td class='where'><a href="<%=u "workers/#{worker}"%>"><%= host %>:<%= pid %></a></td>
|
58
|
+
<td class='queues'><%= queues.split(',').map { |q| '<a class="queue-tag" href="' + u("/queues/#{q}") + '">' + q + '</a>'}.join('') %></td>
|
59
|
+
|
60
|
+
<td class='process'>
|
61
|
+
<% data = worker.processing || {} %>
|
62
|
+
<% if data['queue'] %>
|
63
|
+
<code><%= data['payload']['class'] %></code>
|
64
|
+
<small><a class="queue time" href="<%=u "/working/#{worker}" %>"><%= data['run_at'] %></a></small>
|
65
|
+
<% else %>
|
66
|
+
<span class='waiting'>Waiting for a job...</span>
|
67
|
+
<% end %>
|
68
|
+
</td>
|
69
|
+
</tr>
|
70
|
+
<% end %>
|
71
|
+
<% if workers.empty? %>
|
72
|
+
<tr>
|
73
|
+
<td colspan='4' class='no-data'>There are no registered workers</td>
|
74
|
+
</tr>
|
75
|
+
<% end %>
|
76
|
+
</table>
|
77
|
+
<%=poll%>
|
78
|
+
<% end %>
|
@@ -0,0 +1,67 @@
|
|
1
|
+
<% if params[:id] && (worker = Resque::Worker.find(params[:id])) && worker.job %>
|
2
|
+
<h1><%= worker %>'s job</h1>
|
3
|
+
|
4
|
+
<table>
|
5
|
+
<tr>
|
6
|
+
<th> </th>
|
7
|
+
<th>Where</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 'working.png' %>" alt="working" title="working"></td>
|
15
|
+
<% host, pid, _ = worker.to_s.split(':') %>
|
16
|
+
<td><a href="<%=u "/workers/#{worker}" %>"><%= host %>:<%= pid %></a></td>
|
17
|
+
<% data = worker.job %>
|
18
|
+
<% queue = data['queue'] %>
|
19
|
+
<td><a class="queue" href="<%=u "/queues/#{queue}" %>"><%= queue %></a></td>
|
20
|
+
<td><span class="time"><%= data['run_at'] %></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</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'] ? w.job['run_at'] : '' } %>
|
47
|
+
<% job = worker.job %>
|
48
|
+
<tr>
|
49
|
+
<td class='icon'><img src="<%=u state = worker.state %>.png" alt="<%= state %>" title="<%= state %>"></td>
|
50
|
+
<% host, pid, queues = worker.to_s.split(':') %>
|
51
|
+
<td class='where'><a href="<%=u "/workers/#{worker}" %>"><%= host %>:<%= pid %></a></td>
|
52
|
+
<td class='queues queue'>
|
53
|
+
<a class="queue-tag" href="<%=u "/queues/#{job['queue']}" %>"><%= job['queue'] %></a>
|
54
|
+
</td>
|
55
|
+
<td class='process'>
|
56
|
+
<% if job['queue'] %>
|
57
|
+
<code><%= job['payload']['class'] %></code>
|
58
|
+
<small><a class="queue time" href="<%=u "/working/#{worker}" %>"><%= job['run_at'] %></a></small>
|
59
|
+
<% else %>
|
60
|
+
<span class='waiting'>Waiting for a job...</span>
|
61
|
+
<% end %>
|
62
|
+
</td>
|
63
|
+
</tr>
|
64
|
+
<% end %>
|
65
|
+
</table>
|
66
|
+
|
67
|
+
<% end %>
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'erb'
|
3
|
+
require 'resque'
|
4
|
+
require 'resque/version'
|
5
|
+
|
6
|
+
module Resque
|
7
|
+
class Server < Sinatra::Base
|
8
|
+
dir = File.dirname(File.expand_path(__FILE__))
|
9
|
+
|
10
|
+
set :views, "#{dir}/server/views"
|
11
|
+
set :public, "#{dir}/server/public"
|
12
|
+
set :static, true
|
13
|
+
|
14
|
+
helpers do
|
15
|
+
include Rack::Utils
|
16
|
+
alias_method :h, :escape_html
|
17
|
+
|
18
|
+
def current_section
|
19
|
+
url request.path_info.sub('/','').split('/')[0].downcase
|
20
|
+
end
|
21
|
+
|
22
|
+
def current_page
|
23
|
+
url request.path_info.sub('/','').downcase
|
24
|
+
end
|
25
|
+
|
26
|
+
def url(*path_parts)
|
27
|
+
[ path_prefix, path_parts ].join("/").squeeze('/')
|
28
|
+
end
|
29
|
+
alias_method :u, :url
|
30
|
+
|
31
|
+
def path_prefix
|
32
|
+
request.env['SCRIPT_NAME']
|
33
|
+
end
|
34
|
+
|
35
|
+
def class_if_current(page = '')
|
36
|
+
'class="current"' if current_page.include? page.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
def tab(name)
|
40
|
+
dname = name.to_s.downcase
|
41
|
+
"<li #{class_if_current(dname)}><a href='#{url dname}'>#{name}</a></li>"
|
42
|
+
end
|
43
|
+
|
44
|
+
def redis_get_size(key)
|
45
|
+
case Resque.redis.type(key)
|
46
|
+
when 'none'
|
47
|
+
[]
|
48
|
+
when 'list'
|
49
|
+
Resque.redis.llen(key)
|
50
|
+
when 'set'
|
51
|
+
Resque.redis.scard(key)
|
52
|
+
when 'string'
|
53
|
+
Resque.redis.get(key).length
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def redis_get_value_as_array(key)
|
58
|
+
case Resque.redis.type(key)
|
59
|
+
when 'none'
|
60
|
+
[]
|
61
|
+
when 'list'
|
62
|
+
Resque.redis.lrange(key, 0, 20)
|
63
|
+
when 'set'
|
64
|
+
Resque.redis.smembers(key)
|
65
|
+
when 'string'
|
66
|
+
[Resque.redis.get(key)]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def show_args(args)
|
71
|
+
Array(args).map { |a| a.inspect }.join("\n")
|
72
|
+
end
|
73
|
+
|
74
|
+
def partial?
|
75
|
+
@partial
|
76
|
+
end
|
77
|
+
|
78
|
+
def partial(template, local_vars = {})
|
79
|
+
@partial = true
|
80
|
+
erb(template.to_sym, {:layout => false}, local_vars)
|
81
|
+
ensure
|
82
|
+
@partial = false
|
83
|
+
end
|
84
|
+
|
85
|
+
def poll
|
86
|
+
if @polling
|
87
|
+
text = "Last Updated: #{Time.now.strftime("%H:%M:%S")}"
|
88
|
+
else
|
89
|
+
text = "<a href='#{url(request.path_info)}.poll' rel='poll'>Live Poll</a>"
|
90
|
+
end
|
91
|
+
"<p class='poll'>#{text}</p>"
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
def show(page, layout = true)
|
97
|
+
begin
|
98
|
+
erb page.to_sym, {:layout => layout}, :resque => Resque
|
99
|
+
rescue Errno::ECONNREFUSED
|
100
|
+
erb :error, {:layout => false}, :error => "Can't connect to Redis! (#{Resque.redis.server})"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# to make things easier on ourselves
|
105
|
+
get "/" do
|
106
|
+
redirect url(:overview)
|
107
|
+
end
|
108
|
+
|
109
|
+
%w( overview queues working workers key ).each do |page|
|
110
|
+
get "/#{page}" do
|
111
|
+
show page
|
112
|
+
end
|
113
|
+
|
114
|
+
get "/#{page}/:id" do
|
115
|
+
show page
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
%w( overview workers ).each do |page|
|
120
|
+
get "/#{page}.poll" do
|
121
|
+
content_type "text/plain"
|
122
|
+
@polling = true
|
123
|
+
show(page.to_sym, false).gsub(/\s{1,}/, ' ')
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
get "/failed" do
|
128
|
+
if Resque::Failure.url
|
129
|
+
redirect Resque::Failure.url
|
130
|
+
else
|
131
|
+
show :failed
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
post "/failed/clear" do
|
136
|
+
Resque::Failure.clear
|
137
|
+
redirect u('failed')
|
138
|
+
end
|
139
|
+
|
140
|
+
get "/stats" do
|
141
|
+
redirect url("/stats/resque")
|
142
|
+
end
|
143
|
+
|
144
|
+
get "/stats/:id" do
|
145
|
+
show :stats
|
146
|
+
end
|
147
|
+
|
148
|
+
get "/stats/keys/:key" do
|
149
|
+
show :stats
|
150
|
+
end
|
151
|
+
|
152
|
+
get "/stats.txt" do
|
153
|
+
info = Resque.info
|
154
|
+
|
155
|
+
stats = []
|
156
|
+
stats << "resque.pending=#{info[:pending]}"
|
157
|
+
stats << "resque.processed+=#{info[:processed]}"
|
158
|
+
stats << "resque.failed+=#{info[:failed]}"
|
159
|
+
stats << "resque.workers=#{info[:workers]}"
|
160
|
+
stats << "resque.working=#{info[:working]}"
|
161
|
+
|
162
|
+
Resque.queues.each do |queue|
|
163
|
+
stats << "queues.#{queue}=#{Resque.size(queue)}"
|
164
|
+
end
|
165
|
+
|
166
|
+
content_type 'text/plain'
|
167
|
+
stats.join "\n"
|
168
|
+
end
|
169
|
+
|
170
|
+
def resque
|
171
|
+
Resque
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
data/lib/resque/stat.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
module Resque
|
2
|
+
# The stat subsystem. Used to keep track of integer counts.
|
3
|
+
#
|
4
|
+
# Get a stat: Stat[name]
|
5
|
+
# Incr a stat: Stat.incr(name)
|
6
|
+
# Decr a stat: Stat.decr(name)
|
7
|
+
# Kill a stat: Stat.clear(name)
|
8
|
+
module Stat
|
9
|
+
extend self
|
10
|
+
extend Helpers
|
11
|
+
|
12
|
+
# Returns the int value of a stat, given a string stat name.
|
13
|
+
def get(stat)
|
14
|
+
redis.get("stat:#{stat}").to_i
|
15
|
+
end
|
16
|
+
|
17
|
+
# Alias of `get`
|
18
|
+
def [](stat)
|
19
|
+
get(stat)
|
20
|
+
end
|
21
|
+
|
22
|
+
# For a string stat name, increments the stat by one.
|
23
|
+
#
|
24
|
+
# Can optionally accept a second int parameter. The stat is then
|
25
|
+
# incremented by that amount.
|
26
|
+
def incr(stat, by = 1)
|
27
|
+
redis.incr("stat:#{stat}", by)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Increments a stat by one.
|
31
|
+
def <<(stat)
|
32
|
+
incr stat
|
33
|
+
end
|
34
|
+
|
35
|
+
# For a string stat name, decrements the stat by one.
|
36
|
+
#
|
37
|
+
# Can optionally accept a second int parameter. The stat is then
|
38
|
+
# decremented by that amount.
|
39
|
+
def decr(stat, by = 1)
|
40
|
+
redis.decr("stat:#{stat}", by)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Decrements a stat by one.
|
44
|
+
def >>(stat)
|
45
|
+
decr stat
|
46
|
+
end
|
47
|
+
|
48
|
+
# Removes a stat from Redis, effectively setting it to 0.
|
49
|
+
def clear(stat)
|
50
|
+
redis.del("stat:#{stat}")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/resque/tasks.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# require 'resque/tasks'
|
2
|
+
# will give you the resque tasks
|
3
|
+
|
4
|
+
namespace :resque do
|
5
|
+
desc "Start a Resque Ranger"
|
6
|
+
task :work do
|
7
|
+
Rake::Task['resque:setup'].invoke rescue nil
|
8
|
+
|
9
|
+
worker = nil
|
10
|
+
queues = (ENV['QUEUES'] || ENV['QUEUE']).to_s.split(',')
|
11
|
+
|
12
|
+
begin
|
13
|
+
worker = Resque::Worker.new(*queues)
|
14
|
+
worker.verbose = ENV['LOGGING'] || ENV['VERBOSE']
|
15
|
+
worker.very_verbose = ENV['VVERBOSE']
|
16
|
+
rescue Resque::NoQueueError
|
17
|
+
abort "set QUEUE env var, e.g. $ QUEUE=critical,high rake resque:work"
|
18
|
+
end
|
19
|
+
|
20
|
+
puts "*** Starting worker #{worker}"
|
21
|
+
|
22
|
+
worker.work(ENV['INTERVAL'] || 5) # interval, will block
|
23
|
+
end
|
24
|
+
end
|