qless 0.9.3 → 0.10.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/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 %>
|