reqless 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +8 -0
- data/README.md +648 -0
- data/Rakefile +117 -0
- data/bin/docker-build-and-test +22 -0
- data/exe/reqless-web +11 -0
- data/lib/reqless/config.rb +31 -0
- data/lib/reqless/failure_formatter.rb +43 -0
- data/lib/reqless/job.rb +496 -0
- data/lib/reqless/job_reservers/ordered.rb +29 -0
- data/lib/reqless/job_reservers/round_robin.rb +46 -0
- data/lib/reqless/job_reservers/shuffled_round_robin.rb +21 -0
- data/lib/reqless/lua/reqless-lib.lua +2965 -0
- data/lib/reqless/lua/reqless.lua +2545 -0
- data/lib/reqless/lua_script.rb +90 -0
- data/lib/reqless/middleware/requeue_exceptions.rb +94 -0
- data/lib/reqless/middleware/retry_exceptions.rb +72 -0
- data/lib/reqless/middleware/sentry.rb +66 -0
- data/lib/reqless/middleware/timeout.rb +63 -0
- data/lib/reqless/queue.rb +189 -0
- data/lib/reqless/queue_priority_pattern.rb +16 -0
- data/lib/reqless/server/static/css/bootstrap-responsive.css +686 -0
- data/lib/reqless/server/static/css/bootstrap-responsive.min.css +12 -0
- data/lib/reqless/server/static/css/bootstrap.css +3991 -0
- data/lib/reqless/server/static/css/bootstrap.min.css +689 -0
- data/lib/reqless/server/static/css/codemirror.css +112 -0
- data/lib/reqless/server/static/css/docs.css +839 -0
- data/lib/reqless/server/static/css/jquery.noty.css +105 -0
- data/lib/reqless/server/static/css/noty_theme_twitter.css +137 -0
- data/lib/reqless/server/static/css/style.css +200 -0
- data/lib/reqless/server/static/favicon.ico +0 -0
- data/lib/reqless/server/static/img/glyphicons-halflings-white.png +0 -0
- data/lib/reqless/server/static/img/glyphicons-halflings.png +0 -0
- data/lib/reqless/server/static/js/bootstrap-alert.js +94 -0
- data/lib/reqless/server/static/js/bootstrap-scrollspy.js +125 -0
- data/lib/reqless/server/static/js/bootstrap-tab.js +130 -0
- data/lib/reqless/server/static/js/bootstrap-tooltip.js +270 -0
- data/lib/reqless/server/static/js/bootstrap-typeahead.js +285 -0
- data/lib/reqless/server/static/js/bootstrap.js +1726 -0
- data/lib/reqless/server/static/js/bootstrap.min.js +6 -0
- data/lib/reqless/server/static/js/codemirror.js +2972 -0
- data/lib/reqless/server/static/js/jquery.noty.js +220 -0
- data/lib/reqless/server/static/js/mode/javascript.js +360 -0
- data/lib/reqless/server/static/js/theme/cobalt.css +18 -0
- data/lib/reqless/server/static/js/theme/eclipse.css +25 -0
- data/lib/reqless/server/static/js/theme/elegant.css +10 -0
- data/lib/reqless/server/static/js/theme/lesser-dark.css +45 -0
- data/lib/reqless/server/static/js/theme/monokai.css +28 -0
- data/lib/reqless/server/static/js/theme/neat.css +9 -0
- data/lib/reqless/server/static/js/theme/night.css +21 -0
- data/lib/reqless/server/static/js/theme/rubyblue.css +21 -0
- data/lib/reqless/server/static/js/theme/xq-dark.css +46 -0
- data/lib/reqless/server/views/_job.erb +259 -0
- data/lib/reqless/server/views/_job_list.erb +8 -0
- data/lib/reqless/server/views/_pagination.erb +7 -0
- data/lib/reqless/server/views/about.erb +130 -0
- data/lib/reqless/server/views/completed.erb +11 -0
- data/lib/reqless/server/views/config.erb +14 -0
- data/lib/reqless/server/views/failed.erb +48 -0
- data/lib/reqless/server/views/failed_type.erb +18 -0
- data/lib/reqless/server/views/job.erb +17 -0
- data/lib/reqless/server/views/layout.erb +451 -0
- data/lib/reqless/server/views/overview.erb +137 -0
- data/lib/reqless/server/views/queue.erb +125 -0
- data/lib/reqless/server/views/queues.erb +45 -0
- data/lib/reqless/server/views/tag.erb +6 -0
- data/lib/reqless/server/views/throttles.erb +38 -0
- data/lib/reqless/server/views/track.erb +75 -0
- data/lib/reqless/server/views/worker.erb +34 -0
- data/lib/reqless/server/views/workers.erb +14 -0
- data/lib/reqless/server.rb +549 -0
- data/lib/reqless/subscriber.rb +74 -0
- data/lib/reqless/test_helpers/worker_helpers.rb +55 -0
- data/lib/reqless/throttle.rb +57 -0
- data/lib/reqless/version.rb +5 -0
- data/lib/reqless/worker/base.rb +237 -0
- data/lib/reqless/worker/forking.rb +215 -0
- data/lib/reqless/worker/serial.rb +41 -0
- data/lib/reqless/worker.rb +5 -0
- data/lib/reqless.rb +309 -0
- metadata +399 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
<script>
|
2
|
+
var fade = function(jid, type) {
|
3
|
+
if (type == 'cancel') {
|
4
|
+
$('#job-' + jid).slideUp();
|
5
|
+
}
|
6
|
+
}
|
7
|
+
</script>
|
8
|
+
|
9
|
+
<% if job.nil? %>
|
10
|
+
<div class="row">
|
11
|
+
<div class="span12">
|
12
|
+
<h2><%= jid %> doesn't exist, was canceled, or expired</h2>
|
13
|
+
</div>
|
14
|
+
</div>
|
15
|
+
<% else %>
|
16
|
+
<%= erb :_job, :layout => false, :locals => { :job => job, :queues => queues } %>
|
17
|
+
<% end %>
|
@@ -0,0 +1,451 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<title><%= application_name %><%= (title.length == 0) ? '' : (' | ' + title) %></title>
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
7
|
+
<meta name="description" content="">
|
8
|
+
<meta name="author" content="Dan Lecocq">
|
9
|
+
|
10
|
+
<link href="<%= u '/css/bootstrap.css' %>" rel="stylesheet">
|
11
|
+
<link href="<%= u '/css/bootstrap-responsive.css' %>" rel="stylesheet">
|
12
|
+
<link href="<%= u '/css/docs.css' %>" rel="stylesheet">
|
13
|
+
<link href="<%= u '/css/jquery.noty.css' %>" rel="stylesheet">
|
14
|
+
<link href="<%= u '/css/noty_theme_twitter.css' %>" rel="stylesheet">
|
15
|
+
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
|
16
|
+
|
17
|
+
<style type="text/css">
|
18
|
+
body {
|
19
|
+
padding-top: 60px;
|
20
|
+
}
|
21
|
+
|
22
|
+
.btn-group span {
|
23
|
+
/* This is ugly. Anyone want to change it? */
|
24
|
+
border-color: #e6e6e6 #e6e6e6 #bfbfbf;
|
25
|
+
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
26
|
+
border: 1px solid #cccccc;
|
27
|
+
border-bottom-color: #b3b3b3;
|
28
|
+
background-color: #f5f5f5;
|
29
|
+
font-size: 13px;
|
30
|
+
line-height: 18px;
|
31
|
+
padding: 4px 10px 4px;
|
32
|
+
}
|
33
|
+
|
34
|
+
.btn-group input, .btn-group span {
|
35
|
+
position: relative;
|
36
|
+
float: left;
|
37
|
+
margin-left: -1px;
|
38
|
+
-webkit-border-radius: 0;
|
39
|
+
-moz-border-radius: 0;
|
40
|
+
border-radius: 0;
|
41
|
+
margin-bottom: 0px;
|
42
|
+
}
|
43
|
+
|
44
|
+
.btn-group input:first-child, .btn-group span:first-child {
|
45
|
+
margin-left: 0;
|
46
|
+
-webkit-border-top-left-radius: 4px;
|
47
|
+
-moz-border-radius-topleft: 4px;
|
48
|
+
border-top-left-radius: 4px;
|
49
|
+
-webkit-border-bottom-left-radius: 4px;
|
50
|
+
-moz-border-radius-bottomleft: 4px;
|
51
|
+
border-bottom-left-radius: 4px;
|
52
|
+
}
|
53
|
+
|
54
|
+
.large-text {
|
55
|
+
font-size:18px;
|
56
|
+
}
|
57
|
+
|
58
|
+
.queue-column {
|
59
|
+
min-width:300px;
|
60
|
+
}
|
61
|
+
|
62
|
+
</style>
|
63
|
+
|
64
|
+
<script type="text/javascript">
|
65
|
+
/* This is a helper method to display an alert at the top of the page,
|
66
|
+
* in a vein similar to that of Ruby's flash */
|
67
|
+
var flash = function(message, t, duration) {
|
68
|
+
var noty_id = noty({
|
69
|
+
text : '<strong>' + message + '</strong>',
|
70
|
+
layout : 'top',
|
71
|
+
type : t || 'error',
|
72
|
+
theme : 'noty_theme_twitter',
|
73
|
+
timeout: duration || 1500});
|
74
|
+
}
|
75
|
+
|
76
|
+
/* This just sets a few options that we use */
|
77
|
+
var _ajax = function(obj) {
|
78
|
+
$.ajax({
|
79
|
+
url: obj.url,
|
80
|
+
type: 'POST',
|
81
|
+
dataType: 'json',
|
82
|
+
data: JSON.stringify(obj.data),
|
83
|
+
processData: false,
|
84
|
+
success: obj.success || function() {},
|
85
|
+
error: obj.error || function() {}
|
86
|
+
});
|
87
|
+
}
|
88
|
+
|
89
|
+
/* This is a helper method to move a job into a queue, and then it will
|
90
|
+
* flash a message to that effect on the page */
|
91
|
+
var move = function(jid, queue, cb) {
|
92
|
+
_ajax({
|
93
|
+
url: '<%= u "/move" %>',
|
94
|
+
data: {id:jid, queue:queue},
|
95
|
+
success: function() { flash('Moved ' + jid + ' to ' + queue, 'success', 1500); cb(jid, queue); },
|
96
|
+
error: function() { flash('Failed to move ' + jid + ' to ' + queue); }
|
97
|
+
});
|
98
|
+
}
|
99
|
+
|
100
|
+
/* Helper function for retrying a job */
|
101
|
+
var retry = function(jid, cb) {
|
102
|
+
_ajax({
|
103
|
+
url: '<%= u "/retry" %>',
|
104
|
+
data: {id:jid},
|
105
|
+
success: function() { flash('Retrying ' + jid, 'success', 1500); if (cb) { cb(jid, 'retry'); } },
|
106
|
+
error: function() { flash('Failed to retry ' + jid); }
|
107
|
+
});
|
108
|
+
}
|
109
|
+
|
110
|
+
/* This is a helper method to cancel a job */
|
111
|
+
var cancel = function(jid, cb) {
|
112
|
+
_ajax({
|
113
|
+
url: '<%= u "/cancel" %>',
|
114
|
+
data: [jid],
|
115
|
+
success: function() { flash('Canceled ' + jid, null, 1500); if (cb) { cb(jid, 'cancel'); } },
|
116
|
+
error: function() { flash('Failed to cancel ' + jid); }
|
117
|
+
});
|
118
|
+
}
|
119
|
+
|
120
|
+
/* This is a helper method to untrack a job */
|
121
|
+
var untrack = function(jid, cb) {
|
122
|
+
_ajax({
|
123
|
+
url: '<%= u "/untrack" %>',
|
124
|
+
data: [jid],
|
125
|
+
success: function() { flash('Stopped tracking ' + jid, 'success', 1500); if (cb) { cb(jid, 'untrack'); } },
|
126
|
+
error: function() { flash('Failed to track ' + jid); }
|
127
|
+
});
|
128
|
+
}
|
129
|
+
|
130
|
+
/* This is a helper to start tracking a job, with tags */
|
131
|
+
var track = function(jid, tags, cb) {
|
132
|
+
_ajax({
|
133
|
+
url: '<%= u "/track" %>',
|
134
|
+
data: {id:jid, tags:(tags || [])},
|
135
|
+
success: function() { flash('Now tracking ' + jid, 'success', 1500); if (cb) { cb(jid, 'track'); } },
|
136
|
+
error: function() { flash('Failed to track ' + jid); }
|
137
|
+
});
|
138
|
+
}
|
139
|
+
|
140
|
+
/* This is a helper to retry all jobs of a certain failure type */
|
141
|
+
var retryall = function(type, cb) {
|
142
|
+
_ajax({
|
143
|
+
url: '<%= u "/retryall" %>',
|
144
|
+
data: {type: type},
|
145
|
+
success: function(response) {
|
146
|
+
flash('Retrying failures of type ' + type, 'success', 1500);
|
147
|
+
if (cb) {
|
148
|
+
for (var i in response) {
|
149
|
+
cb(response[i].id);
|
150
|
+
}
|
151
|
+
}
|
152
|
+
},
|
153
|
+
error: function() { flash('Failed to retry failures of type ' + type); }
|
154
|
+
});
|
155
|
+
}
|
156
|
+
|
157
|
+
/* This is a helper to cancel all jobs of a certain failure type */
|
158
|
+
var cancelall = function(type, cb) {
|
159
|
+
_ajax({
|
160
|
+
url: '<%= u "/cancelall" %>',
|
161
|
+
data: {type: type},
|
162
|
+
success: function(response) {
|
163
|
+
flash('Canceling failures of type ' + type, 'success', 1500);
|
164
|
+
if (cb) {
|
165
|
+
for (var i in response) {
|
166
|
+
cb(response[i].id);
|
167
|
+
}
|
168
|
+
}
|
169
|
+
},
|
170
|
+
error: function() { flash('Failed to cancel failures of type ' + type); }
|
171
|
+
});
|
172
|
+
}
|
173
|
+
|
174
|
+
/* This is a helper to remove job dependencies */
|
175
|
+
var undepend = function(jid, dependency, cb) {
|
176
|
+
_ajax({
|
177
|
+
url: '<%= u "/undepend" %>',
|
178
|
+
data: {id:jid, dependency:dependency},
|
179
|
+
success: function() { flash(jid + ' no longer depends on ' + dependency, 'success', 1500); if (cb) { cb(jid, 'undepend'); } },
|
180
|
+
error: function() { flash('Failed to remove ' + jid + '\'s dependency on ' + dependency); }
|
181
|
+
});
|
182
|
+
}
|
183
|
+
|
184
|
+
/* Helper function to fade out a particular element id */
|
185
|
+
var fade = function(jid, type) {
|
186
|
+
if (type != 'untrack' && type != 'track') {
|
187
|
+
$('#job-' + jid).slideUp();
|
188
|
+
}
|
189
|
+
}
|
190
|
+
|
191
|
+
/* Helper function to make a button ask for confirmation
|
192
|
+
* after being pressed once. Accepts the confirmation text,
|
193
|
+
* and the function to execute after it has been run */
|
194
|
+
var confirmation = function(button, html, action, delay) {
|
195
|
+
var obj = $(button);
|
196
|
+
var original = obj.html();
|
197
|
+
var timeout = setTimeout(function() {
|
198
|
+
obj.html(original).unbind('click').click(function() {
|
199
|
+
confirmation(button, html, action, delay);
|
200
|
+
});
|
201
|
+
}, delay || 3000);
|
202
|
+
obj.removeAttr('onclick').html(html).unbind('click').click(function() {
|
203
|
+
clearTimeout(timeout);
|
204
|
+
obj.html(original).unbind('click').click(function() {
|
205
|
+
confirmation(button, html, action, delay);
|
206
|
+
});
|
207
|
+
action();
|
208
|
+
});
|
209
|
+
}
|
210
|
+
|
211
|
+
/* Helper function for adding a tag to a job */
|
212
|
+
var tag = function(jid, tag) {
|
213
|
+
var data = {};
|
214
|
+
data[jid] = [tag];
|
215
|
+
// The button group of the 'add tag' bit
|
216
|
+
var group =
|
217
|
+
_ajax({
|
218
|
+
url: '<%= u "/tag" %>',
|
219
|
+
data: data,
|
220
|
+
success : function() {
|
221
|
+
var div = $('<div>').attr('class', 'btn-group').attr('style', 'float:left');
|
222
|
+
var span = $('<span>').attr('class', 'tag').text(tag);
|
223
|
+
var btn = $('<button>').attr('class', 'btn').click(function() {
|
224
|
+
untag(jid, tag);
|
225
|
+
});
|
226
|
+
btn.append($('<i>').attr('class', 'icon-remove'));
|
227
|
+
div.append(span).append(btn);
|
228
|
+
$('#job-' + jid).find('.add-tag').val(null).parent().before(div);
|
229
|
+
}, error: function() {
|
230
|
+
flash('Failed to tag ' + jid + ' with ' + tag);
|
231
|
+
}
|
232
|
+
});
|
233
|
+
}
|
234
|
+
|
235
|
+
/* Helper function for untagging a job */
|
236
|
+
var untag = function(jid, tag) {
|
237
|
+
var data = {};
|
238
|
+
data[jid] = [tag];
|
239
|
+
// The button group of the 'add tag' bit
|
240
|
+
var group =
|
241
|
+
_ajax({
|
242
|
+
url: '<%= u "/untag" %>',
|
243
|
+
data: data,
|
244
|
+
success : function() {
|
245
|
+
$("#job-" + jid).find('.tag').filter(function() {
|
246
|
+
return $(this).text() === tag;
|
247
|
+
}).parent().remove();
|
248
|
+
}, error: function() {
|
249
|
+
flash('Failed to untag ' + jid + ' with ' + tag);
|
250
|
+
}
|
251
|
+
});
|
252
|
+
}
|
253
|
+
|
254
|
+
/* Helper function for changing a job's priority */
|
255
|
+
var priority = function(jid, priority) {
|
256
|
+
var p = parseInt(priority);
|
257
|
+
var input = $('#job-' + jid).find('.priority');
|
258
|
+
if (p != null) {
|
259
|
+
input.attr('disabled', true);
|
260
|
+
var data = {};
|
261
|
+
data[jid] = priority;
|
262
|
+
_ajax({
|
263
|
+
url: '<%= u "/priority" %>',
|
264
|
+
data: data,
|
265
|
+
success : function(data) {
|
266
|
+
if (data[jid] != 'failed' && data[jid] != null) {
|
267
|
+
input.attr('disabled', false).attr('placeholder', 'Pri ' + priority).val(null).blur();
|
268
|
+
} else {
|
269
|
+
flash('Couldn\'t reprioritize ' + jid);
|
270
|
+
input.val(null).blur();
|
271
|
+
}
|
272
|
+
}, error: function() {
|
273
|
+
flash('Couldn\'t reprioritize ' + jid);
|
274
|
+
input.val(null).blur();
|
275
|
+
}
|
276
|
+
});
|
277
|
+
} else {
|
278
|
+
// Reset it to its original value, and print an error
|
279
|
+
flash('Cannot derive integer from "' + priority + '"');
|
280
|
+
input.val(null).blur();
|
281
|
+
}
|
282
|
+
}
|
283
|
+
|
284
|
+
var pause = function(queue) {
|
285
|
+
_ajax({
|
286
|
+
url: '<%= u "/pause" %>',
|
287
|
+
data: {
|
288
|
+
'queue': queue
|
289
|
+
}, success: function(data) {
|
290
|
+
var button = $('#' + queue + '-pause');
|
291
|
+
button.attr('title', 'Unpause').attr(
|
292
|
+
'data-original-title', 'Unpause');
|
293
|
+
button.addClass('btn-success').removeClass('btn-warning');
|
294
|
+
button.children().addClass('icon-play').removeClass('icon-pause');
|
295
|
+
button.attr('onclick', 'unpause("' + queue + '")');
|
296
|
+
}, error: function() {
|
297
|
+
flash('Couldn\'t pause queue ' + queue);
|
298
|
+
}
|
299
|
+
})
|
300
|
+
}
|
301
|
+
|
302
|
+
var unpause = function(queue) {
|
303
|
+
_ajax({
|
304
|
+
url: '<%= u "/unpause" %>',
|
305
|
+
data: {
|
306
|
+
'queue': queue
|
307
|
+
}, success: function(data) {
|
308
|
+
var button = $('#' + queue + '-pause');
|
309
|
+
button.attr('title', 'Pause').attr(
|
310
|
+
'data-original-title', 'Pause');
|
311
|
+
button.addClass('btn-warning').removeClass('btn-success');
|
312
|
+
button.children().addClass('icon-pause').removeClass('icon-play');
|
313
|
+
button.attr('onclick', 'pause("' + queue + '")');
|
314
|
+
}, error: function() {
|
315
|
+
flash('Couldn\'t unpause queue ' + queue);
|
316
|
+
}
|
317
|
+
})
|
318
|
+
}
|
319
|
+
|
320
|
+
var timeout = function(jid) {
|
321
|
+
_ajax({
|
322
|
+
url: '<%= u "/timeout" %>',
|
323
|
+
data: {
|
324
|
+
'jid': jid
|
325
|
+
}, success: function(data) {
|
326
|
+
flash('Job timed out', 'success');
|
327
|
+
}, error: function(data) {
|
328
|
+
flash('Failed to time out job: ' + data);
|
329
|
+
console.log(data);
|
330
|
+
}
|
331
|
+
})
|
332
|
+
}
|
333
|
+
|
334
|
+
var expire_throttle = function(throttle_id, expiration) {
|
335
|
+
var data = { 'id': throttle_id, 'expiration': expiration };
|
336
|
+
|
337
|
+
$.ajax({
|
338
|
+
url: '<%= u "/throttle" %>',
|
339
|
+
type: 'PUT',
|
340
|
+
dataType: 'json',
|
341
|
+
processData: false,
|
342
|
+
data: JSON.stringify(data),
|
343
|
+
success: function(data) {
|
344
|
+
flash('Set expiration for throttle ' + throttle_id, 'success');
|
345
|
+
},
|
346
|
+
error: function(data) {
|
347
|
+
flash('Couldn\'t update expiration for throttle ' + throttle_id);
|
348
|
+
}
|
349
|
+
})
|
350
|
+
}
|
351
|
+
|
352
|
+
var delete_throttle = function(throttle_id) {
|
353
|
+
var data = { 'id': throttle_id };
|
354
|
+
|
355
|
+
$.ajax({
|
356
|
+
url: '<%= u "/throttle" %>',
|
357
|
+
type: 'DELETE',
|
358
|
+
dataType: 'json',
|
359
|
+
processData: false,
|
360
|
+
data: JSON.stringify(data),
|
361
|
+
success: function(data) {
|
362
|
+
flash('Deleted throttle for ' + throttle_id, 'success');
|
363
|
+
$('.' + throttle_id.replace(/:/g, '-') + '-maximum').val(data['maximum']);
|
364
|
+
},
|
365
|
+
error: function(data) {
|
366
|
+
flash('Couldn\'t delete thottle ' + throttle_id);
|
367
|
+
}
|
368
|
+
})
|
369
|
+
}
|
370
|
+
|
371
|
+
var update_throttle = function(throttle_id, maximum) {
|
372
|
+
_ajax({
|
373
|
+
url: '<%= u "/throttle" %>',
|
374
|
+
data: {
|
375
|
+
'id': throttle_id,
|
376
|
+
'maximum': maximum
|
377
|
+
}, success: function(data) {
|
378
|
+
flash('Updated throttle for ' + throttle_id, 'success');
|
379
|
+
}, error: function(data) {
|
380
|
+
flash('Couldn\'t update throttle ' + throttle_id);
|
381
|
+
}
|
382
|
+
})
|
383
|
+
}
|
384
|
+
|
385
|
+
$(document).ready(function() {
|
386
|
+
$('button').tooltip({delay:200});
|
387
|
+
});
|
388
|
+
</script>
|
389
|
+
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
|
390
|
+
<!--[if lt IE 9]>
|
391
|
+
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
392
|
+
<![endif]-->
|
393
|
+
</head>
|
394
|
+
|
395
|
+
<body>
|
396
|
+
<div class="navbar navbar-fixed-top">
|
397
|
+
<div class="navbar-inner">
|
398
|
+
<div class="container">
|
399
|
+
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
|
400
|
+
<span class="icon-bar"></span>
|
401
|
+
<span class="icon-bar"></span>
|
402
|
+
<span class="icon-bar"></span>
|
403
|
+
</a>
|
404
|
+
<a class="brand" href="<%= u '/' %>"><%= application_name %></a>
|
405
|
+
<div class="nav-collapse">
|
406
|
+
<ul class="nav nav-bar">
|
407
|
+
<% tabs.each do |tab| %>
|
408
|
+
<li><a href='<%= u tab[:path] %>'><%= tab[:name] %></a></li>
|
409
|
+
<% end %>
|
410
|
+
</ul>
|
411
|
+
<ul class="nav nav-bar pull-right">
|
412
|
+
<li>
|
413
|
+
<form class="navbar-search" action="<%= u '/tag' %>">
|
414
|
+
<input id="tag-search" type="text" class="search-query" placeholder="Search by Tag" data-provide="typeahead" name="tag"/>
|
415
|
+
</form>
|
416
|
+
</li>
|
417
|
+
</ul>
|
418
|
+
</div>
|
419
|
+
</div>
|
420
|
+
</div>
|
421
|
+
</div>
|
422
|
+
|
423
|
+
<div class="container">
|
424
|
+
<%= yield %>
|
425
|
+
<!-- <footer class="footer">
|
426
|
+
<p>Powered by <a href="http://github.com/tdg5/reqless-rb">reqless</a> v<%=Reqless::VERSION%></p>
|
427
|
+
</footer> -->
|
428
|
+
</div> <!-- /container -->
|
429
|
+
|
430
|
+
<!-- Le javascript
|
431
|
+
================================================== -->
|
432
|
+
<script src="<%= u '/js/bootstrap.min.js' %>"></script>
|
433
|
+
<script src="<%= u '/js/bootstrap-tab.js' %>"></script>
|
434
|
+
<script src="<%= u '/js/bootstrap-alert.js' %>"></script>
|
435
|
+
<script src="<%= u '/js/bootstrap-tooltip.js' %>"></script>
|
436
|
+
<script src="<%= u '/js/bootstrap-scrollspy.js' %>"></script>
|
437
|
+
<script src="<%= u '/js/bootstrap-typeahead.js' %>"></script>
|
438
|
+
|
439
|
+
<!-- Noty! This is such a wonderful-looking library, and /exactly/ what I wanted. Thank you so much! -->
|
440
|
+
<script src="<%= u '/js/jquery.noty.js' %>"></script>
|
441
|
+
<!--
|
442
|
+
<script src="../assets/js/bootstrap-transition.js"></script>
|
443
|
+
<script src="../assets/js/bootstrap-modal.js"></script>
|
444
|
+
<script src="../assets/js/bootstrap-dropdown.js"></script>
|
445
|
+
<script src="../assets/js/bootstrap-popover.js"></script>
|
446
|
+
<script src="../assets/js/bootstrap-button.js"></script>
|
447
|
+
<script src="../assets/js/bootstrap-collapse.js"></script>
|
448
|
+
<script src="../assets/js/bootstrap-carousel.js"></script>
|
449
|
+
-->
|
450
|
+
</body>
|
451
|
+
</html>
|
@@ -0,0 +1,137 @@
|
|
1
|
+
<% if queues.empty? %>
|
2
|
+
<div class="page-header">
|
3
|
+
<h1>No Queues <small>I wish I had some queues :-/</small></h1>
|
4
|
+
</div>
|
5
|
+
<% else %>
|
6
|
+
<div class="page-header">
|
7
|
+
<h1>Queues <small>And their job counts</small></h1>
|
8
|
+
</div>
|
9
|
+
|
10
|
+
<table class="table">
|
11
|
+
<thead>
|
12
|
+
<tr>
|
13
|
+
<th></th>
|
14
|
+
<th>running</th>
|
15
|
+
<th>waiting</th>
|
16
|
+
<th>throttled</th>
|
17
|
+
<th>scheduled</th>
|
18
|
+
<th>stalled</th>
|
19
|
+
<th>depends</th>
|
20
|
+
<th>recurring</th>
|
21
|
+
</tr>
|
22
|
+
</thead>
|
23
|
+
<tbody>
|
24
|
+
<% queues.each do |queue| %>
|
25
|
+
<tr class="queue-row">
|
26
|
+
<td class="queue-column large-text">
|
27
|
+
<% if queue['paused'] %>
|
28
|
+
<button
|
29
|
+
id="<%= queue['name'] %>-pause"
|
30
|
+
title="Unpause"
|
31
|
+
class="btn btn-success"
|
32
|
+
onclick="unpause('<%= queue['name'] %>')"><i class="icon-play"></i>
|
33
|
+
</button>
|
34
|
+
<% else %>
|
35
|
+
<button
|
36
|
+
id="<%= queue['name'] %>-pause"
|
37
|
+
title="Pause"
|
38
|
+
class="btn btn-warning"
|
39
|
+
onclick="pause('<%= queue['name'] %>')"><i class="icon-pause"></i>
|
40
|
+
</button>
|
41
|
+
<% end %>
|
42
|
+
<a href="<%= u "/queues/#{CGI::escape(queue['name'])}" %>"><%= queue['name'] %></a>
|
43
|
+
</td>
|
44
|
+
<td><%= queue['running'] %></td>
|
45
|
+
<td><%= queue['waiting'] %></td>
|
46
|
+
<td><%= queue['throttled'] %></td>
|
47
|
+
<td><%= queue['scheduled'] %></td>
|
48
|
+
<td><%= queue['stalled'] %></td>
|
49
|
+
<td><%= queue['depends'] %></td>
|
50
|
+
<td><%= queue['recurring'] %></td>
|
51
|
+
</tr>
|
52
|
+
<% end %>
|
53
|
+
</tbody>
|
54
|
+
</table>
|
55
|
+
<% end %>
|
56
|
+
|
57
|
+
<% if failed.empty? %>
|
58
|
+
<div class="page-header">
|
59
|
+
<h1>No Failed Jobs <small>Clean as a whistle</small></h1>
|
60
|
+
</div>
|
61
|
+
<% else %>
|
62
|
+
<div class="page-header">
|
63
|
+
<h1>Failed Jobs <small>D'oh!</small></h1>
|
64
|
+
</div>
|
65
|
+
|
66
|
+
<table class="table">
|
67
|
+
<thead>
|
68
|
+
<tr>
|
69
|
+
<th>failure</th>
|
70
|
+
<th>count</th>
|
71
|
+
</tr>
|
72
|
+
</thead>
|
73
|
+
<tbody>
|
74
|
+
<% failed.sort_by { |t, count| -count }.each do |t, count| %>
|
75
|
+
<tr class="failed-row">
|
76
|
+
<td class="large-text"><a href="<%= u "/failed/#{t}" %>"><%= t %></a></td>
|
77
|
+
<td><%= count %></td>
|
78
|
+
</tr>
|
79
|
+
<% end %>
|
80
|
+
</tbody>
|
81
|
+
</table>
|
82
|
+
<% end %>
|
83
|
+
|
84
|
+
<% if tracked['jobs'].empty? %>
|
85
|
+
<div class="page-header">
|
86
|
+
<h1>No Tracked Jobs <small>These aren't the droids you're looking for</small></h1>
|
87
|
+
</div>
|
88
|
+
<% else %>
|
89
|
+
<div class="page-header">
|
90
|
+
<h1>Tracked Jobs <small>These <i>are</i> the droids you're looking for</small></h1>
|
91
|
+
</div>
|
92
|
+
<% counts = Hash.new; tracked['jobs'].each { |job| counts[job.state] ||= 0; counts[job.state] += 1 } %>
|
93
|
+
<table class="table">
|
94
|
+
<thead>
|
95
|
+
<tr>
|
96
|
+
<th>state</th>
|
97
|
+
<th>count</th>
|
98
|
+
</tr>
|
99
|
+
</thead>
|
100
|
+
<tbody>
|
101
|
+
<% counts.sort_by { |state, count| - count }.each do |state, count| %>
|
102
|
+
<tr class="tracked-row">
|
103
|
+
<td class="large-text"><a href="<%= u "/track##{state}" %>"><%= state %></a></td>
|
104
|
+
<td><%= count %></td>
|
105
|
+
</tr>
|
106
|
+
<% end %>
|
107
|
+
</tbody>
|
108
|
+
</table>
|
109
|
+
<% end %>
|
110
|
+
|
111
|
+
<% if workers.empty? %>
|
112
|
+
<div class="page-header">
|
113
|
+
<h1>No Workers <small>Nobody's doin' nothin'!</small></h1>
|
114
|
+
</div>
|
115
|
+
<% else %>
|
116
|
+
<div class="page-header">
|
117
|
+
<h1>Current Workers <small>And their job counts</small></h1>
|
118
|
+
</div>
|
119
|
+
<table class="table">
|
120
|
+
<thead>
|
121
|
+
<tr>
|
122
|
+
<th></th>
|
123
|
+
<th>running</th>
|
124
|
+
<th>stalled</th>
|
125
|
+
</tr>
|
126
|
+
</thead>
|
127
|
+
<tbody>
|
128
|
+
<% workers.each do |worker| %>
|
129
|
+
<tr class='worker-row'>
|
130
|
+
<td class="large-text"><a href="<%= u "/workers/#{worker['name']}" %>"><%= worker['name'] %></a></td>
|
131
|
+
<td><%= worker['jobs'] %></td>
|
132
|
+
<td><%= worker['stalled'] %></td>
|
133
|
+
</tr>
|
134
|
+
<% end %>
|
135
|
+
</tbody>
|
136
|
+
</table>
|
137
|
+
<% end %>
|