resque 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of resque might be problematic. Click here for more details.
- data/.kick +26 -0
- data/HISTORY.md +3 -0
- data/LICENSE +20 -0
- data/README.markdown +638 -0
- data/Rakefile +61 -0
- data/TODO.md +60 -0
- data/bin/resque +57 -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/existing_classes_as_jobs.rb +3 -0
- data/examples/instance.rb +11 -0
- data/examples/simple.rb +30 -0
- data/init.rb +1 -0
- data/lib/resque.rb +184 -0
- data/lib/resque/errors.rb +7 -0
- data/lib/resque/failure.rb +57 -0
- data/lib/resque/failure/base.rb +54 -0
- data/lib/resque/failure/hoptoad.rb +88 -0
- data/lib/resque/failure/redis.rb +28 -0
- data/lib/resque/helpers.rb +57 -0
- data/lib/resque/job.rb +91 -0
- data/lib/resque/server.rb +154 -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/nav-bg.png +0 -0
- data/lib/resque/server/public/ranger.js +7 -0
- data/lib/resque/server/public/reset.css +51 -0
- data/lib/resque/server/public/style.css +67 -0
- data/lib/resque/server/public/tab_b.gif +0 -0
- data/lib/resque/server/public/tab_r.gif +0 -0
- data/lib/resque/server/public/tabs.css +189 -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 +29 -0
- data/lib/resque/server/views/key.erb +17 -0
- data/lib/resque/server/views/layout.erb +43 -0
- data/lib/resque/server/views/next_more.erb +12 -0
- data/lib/resque/server/views/overview.erb +2 -0
- data/lib/resque/server/views/queues.erb +40 -0
- data/lib/resque/server/views/stats.erb +62 -0
- data/lib/resque/server/views/workers.erb +72 -0
- data/lib/resque/server/views/working.erb +66 -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/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 +212 -0
- metadata +124 -0
Binary file
|
Binary file
|
@@ -0,0 +1,189 @@
|
|
1
|
+
/* tabs styles, based on http://www.alistapart.com/articles/slidingdoors */
|
2
|
+
|
3
|
+
DIV.tabs
|
4
|
+
{
|
5
|
+
float : left;
|
6
|
+
width : 100%;
|
7
|
+
background : url("tab_b.gif") repeat-x bottom;
|
8
|
+
margin-bottom : 4px;
|
9
|
+
}
|
10
|
+
|
11
|
+
DIV.tabs UL
|
12
|
+
{
|
13
|
+
margin : 0px;
|
14
|
+
padding-left : 10px;
|
15
|
+
list-style : none;
|
16
|
+
}
|
17
|
+
|
18
|
+
DIV.tabs LI, DIV.tabs FORM
|
19
|
+
{
|
20
|
+
display : inline;
|
21
|
+
margin : 0px;
|
22
|
+
padding : 0px;
|
23
|
+
}
|
24
|
+
|
25
|
+
DIV.tabs FORM
|
26
|
+
{
|
27
|
+
float : right;
|
28
|
+
}
|
29
|
+
|
30
|
+
DIV.tabs A
|
31
|
+
{
|
32
|
+
float : left;
|
33
|
+
background : url("tab_r.gif") no-repeat right top;
|
34
|
+
border-bottom : 1px solid #84B0C7;
|
35
|
+
font-size : 80%;
|
36
|
+
font-weight : bold;
|
37
|
+
text-decoration : none;
|
38
|
+
}
|
39
|
+
|
40
|
+
DIV.tabs A:hover
|
41
|
+
{
|
42
|
+
background-position: 100% -150px;
|
43
|
+
}
|
44
|
+
|
45
|
+
DIV.tabs A:link, DIV.tabs A:visited,
|
46
|
+
DIV.tabs A:active, DIV.tabs A:hover
|
47
|
+
{
|
48
|
+
color: #1A419D;
|
49
|
+
}
|
50
|
+
|
51
|
+
DIV.tabs SPAN
|
52
|
+
{
|
53
|
+
float : left;
|
54
|
+
display : block;
|
55
|
+
background : url("tab_l.gif") no-repeat left top;
|
56
|
+
padding : 5px 9px;
|
57
|
+
white-space : nowrap;
|
58
|
+
}
|
59
|
+
|
60
|
+
DIV.tabs INPUT
|
61
|
+
{
|
62
|
+
float : right;
|
63
|
+
display : inline;
|
64
|
+
font-size : 1em;
|
65
|
+
}
|
66
|
+
|
67
|
+
DIV.tabs TD
|
68
|
+
{
|
69
|
+
font-size : 80%;
|
70
|
+
font-weight : bold;
|
71
|
+
text-decoration : none;
|
72
|
+
}
|
73
|
+
|
74
|
+
/* Commented Backslash Hack hides rule from IE5-Mac \*/
|
75
|
+
DIV.tabs SPAN {float : none;}
|
76
|
+
/* End IE5-Mac hack */
|
77
|
+
|
78
|
+
DIV.tabs A:hover SPAN
|
79
|
+
{
|
80
|
+
background-position: 0% -150px;
|
81
|
+
}
|
82
|
+
|
83
|
+
DIV.tabs LI.current A
|
84
|
+
{
|
85
|
+
background-position: 100% -150px;
|
86
|
+
border-width : 0px;
|
87
|
+
}
|
88
|
+
|
89
|
+
DIV.tabs LI.current SPAN
|
90
|
+
{
|
91
|
+
background-position: 0% -150px;
|
92
|
+
padding-bottom : 6px;
|
93
|
+
}
|
94
|
+
|
95
|
+
DIV.navpath
|
96
|
+
{
|
97
|
+
background : none;
|
98
|
+
border : none;
|
99
|
+
border-bottom : 1px solid #84B0C7;
|
100
|
+
text-align : center;
|
101
|
+
margin : 2px;
|
102
|
+
padding : 2px;
|
103
|
+
}
|
104
|
+
div.tabs {
|
105
|
+
background: url(nav-bg.png) repeat-x !important;
|
106
|
+
margin: 0 !important;
|
107
|
+
margin-bottom: 0 !important;
|
108
|
+
padding: 8px 0;
|
109
|
+
float: none;
|
110
|
+
border-bottom: 1px solid #A4B0BC;
|
111
|
+
font-size: 100%;
|
112
|
+
}
|
113
|
+
|
114
|
+
div.tabs li {
|
115
|
+
line-height: 100%;
|
116
|
+
display: block;
|
117
|
+
float: left;
|
118
|
+
margin-right: 10px;
|
119
|
+
}
|
120
|
+
|
121
|
+
div.tabs a {
|
122
|
+
background: none;
|
123
|
+
font-size: 100%;
|
124
|
+
padding: 5px 8px;
|
125
|
+
text-shadow: 1px 1px #eff4f7;
|
126
|
+
}
|
127
|
+
|
128
|
+
div.tabs span {
|
129
|
+
background: none;
|
130
|
+
padding: 0;
|
131
|
+
}
|
132
|
+
|
133
|
+
div.tabs li.current a {
|
134
|
+
background: #bdcad4;
|
135
|
+
-webkit-border-radius: 4px;
|
136
|
+
-moz-border-radius: 4px;
|
137
|
+
-o-border-radius: 4px;
|
138
|
+
border-radius: 4px;
|
139
|
+
text-shadow: none;
|
140
|
+
}
|
141
|
+
|
142
|
+
div.tabs li.current span {
|
143
|
+
padding: 0;
|
144
|
+
}
|
145
|
+
|
146
|
+
div.tabs a:link, div.tabs a:visited, div.tabs a:active, div.tabs a:hover
|
147
|
+
{
|
148
|
+
color: #546e80;
|
149
|
+
border: none;
|
150
|
+
}
|
151
|
+
|
152
|
+
div.tabs ul:after {
|
153
|
+
content: ".";
|
154
|
+
display: block;
|
155
|
+
clear: both;
|
156
|
+
height: 0;
|
157
|
+
visibility: hidden;
|
158
|
+
}
|
159
|
+
|
160
|
+
div.tabs + div.tabs {
|
161
|
+
background: #f2f6f9 !important;
|
162
|
+
border-bottom: 1px solid #e2ecf3 !important;
|
163
|
+
}
|
164
|
+
|
165
|
+
div.navpath {
|
166
|
+
line-height: 100%;
|
167
|
+
text-align: left;
|
168
|
+
background: #f2f6f9 !important;
|
169
|
+
border-bottom: 1px solid #e2ecf3 !important;
|
170
|
+
padding: 0;
|
171
|
+
margin: 0;
|
172
|
+
}
|
173
|
+
|
174
|
+
div.navpath:after {
|
175
|
+
content: ".";
|
176
|
+
display: block;
|
177
|
+
visibility: hidden;
|
178
|
+
clear: both;
|
179
|
+
padding: 0;
|
180
|
+
margin: 0;
|
181
|
+
height: 0;
|
182
|
+
}
|
183
|
+
|
184
|
+
div.navpath a {
|
185
|
+
display: block;
|
186
|
+
float: left;
|
187
|
+
padding: 8px 20px;
|
188
|
+
color: #8c99a3;
|
189
|
+
}
|
Binary file
|
@@ -0,0 +1 @@
|
|
1
|
+
<h1><%= error %></h1>
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<h1><%= size = Resque::Failure.count %> Jobs Failed</h1>
|
2
|
+
<h2>Showing <%= start = params[:start].to_i %> to <%= start + 20 %></h2>
|
3
|
+
<table>
|
4
|
+
<tr>
|
5
|
+
<th>Queue</th>
|
6
|
+
<th>Worker</th>
|
7
|
+
<th>Failed</th>
|
8
|
+
<th>Class</th>
|
9
|
+
<th>Args</th>
|
10
|
+
<th>Error</th>
|
11
|
+
</tr>
|
12
|
+
<% for job in Resque::Failure.all(start, 20) %>
|
13
|
+
<tr>
|
14
|
+
<td><%= job['queue'] %></td>
|
15
|
+
<td><a href="<= url(:workers, job['worker']) %>"><%= job['worker'].split(':')[0...2].join(':') %></a></td>
|
16
|
+
<td><span class="time"><%= job['failed_at'] %></span></td>
|
17
|
+
<td><%= job['payload']['class'] %></td>
|
18
|
+
<td>
|
19
|
+
<a href="#" class="backtrace"><%= Array(job['payload']['args']).size %></a>
|
20
|
+
<pre style="display:none;"><%=h show_args(job['payload']['args']) %></pre>
|
21
|
+
</td>
|
22
|
+
<td>
|
23
|
+
<a href="#" class="backtrace"><%= h(job['error']) %></a>
|
24
|
+
<pre style="display:none;"><%=h job['backtrace'].join("\n") %></pre>
|
25
|
+
</td>
|
26
|
+
</tr>
|
27
|
+
<% end %>
|
28
|
+
<%= partial :next_more, :start => start, :size => size %>
|
29
|
+
</table>
|
@@ -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,43 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Resque.</title>
|
5
|
+
<link href="<%=u 'style.css' %>" media="screen" rel="stylesheet" type="text/css">
|
6
|
+
<link href="<%=u 'tabs.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
|
+
|
13
|
+
<div class="navigation" id="top">
|
14
|
+
<div class="tabs">
|
15
|
+
<div id="logo">
|
16
|
+
Resque
|
17
|
+
</div>
|
18
|
+
<ul>
|
19
|
+
<%= tab "Overview" %>
|
20
|
+
<%= tab "Working" %>
|
21
|
+
<%= tab "Failed" %>
|
22
|
+
<%= tab "Queues" %>
|
23
|
+
<%= tab "Workers" %>
|
24
|
+
<%= tab "Stats" %>
|
25
|
+
</ul>
|
26
|
+
</div>
|
27
|
+
<% if @subtabs %>
|
28
|
+
<div class="tabs">
|
29
|
+
<ul>
|
30
|
+
<% for subtab in @subtabs %>
|
31
|
+
<li <%= class_if_current "#{current_section}/#{subtab}" %>><a href="<%= current_section %>/<%= subtab %>"><span><%= subtab %></span></a></li>
|
32
|
+
<% end %>
|
33
|
+
</ul>
|
34
|
+
</div>
|
35
|
+
<% end %>
|
36
|
+
</div>
|
37
|
+
|
38
|
+
<div id="main">
|
39
|
+
<%= yield %>
|
40
|
+
</div>
|
41
|
+
|
42
|
+
</body>
|
43
|
+
</html>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<tr>
|
2
|
+
<td>
|
3
|
+
<% if start - 20 >= 0 %>
|
4
|
+
<a href="/<%= current_page %>?start=<%= start - 20 %>">« less</a>
|
5
|
+
<% end %>
|
6
|
+
</td>
|
7
|
+
<td>
|
8
|
+
<% if start + 20 <= size %>
|
9
|
+
<a href="/<%= current_page %>?start=<%= start + 20 %>">more »</a>
|
10
|
+
<% end %>
|
11
|
+
</td>
|
12
|
+
</tr>
|
@@ -0,0 +1,40 @@
|
|
1
|
+
<% @subtabs = resque.queues unless partial? %>
|
2
|
+
|
3
|
+
<% if queue = params[:id] %>
|
4
|
+
|
5
|
+
<h1><%= size = resque.size(queue) %> Pending Jobs in '<%= queue.upcase %>'</h1>
|
6
|
+
<h2>Showing <%= start = params[:start].to_i %> to <%= start + 20 %></h2>
|
7
|
+
<table>
|
8
|
+
<tr>
|
9
|
+
<th>Class</th>
|
10
|
+
<th>Args</th>
|
11
|
+
</tr>
|
12
|
+
<% for job in resque.peek(queue, start, 20) %>
|
13
|
+
<tr>
|
14
|
+
<td><%= job['class'] %></td>
|
15
|
+
<td><%=h job['args'].inspect %></td>
|
16
|
+
</tr>
|
17
|
+
<% end %>
|
18
|
+
<%= partial :next_more, :start => start, :size => size %>
|
19
|
+
</table>
|
20
|
+
<% else %>
|
21
|
+
|
22
|
+
<h1>Queues</h1>
|
23
|
+
<table>
|
24
|
+
<tr>
|
25
|
+
<th>Name</th>
|
26
|
+
<th>Pending</th>
|
27
|
+
</tr>
|
28
|
+
<% for queue in resque.queues.sort_by { |q| q.to_s } %>
|
29
|
+
<tr>
|
30
|
+
<td><a class="queue" href="<%= url "queues/#{queue}" %>"><%= queue %></a></td>
|
31
|
+
<td><%= resque.size queue %></td>
|
32
|
+
</tr>
|
33
|
+
<% end %>
|
34
|
+
<tr>
|
35
|
+
<td><a class="queue" href="<%= url :failed %>">failed</a></td>
|
36
|
+
<td><%= Resque::Failure.count %></td>
|
37
|
+
</tr>
|
38
|
+
</table>
|
39
|
+
|
40
|
+
<% 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>
|
11
|
+
<% for key, value in resque.info.to_a.sort_by { |i| i[0].to_s } %>
|
12
|
+
<tr>
|
13
|
+
<td>
|
14
|
+
<%= key %>
|
15
|
+
</td>
|
16
|
+
<td>
|
17
|
+
<%= value %>
|
18
|
+
</td>
|
19
|
+
</tr>
|
20
|
+
<% end %>
|
21
|
+
</table>
|
22
|
+
|
23
|
+
<% elsif params[:id] == 'redis' %>
|
24
|
+
|
25
|
+
<h1><%= resque.redis %></h1>
|
26
|
+
<table>
|
27
|
+
<% for key, value in resque.redis.info.to_a.sort_by { |i| i[0].to_s } %>
|
28
|
+
<tr>
|
29
|
+
<td>
|
30
|
+
<%= key %>
|
31
|
+
</td>
|
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
|
+
<h2>(All keys are actually prefixed with "resque:")</h2>
|
43
|
+
<table>
|
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
|
+
<td>
|
52
|
+
<a href="/stats/keys/<%= key %>"><%= key %></a>
|
53
|
+
</td>
|
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,72 @@
|
|
1
|
+
<% if params[:id] && worker = Resque::Worker.find(params[:id]) %>
|
2
|
+
|
3
|
+
<h1>Worker <%= worker %></h1>
|
4
|
+
<table>
|
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><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><%= queues.split(',').map { |q| '<a class="queue" href="' + u("/queues/#{q}") + '">' + q + '</a>'}.join(', ') %></td>
|
23
|
+
<td><%= worker.processed %></td>
|
24
|
+
<td><%= worker.failed %></td>
|
25
|
+
<td>
|
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
|
+
Waiting for more
|
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><%= resque.workers.size %> Workers</h1>
|
44
|
+
<table>
|
45
|
+
<tr>
|
46
|
+
<th> </th>
|
47
|
+
<th>Where</th>
|
48
|
+
<th>Queues</th>
|
49
|
+
<th>Processing</th>
|
50
|
+
</tr>
|
51
|
+
<% for worker in resque.workers.sort_by { |w| w.to_s } %>
|
52
|
+
<tr>
|
53
|
+
<td><img src="<%=u state = worker.state %>.png" alt="<%= state %>" title="<%= state %>"></td>
|
54
|
+
|
55
|
+
<% host, pid, queues = worker.to_s.split(':') %>
|
56
|
+
<td><a href="/workers/<%= worker %>"><%= host %>:<%= pid %></a></td>
|
57
|
+
<td><%= queues.split(',').map { |q| '<a class="queue" href="' + u("/queues/#{q}") + '">' + q + '</a>'}.join(', ') %></td>
|
58
|
+
|
59
|
+
<td>
|
60
|
+
<% data = worker.processing || {} %>
|
61
|
+
<% if data['queue'] %>
|
62
|
+
<code><%= data['payload']['class'] %></code>
|
63
|
+
<small><a class="queue time" href="<%=u "/working/#{worker}" %>"><%= data['run_at'] %></a></small>
|
64
|
+
<% else %>
|
65
|
+
Waiting for more
|
66
|
+
<% end %>
|
67
|
+
</td>
|
68
|
+
</tr>
|
69
|
+
<% end %>
|
70
|
+
</table>
|
71
|
+
|
72
|
+
<% end %>
|