qless 0.9.3 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +9 -3
- data/README.md +70 -25
- data/Rakefile +125 -9
- data/exe/install_phantomjs +21 -0
- data/lib/qless.rb +115 -76
- data/lib/qless/config.rb +11 -9
- data/lib/qless/failure_formatter.rb +43 -0
- data/lib/qless/job.rb +201 -102
- data/lib/qless/job_reservers/ordered.rb +7 -1
- data/lib/qless/job_reservers/round_robin.rb +16 -6
- data/lib/qless/job_reservers/shuffled_round_robin.rb +9 -2
- data/lib/qless/lua/qless-lib.lua +2463 -0
- data/lib/qless/lua/qless.lua +2012 -0
- data/lib/qless/lua_script.rb +63 -12
- data/lib/qless/middleware/memory_usage_monitor.rb +62 -0
- data/lib/qless/middleware/metriks.rb +45 -0
- data/lib/qless/middleware/redis_reconnect.rb +6 -3
- data/lib/qless/middleware/requeue_exceptions.rb +94 -0
- data/lib/qless/middleware/retry_exceptions.rb +38 -9
- data/lib/qless/middleware/sentry.rb +3 -7
- data/lib/qless/middleware/timeout.rb +64 -0
- data/lib/qless/queue.rb +90 -55
- data/lib/qless/server.rb +177 -130
- data/lib/qless/server/views/_job.erb +33 -15
- data/lib/qless/server/views/completed.erb +11 -0
- data/lib/qless/server/views/layout.erb +70 -11
- data/lib/qless/server/views/overview.erb +93 -53
- data/lib/qless/server/views/queue.erb +9 -8
- data/lib/qless/server/views/queues.erb +18 -1
- data/lib/qless/subscriber.rb +37 -22
- data/lib/qless/tasks.rb +5 -10
- data/lib/qless/test_helpers/worker_helpers.rb +55 -0
- data/lib/qless/version.rb +3 -1
- data/lib/qless/worker.rb +4 -413
- data/lib/qless/worker/base.rb +247 -0
- data/lib/qless/worker/forking.rb +245 -0
- data/lib/qless/worker/serial.rb +41 -0
- metadata +135 -52
- data/lib/qless/qless-core/cancel.lua +0 -101
- data/lib/qless/qless-core/complete.lua +0 -233
- data/lib/qless/qless-core/config.lua +0 -56
- data/lib/qless/qless-core/depends.lua +0 -65
- data/lib/qless/qless-core/deregister_workers.lua +0 -12
- data/lib/qless/qless-core/fail.lua +0 -117
- data/lib/qless/qless-core/failed.lua +0 -83
- data/lib/qless/qless-core/get.lua +0 -37
- data/lib/qless/qless-core/heartbeat.lua +0 -51
- data/lib/qless/qless-core/jobs.lua +0 -41
- data/lib/qless/qless-core/pause.lua +0 -18
- data/lib/qless/qless-core/peek.lua +0 -165
- data/lib/qless/qless-core/pop.lua +0 -314
- data/lib/qless/qless-core/priority.lua +0 -32
- data/lib/qless/qless-core/put.lua +0 -169
- data/lib/qless/qless-core/qless-lib.lua +0 -2354
- data/lib/qless/qless-core/qless.lua +0 -1862
- data/lib/qless/qless-core/queues.lua +0 -58
- data/lib/qless/qless-core/recur.lua +0 -190
- data/lib/qless/qless-core/retry.lua +0 -73
- data/lib/qless/qless-core/stats.lua +0 -92
- data/lib/qless/qless-core/tag.lua +0 -100
- data/lib/qless/qless-core/track.lua +0 -79
- data/lib/qless/qless-core/unfail.lua +0 -54
- data/lib/qless/qless-core/unpause.lua +0 -12
- data/lib/qless/qless-core/workers.lua +0 -69
- data/lib/qless/wait_until.rb +0 -19
@@ -4,13 +4,13 @@
|
|
4
4
|
<div class="row">
|
5
5
|
<div class="span6">
|
6
6
|
<h2 style="text-overflow: ellipsis; white-space: nowrap; overflow: hidden">
|
7
|
-
<a href="<%= u "/jobs/#{job.jid}" %>"><%= job.jid[0..8] %>...</a> | <%= job.klass_name %>
|
7
|
+
<a href="<%= u "/jobs/#{job.jid}" %>" title="<%= job.jid %>"><%= job.jid[0..8] %>...</a> | <span title="<%= job.klass_name %>"><%= job.klass_name %></span>
|
8
8
|
</h2>
|
9
9
|
</div>
|
10
10
|
<div class="span3">
|
11
11
|
<h2 style="text-overflow: ellipsis; white-space: nowrap; overflow: hidden">
|
12
12
|
<strong>
|
13
|
-
| <%= job.state %> / <a href="<%= u "/queues/#{job.queue_name}" %>"><%= job.queue_name %></a><%= job.worker_name.nil? ? "/ #{job.worker_name}" : "" %>
|
13
|
+
| <%= job.state %> / <a href="<%= u "/queues/#{CGI::escape(job.queue_name)}" %>" title="<%= job.queue_name %><%= job.worker_name.nil? ? "/ #{job.worker_name}" : "" %>"><%= job.queue_name %></a><%= job.worker_name.nil? ? "/ #{job.worker_name}" : "" %>
|
14
14
|
</strong>
|
15
15
|
</h2>
|
16
16
|
</div>
|
@@ -20,9 +20,12 @@
|
|
20
20
|
<% if (job.state != "complete") %>
|
21
21
|
<button title="delete" class="btn btn-danger" onclick="confirmation(this, 'Delete?', function() { cancel('<%= job.jid %>', fade) })"><i class="icon-remove"></i></button>
|
22
22
|
<% end %>
|
23
|
+
<% if (job.state == "running") %>
|
24
|
+
<button title="Time out job" class="btn btn-danger" onclick="confirmation(this, 'Time out job?', function() { timeout('<%= job.jid %>') })"><i class="icon-time"></i></button>
|
25
|
+
<% end %>
|
23
26
|
<button title="track" class="btn<%= job.tracked ? " active" : "" %>" data-toggle="button" onclick="$(this).hasClass('active') ? untrack('<%= job.jid %>', fade) : track('<%= job.jid %>', [], fade)"><i class="icon-flag"></i></button>
|
24
27
|
<% if (job.state == 'failed') %>
|
25
|
-
<button title="
|
28
|
+
<button title="requeue" class="btn btn-success" onclick="retry('<%= job.jid %>', fade)"><i class="icon-repeat"></i></button>
|
26
29
|
<% end %>
|
27
30
|
<button title="move" class="btn dropdown-toggle btn-success" data-toggle="dropdown">
|
28
31
|
<i class="caret"></i>
|
@@ -56,7 +59,7 @@
|
|
56
59
|
<div style="float:left; margin-right: 10px"><h3>Dependencies:</h3></div>
|
57
60
|
<% job.dependencies.each do |jid| %>
|
58
61
|
<div class="btn-group" style="float:left; margin-right: 10px" id="<%= sanitize_attr("#{job.jid}-dependson-#{jid}") %>">
|
59
|
-
<button class="btn" onclick="window.open('<%= u "/jobs/#{jid}" %>', '_blank')"><%= jid[0...8] %>...</button>
|
62
|
+
<button class="btn" onclick="window.open('<%= u "/jobs/#{jid}" %>', '_blank')" title="<%= jid %>"><%= jid[0...8] %>...</button>
|
60
63
|
<button class="btn dropdown-toggle" onclick="confirmation(this, 'Undepend?', function() { undepend('<%= job.jid %>', '<%= jid %>', function() { $('#<%= sanitize_attr("#{job.jid}-dependson-#{jid}") %>').remove()} ); })">
|
61
64
|
<i class="icon-remove"></i>
|
62
65
|
</button>
|
@@ -72,7 +75,7 @@
|
|
72
75
|
<div style="float:left; margin-right: 10px"><h3>Dependents:</h3></div>
|
73
76
|
<% job.dependents.each do |jid| %>
|
74
77
|
<div class="btn-group" style="float:left; margin-right: 10px" id="<%= sanitize_attr("#{job.jid}-dependents-#{jid}") %>">
|
75
|
-
<button class="btn" onclick="window.open('<%= u "/jobs/#{jid}" %>', '_blank')"><%= jid[0...8] %>...</button>
|
78
|
+
<button class="btn" onclick="window.open('<%= u "/jobs/#{jid}" %>', '_blank')" title="<%= jid %>"><%= jid[0...8] %>...</button>
|
76
79
|
<button class="btn dropdown-toggle" onclick="confirmation(this, 'Undepend?', function() { undepend('<%= jid %>', '<%= job.jid %>', function() { $('#<%= sanitize_attr("#{job.jid}-dependents-#{jid}") %>').remove()} ); })">
|
77
80
|
<i class="icon-remove"></i>
|
78
81
|
</button>
|
@@ -92,7 +95,7 @@
|
|
92
95
|
</button>
|
93
96
|
</div>
|
94
97
|
<% end %>
|
95
|
-
|
98
|
+
|
96
99
|
<!-- One for adding new tags -->
|
97
100
|
<div class="btn-group" style="float:left">
|
98
101
|
<input class="span1 add-tag" type="text" placeholder="Add Tag" onchange="tag('<%= job.jid %>', $(this).val())"></input>
|
@@ -113,11 +116,26 @@
|
|
113
116
|
<h3><small>History</small></h3>
|
114
117
|
<div style="overflow-y:scroll; height: 200px">
|
115
118
|
<% job.queue_history.reverse.each do |h| %>
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
119
|
+
<% if h['what'] == 'put' %>
|
120
|
+
<pre><strong><%= h['what'] %></strong> at <%= strftime(h['when']) %>
|
121
|
+
in queue <strong><%= h['q'] %></strong></pre>
|
122
|
+
<% elsif h['what'] == 'popped' %>
|
123
|
+
<pre><strong><%= h['what'] %></strong> at <%= strftime(h['when']) %>
|
124
|
+
by <strong><%= h['worker'] %></strong></pre>
|
125
|
+
<% elsif h['what'] == 'done' %>
|
126
|
+
<pre><strong>completed</strong> at <%= strftime(h['when']) %></pre>
|
127
|
+
<% elsif h['what'] == 'failed' %>
|
128
|
+
<% if h['worker'] %>
|
129
|
+
<pre><strong><%= h['what'] %></strong> at <%= strftime(h['when']) %>
|
130
|
+
by <strong><%= h['worker'] %></strong>
|
131
|
+
in group <strong><%= h['group'] %></strong></pre>
|
132
|
+
<% else %>
|
133
|
+
<pre><strong><%= h['what'] %></strong> at <%= strftime(h['when']) %>
|
134
|
+
in group <strong><%= h['group'] %></strong></pre>
|
135
|
+
<% end %>
|
136
|
+
<% else %>
|
137
|
+
<pre><strong><%= h['what'] %></strong> at <%= strftime(h['when']) %></pre>
|
138
|
+
<% end %>
|
121
139
|
<% end %>
|
122
140
|
</div>
|
123
141
|
</div>
|
@@ -144,13 +162,13 @@
|
|
144
162
|
<div class="row">
|
145
163
|
<div class="span6">
|
146
164
|
<h2 style="text-overflow: ellipsis; white-space: nowrap; overflow: hidden">
|
147
|
-
<a href="<%= u "/jobs/#{job.jid}" %>"><%= job.jid[0..8] %>...</a> | <%= job.klass_name %>
|
165
|
+
<a href="<%= u "/jobs/#{job.jid}" %>" title="<%= job.jid %>"><%= job.jid[0..8] %>...</a> | <span title="<%= job.klass_name %>"><%= job.klass_name %></span>
|
148
166
|
</h2>
|
149
167
|
</div>
|
150
168
|
<div class="span3">
|
151
169
|
<h2 style="text-overflow: ellipsis; white-space: nowrap; overflow: hidden">
|
152
170
|
<strong>
|
153
|
-
| recurring / <a href="<%= u "/queues/#{job.queue_name}" %>"><%= job.queue_name %></a>
|
171
|
+
| recurring / <a href="<%= u "/queues/#{CGI::escape(job.queue_name)}" %>" title="<%= job.queue_name %>"><%= job.queue_name %></a>
|
154
172
|
</strong>
|
155
173
|
</h2>
|
156
174
|
</div>
|
@@ -183,7 +201,7 @@
|
|
183
201
|
</div>
|
184
202
|
</div>
|
185
203
|
</div>
|
186
|
-
|
204
|
+
|
187
205
|
<div class="row">
|
188
206
|
<div class="span12 tags" style="margin-bottom: 3px;">
|
189
207
|
<% job.tags.each do |tag| %>
|
@@ -194,7 +212,7 @@
|
|
194
212
|
</button>
|
195
213
|
</div>
|
196
214
|
<% end %>
|
197
|
-
|
215
|
+
|
198
216
|
<!-- One for adding new tags -->
|
199
217
|
<div class="btn-group" style="float:left">
|
200
218
|
<input class="span1 add-tag" type="text" placeholder="Add Tag" onchange="tag('<%= job.jid %>', $(this).val())"></input>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<% if jobs.empty? %>
|
2
|
+
<div class="page-header">
|
3
|
+
<h1>No Completed Jobs<small>(yet)</small></h1>
|
4
|
+
</div>
|
5
|
+
<% else %>
|
6
|
+
<div class="page-header">
|
7
|
+
<h1>Completed Jobs <small>You must be doing something right!</small></h1>
|
8
|
+
</div>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<%= erb :_job_list, :locals => { :jobs => jobs, :queues => queues } %>
|
@@ -12,13 +12,13 @@
|
|
12
12
|
<link href="<%= u '/css/docs.css' %>" rel="stylesheet">
|
13
13
|
<link href="<%= u '/css/jquery.noty.css' %>" rel="stylesheet">
|
14
14
|
<link href="<%= u '/css/noty_theme_twitter.css' %>" rel="stylesheet">
|
15
|
-
<script src="
|
15
|
+
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
|
16
16
|
|
17
17
|
<style type="text/css">
|
18
18
|
body {
|
19
19
|
padding-top: 60px;
|
20
20
|
}
|
21
|
-
|
21
|
+
|
22
22
|
.btn-group span {
|
23
23
|
/* This is ugly. Anyone want to change it? */
|
24
24
|
border-color: #e6e6e6 #e6e6e6 #bfbfbf;
|
@@ -30,7 +30,7 @@
|
|
30
30
|
line-height: 18px;
|
31
31
|
padding: 4px 10px 4px;
|
32
32
|
}
|
33
|
-
|
33
|
+
|
34
34
|
.btn-group input, .btn-group span {
|
35
35
|
position: relative;
|
36
36
|
float: left;
|
@@ -40,7 +40,7 @@
|
|
40
40
|
border-radius: 0;
|
41
41
|
margin-bottom: 0px;
|
42
42
|
}
|
43
|
-
|
43
|
+
|
44
44
|
.btn-group input:first-child, .btn-group span:first-child {
|
45
45
|
margin-left: 0;
|
46
46
|
-webkit-border-top-left-radius: 4px;
|
@@ -50,6 +50,15 @@
|
|
50
50
|
-moz-border-radius-bottomleft: 4px;
|
51
51
|
border-bottom-left-radius: 4px;
|
52
52
|
}
|
53
|
+
|
54
|
+
.large-text {
|
55
|
+
font-size:18px;
|
56
|
+
}
|
57
|
+
|
58
|
+
.queue-column {
|
59
|
+
min-width:300px;
|
60
|
+
}
|
61
|
+
|
53
62
|
</style>
|
54
63
|
|
55
64
|
<script type="text/javascript">
|
@@ -84,7 +93,7 @@
|
|
84
93
|
url: '<%= u "/move" %>',
|
85
94
|
data: {id:jid, queue:queue},
|
86
95
|
success: function() { flash('Moved ' + jid + ' to ' + queue, 'success', 1500); cb(jid, queue); },
|
87
|
-
|
96
|
+
error: function() { flash('Failed to move ' + jid + ' to ' + queue); }
|
88
97
|
});
|
89
98
|
}
|
90
99
|
|
@@ -94,7 +103,7 @@
|
|
94
103
|
url: '<%= u "/retry" %>',
|
95
104
|
data: {id:jid},
|
96
105
|
success: function() { flash('Retrying ' + jid, 'success', 1500); if (cb) { cb(jid, 'retry'); } },
|
97
|
-
|
106
|
+
error: function() { flash('Failed to retry ' + jid); }
|
98
107
|
});
|
99
108
|
}
|
100
109
|
|
@@ -198,13 +207,13 @@
|
|
198
207
|
action();
|
199
208
|
});
|
200
209
|
}
|
201
|
-
|
210
|
+
|
202
211
|
/* Helper function for adding a tag to a job */
|
203
212
|
var tag = function(jid, tag) {
|
204
213
|
var data = {};
|
205
214
|
data[jid] = [tag];
|
206
215
|
// The button group of the 'add tag' bit
|
207
|
-
var group =
|
216
|
+
var group =
|
208
217
|
_ajax({
|
209
218
|
url: '<%= u "/tag" %>',
|
210
219
|
data: data,
|
@@ -222,13 +231,13 @@
|
|
222
231
|
}
|
223
232
|
});
|
224
233
|
}
|
225
|
-
|
234
|
+
|
226
235
|
/* Helper function for untagging a job */
|
227
236
|
var untag = function(jid, tag) {
|
228
237
|
var data = {};
|
229
238
|
data[jid] = [tag];
|
230
239
|
// The button group of the 'add tag' bit
|
231
|
-
var group =
|
240
|
+
var group =
|
232
241
|
_ajax({
|
233
242
|
url: '<%= u "/untag" %>',
|
234
243
|
data: data,
|
@@ -241,7 +250,7 @@
|
|
241
250
|
}
|
242
251
|
});
|
243
252
|
}
|
244
|
-
|
253
|
+
|
245
254
|
/* Helper function for changing a job's priority */
|
246
255
|
var priority = function(jid, priority) {
|
247
256
|
var p = parseInt(priority);
|
@@ -272,6 +281,56 @@
|
|
272
281
|
}
|
273
282
|
}
|
274
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
|
+
|
275
334
|
$(document).ready(function() {
|
276
335
|
$('button').tooltip({delay:200});
|
277
336
|
});
|
@@ -7,23 +7,49 @@
|
|
7
7
|
<h1>Queues <small>And their job counts</small></h1>
|
8
8
|
</div>
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
10
|
+
<table class="table">
|
11
|
+
<thead>
|
12
|
+
<tr>
|
13
|
+
<th></th>
|
14
|
+
<th>running</th>
|
15
|
+
<th>waiting</th>
|
16
|
+
<th>scheduled</th>
|
17
|
+
<th>stalled</th>
|
18
|
+
<th>depends</th>
|
19
|
+
<th>recurring</th>
|
20
|
+
</tr>
|
21
|
+
</thead>
|
22
|
+
<tbody>
|
23
|
+
<% queues.each do |queue| %>
|
24
|
+
<tr class="queue-row">
|
25
|
+
<td class="queue-column large-text">
|
26
|
+
<% if queue['paused'] %>
|
27
|
+
<button
|
28
|
+
id="<%= queue['name'] %>-pause"
|
29
|
+
title="Unpause"
|
30
|
+
class="btn btn-success"
|
31
|
+
onclick="unpause('<%= queue['name'] %>')"><i class="icon-play"></i>
|
32
|
+
</button>
|
33
|
+
<% else %>
|
34
|
+
<button
|
35
|
+
id="<%= queue['name'] %>-pause"
|
36
|
+
title="Pause"
|
37
|
+
class="btn btn-warning"
|
38
|
+
onclick="pause('<%= queue['name'] %>')"><i class="icon-pause"></i>
|
39
|
+
</button>
|
40
|
+
<% end %>
|
41
|
+
<a href="<%= u "/queues/#{CGI::escape(queue['name'])}" %>"><%= queue['name'] %></a>
|
42
|
+
</td>
|
43
|
+
<td><%= queue['running'] %></td>
|
44
|
+
<td><%= queue['waiting'] %></td>
|
45
|
+
<td><%= queue['scheduled'] %></td>
|
46
|
+
<td><%= queue['stalled'] %></td>
|
47
|
+
<td><%= queue['depends'] %></td>
|
48
|
+
<td><%= queue['recurring'] %></td>
|
49
|
+
</tr>
|
26
50
|
<% end %>
|
51
|
+
</tbody>
|
52
|
+
</table>
|
27
53
|
<% end %>
|
28
54
|
|
29
55
|
<% if failed.empty? %>
|
@@ -34,22 +60,23 @@
|
|
34
60
|
<div class="page-header">
|
35
61
|
<h1>Failed Jobs <small>D'oh!</small></h1>
|
36
62
|
</div>
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
<
|
41
|
-
<
|
42
|
-
|
43
|
-
|
44
|
-
</
|
45
|
-
<
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
63
|
+
|
64
|
+
<table class="table">
|
65
|
+
<thead>
|
66
|
+
<tr>
|
67
|
+
<th>failure</th>
|
68
|
+
<th>count</th>
|
69
|
+
</tr>
|
70
|
+
</thead>
|
71
|
+
<tbody>
|
72
|
+
<% failed.sort_by { |t, count| -count }.each do |t, count| %>
|
73
|
+
<tr class="failed-row">
|
74
|
+
<td class="large-text"><a href="<%= u "/failed/#{t}" %>"><%= t %></a></td>
|
75
|
+
<td><%= count %></td>
|
76
|
+
</tr>
|
77
|
+
<% end %>
|
78
|
+
</tbody>
|
79
|
+
</table>
|
53
80
|
<% end %>
|
54
81
|
|
55
82
|
<% if tracked['jobs'].empty? %>
|
@@ -61,16 +88,22 @@
|
|
61
88
|
<h1>Tracked Jobs <small>These <i>are</i> the droids you're looking for</small></h1>
|
62
89
|
</div>
|
63
90
|
<% counts = Hash.new; tracked['jobs'].each { |job| counts[job.state] ||= 0; counts[job.state] += 1 } %>
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
91
|
+
<table class="table">
|
92
|
+
<thead>
|
93
|
+
<tr>
|
94
|
+
<th>state</th>
|
95
|
+
<th>count</th>
|
96
|
+
</tr>
|
97
|
+
</thead>
|
98
|
+
<tbody>
|
99
|
+
<% counts.sort_by { |state, count| - count }.each do |state, count| %>
|
100
|
+
<tr class="tracked-row">
|
101
|
+
<td class="large-text"><a href="<%= u "/track##{state}" %>"><%= state %></a></td>
|
102
|
+
<td><%= count %></td>
|
103
|
+
</tr>
|
104
|
+
<% end %>
|
105
|
+
</tbody>
|
106
|
+
</table>
|
74
107
|
<% end %>
|
75
108
|
|
76
109
|
<% if workers.empty? %>
|
@@ -81,15 +114,22 @@
|
|
81
114
|
<div class="page-header">
|
82
115
|
<h1>Current Workers <small>And their job counts</small></h1>
|
83
116
|
</div>
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
117
|
+
<table class="table">
|
118
|
+
<thead>
|
119
|
+
<tr>
|
120
|
+
<th></th>
|
121
|
+
<th>running</th>
|
122
|
+
<th>stalled</th>
|
123
|
+
</tr>
|
124
|
+
</thead>
|
125
|
+
<tbody>
|
126
|
+
<% workers.each do |worker| %>
|
127
|
+
<tr class='worker-row'>
|
128
|
+
<td class="large-text"><a href="<%= u "/workers/#{worker['name']}" %>"><%= worker['name'] %></a></td>
|
129
|
+
<td><%= worker['jobs'] %></td>
|
130
|
+
<td><%= worker['stalled'] %></td>
|
131
|
+
</tr>
|
132
|
+
<% end %>
|
133
|
+
</tbody>
|
134
|
+
</table>
|
95
135
|
<% end %>
|