sidekiq-undertaker 1.1.0 → 1.3.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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby-build.yml +1 -1
- data/CHANGELOG.md +104 -0
- data/README.md +7 -4
- data/assets/Undertaker_demo_1_job_1_error.png +0 -0
- data/assets/Undertaker_demo_1_job_all_errors.png +0 -0
- data/assets/Undertaker_demo_all_errors.png +0 -0
- data/assets/Undertaker_demo_all_jobs.png +0 -0
- data/assets/Undertaker_demo_all_jobs_1_error.png +0 -0
- data/lib/sidekiq/undertaker/version.rb +1 -1
- data/lib/sidekiq/undertaker/web_extension/api_helpers.rb +69 -12
- data/lib/sidekiq/undertaker/web_extension.rb +8 -1
- data/sidekiq-undertaker.gemspec +3 -1
- data/spec/fixtures/approvals/sidekiq_undertaker_webextension/show_filter/when_filter_page_is_called/behaves_like_a_page/the_displayed_page_is_correct_for_sidekiqv6.approved.txt +29 -15
- data/spec/fixtures/approvals/sidekiq_undertaker_webextension/show_filter/when_job_classbucket_page_is_called/behaves_like_a_page/the_displayed_page_is_correct_for_sidekiqv6.approved.txt +13 -15
- data/spec/fixtures/approvals/sidekiq_undertaker_webextension/show_filter/when_job_classbucket_page_is_polled/behaves_like_a_page/the_displayed_page_is_correct_for_sidekiqv6.approved.txt +13 -15
- data/spec/fixtures/approvals/sidekiq_undertaker_webextension/show_morgue/when_job_classerrorbucket_is_called/with_all_failures_and_errors/behaves_like_a_page/the_displayed_page_is_correct_for_sidekiqv6.approved.txt +19 -15
- data/spec/fixtures/approvals/sidekiq_undertaker_webextension/show_morgue/when_job_classerrorbucket_is_called/with_specific_job_class_and_a_specific_error/behaves_like_a_page/the_displayed_page_is_correct_for_sidekiqv6.approved.txt +19 -15
- data/spec/fixtures/approvals/sidekiq_undertaker_webextension/show_morgue/when_job_classerrorbucket_is_called/with_specific_job_class_and_a_specific_error/with_pagination/behaves_like_a_page/the_displayed_page_is_correct_for_sidekiqv6.approved.txt +19 -15
- data/spec/sidekiq/undertaker/job_distributor_spec.rb +3 -3
- data/spec/sidekiq/undertaker/job_filter_spec.rb +3 -3
- data/spec/sidekiq/undertaker/web_extension_spec.rb +115 -0
- data/web/locales/en.yml +2 -0
- data/web/views/filter.erb +16 -0
- data/web/views/morgue.erb +6 -0
- metadata +31 -14
- data/Demo_Filter.png +0 -0
- data/Demo_Job_Filter.png +0 -0
- data/Demo_Morgue_1_Job.png +0 -0
- data/Demo_Morgue_all.png +0 -0
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
<meta name="google" content="notranslate" />
|
|
19
19
|
|
|
20
20
|
</head>
|
|
21
|
-
<body class="admin" data-
|
|
21
|
+
<body class="admin" data-locale="en">
|
|
22
22
|
<div class="navbar navbar-default navbar-fixed-top">
|
|
23
23
|
<div class="container-fluid">
|
|
24
24
|
<div class="navbar-header" data-navbar="static">
|
|
@@ -29,9 +29,8 @@
|
|
|
29
29
|
</button>
|
|
30
30
|
<div class="navbar-toggle collapsed navbar-livereload">
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
<a
|
|
34
|
-
|
|
32
|
+
<a class="live-poll-start live-poll btn btn-primary">Live Poll</a>
|
|
33
|
+
<a class="live-poll-stop live-poll btn btn-primary active">Stop Polling</a>
|
|
35
34
|
|
|
36
35
|
|
|
37
36
|
|
|
@@ -95,9 +94,8 @@
|
|
|
95
94
|
<li class="navbar-livereload">
|
|
96
95
|
<div class="poll-wrapper">
|
|
97
96
|
|
|
98
|
-
|
|
99
|
-
<a
|
|
100
|
-
|
|
97
|
+
<a class="live-poll-start live-poll btn btn-primary">Live Poll</a>
|
|
98
|
+
<a class="live-poll-stop live-poll btn btn-primary active">Stop Polling</a>
|
|
101
99
|
|
|
102
100
|
|
|
103
101
|
|
|
@@ -114,40 +112,40 @@
|
|
|
114
112
|
<div class="col-sm-12 summary_bar">
|
|
115
113
|
<ul class="list-unstyled summary row">
|
|
116
114
|
<li class="processed col-sm-1">
|
|
117
|
-
<span class="count">0</span>
|
|
115
|
+
<span id="txtProcessed" class="count">0</span>
|
|
118
116
|
<span class="desc">Processed</span>
|
|
119
117
|
</li>
|
|
120
118
|
<li class="failed col-sm-1">
|
|
121
|
-
<span class="count">0</span>
|
|
119
|
+
<span id="txtFailed" class="count">0</span>
|
|
122
120
|
<span class="desc">Failed</span>
|
|
123
121
|
</li>
|
|
124
122
|
<li class="busy col-sm-1">
|
|
125
123
|
<a href="/sidekiq/busy">
|
|
126
|
-
<span class="count">0</span>
|
|
124
|
+
<span id="txtBusy" class="count">0</span>
|
|
127
125
|
<span class="desc">Busy</span>
|
|
128
126
|
</a>
|
|
129
127
|
</li>
|
|
130
128
|
<li class="enqueued col-sm-1">
|
|
131
129
|
<a href="/sidekiq/queues">
|
|
132
|
-
<span class="count">0</span>
|
|
130
|
+
<span id="txtEnqueued" class="count">0</span>
|
|
133
131
|
<span class="desc">Enqueued</span>
|
|
134
132
|
</a>
|
|
135
133
|
</li>
|
|
136
134
|
<li class="retries col-sm-1">
|
|
137
135
|
<a href="/sidekiq/retries">
|
|
138
|
-
<span class="count">0</span>
|
|
136
|
+
<span id="txtRetries" class="count">0</span>
|
|
139
137
|
<span class="desc">Retries</span>
|
|
140
138
|
</a>
|
|
141
139
|
</li>
|
|
142
140
|
<li class="scheduled col-sm-1">
|
|
143
141
|
<a href="/sidekiq/scheduled">
|
|
144
|
-
<span class="count">0</span>
|
|
142
|
+
<span id="txtScheduled" class="count">0</span>
|
|
145
143
|
<span class="desc">Scheduled</span>
|
|
146
144
|
</a>
|
|
147
145
|
</li>
|
|
148
146
|
<li class="dead col-sm-1">
|
|
149
147
|
<a href="/sidekiq/morgue">
|
|
150
|
-
<span class="count">4</span>
|
|
148
|
+
<span id="txtDead" class="count">4</span>
|
|
151
149
|
<span class="desc">Dead</span>
|
|
152
150
|
</a>
|
|
153
151
|
</li>
|
|
@@ -278,6 +276,7 @@
|
|
|
278
276
|
|
|
279
277
|
</table>
|
|
280
278
|
<input class="btn btn-primary btn-xs pull-left" type="submit" name="retry" value="Revive" />
|
|
279
|
+
<input class="btn btn-secondary btn-xs pull-left" type="submit" name="export" value="Export" />
|
|
281
280
|
<input class="btn btn-danger btn-xs pull-left" type="submit" name="delete" value="Bury" />
|
|
282
281
|
</form>
|
|
283
282
|
|
|
@@ -286,6 +285,11 @@
|
|
|
286
285
|
<input class="btn btn-danger btn-xs pull-right" type="submit" name="delete" value="Bury All" data-confirm="Are you sure?" />
|
|
287
286
|
</form>
|
|
288
287
|
|
|
288
|
+
<form action="/sidekiq/undertaker/morgue/all/all/total_dead/export" method="post">
|
|
289
|
+
<input type='hidden' name='authenticity_token' value='stubbed-csrf-token'/>
|
|
290
|
+
<input class="btn btn-secondary btn-xs pull-right" type="submit" name="export" value="Export All" />
|
|
291
|
+
</form>
|
|
292
|
+
|
|
289
293
|
<form action="/sidekiq/undertaker/morgue/all/all/total_dead/retry" method="post">
|
|
290
294
|
<input type='hidden' name='authenticity_token' value='stubbed-csrf-token'/>
|
|
291
295
|
<input class="btn btn-danger btn-xs pull-right" type="submit" name="retry" value="Revive All" data-confirm="Are you sure?" />
|
|
@@ -307,7 +311,7 @@
|
|
|
307
311
|
<p class="navbar-text redis-url" title="redis://127.0.0.1:6379/0">redis://127.0.0.1:6379/0</p>
|
|
308
312
|
</li>
|
|
309
313
|
<li>
|
|
310
|
-
<p class="navbar-text server-utc-time">20:57:00 UTC</p>
|
|
314
|
+
<p id="serverUtcTime" class="navbar-text server-utc-time">20:57:00 UTC</p>
|
|
311
315
|
</li>
|
|
312
316
|
<li>
|
|
313
317
|
<p class="navbar-text"><a style="color: gray;" href="https://github.com/mperham/sidekiq/wiki">docs</a></p>
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
<meta name="google" content="notranslate" />
|
|
19
19
|
|
|
20
20
|
</head>
|
|
21
|
-
<body class="admin" data-
|
|
21
|
+
<body class="admin" data-locale="en">
|
|
22
22
|
<div class="navbar navbar-default navbar-fixed-top">
|
|
23
23
|
<div class="container-fluid">
|
|
24
24
|
<div class="navbar-header" data-navbar="static">
|
|
@@ -29,9 +29,8 @@
|
|
|
29
29
|
</button>
|
|
30
30
|
<div class="navbar-toggle collapsed navbar-livereload">
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
<a
|
|
34
|
-
|
|
32
|
+
<a class="live-poll-start live-poll btn btn-primary">Live Poll</a>
|
|
33
|
+
<a class="live-poll-stop live-poll btn btn-primary active">Stop Polling</a>
|
|
35
34
|
|
|
36
35
|
|
|
37
36
|
|
|
@@ -95,9 +94,8 @@
|
|
|
95
94
|
<li class="navbar-livereload">
|
|
96
95
|
<div class="poll-wrapper">
|
|
97
96
|
|
|
98
|
-
|
|
99
|
-
<a
|
|
100
|
-
|
|
97
|
+
<a class="live-poll-start live-poll btn btn-primary">Live Poll</a>
|
|
98
|
+
<a class="live-poll-stop live-poll btn btn-primary active">Stop Polling</a>
|
|
101
99
|
|
|
102
100
|
|
|
103
101
|
|
|
@@ -114,40 +112,40 @@
|
|
|
114
112
|
<div class="col-sm-12 summary_bar">
|
|
115
113
|
<ul class="list-unstyled summary row">
|
|
116
114
|
<li class="processed col-sm-1">
|
|
117
|
-
<span class="count">0</span>
|
|
115
|
+
<span id="txtProcessed" class="count">0</span>
|
|
118
116
|
<span class="desc">Processed</span>
|
|
119
117
|
</li>
|
|
120
118
|
<li class="failed col-sm-1">
|
|
121
|
-
<span class="count">0</span>
|
|
119
|
+
<span id="txtFailed" class="count">0</span>
|
|
122
120
|
<span class="desc">Failed</span>
|
|
123
121
|
</li>
|
|
124
122
|
<li class="busy col-sm-1">
|
|
125
123
|
<a href="/sidekiq/busy">
|
|
126
|
-
<span class="count">0</span>
|
|
124
|
+
<span id="txtBusy" class="count">0</span>
|
|
127
125
|
<span class="desc">Busy</span>
|
|
128
126
|
</a>
|
|
129
127
|
</li>
|
|
130
128
|
<li class="enqueued col-sm-1">
|
|
131
129
|
<a href="/sidekiq/queues">
|
|
132
|
-
<span class="count">0</span>
|
|
130
|
+
<span id="txtEnqueued" class="count">0</span>
|
|
133
131
|
<span class="desc">Enqueued</span>
|
|
134
132
|
</a>
|
|
135
133
|
</li>
|
|
136
134
|
<li class="retries col-sm-1">
|
|
137
135
|
<a href="/sidekiq/retries">
|
|
138
|
-
<span class="count">0</span>
|
|
136
|
+
<span id="txtRetries" class="count">0</span>
|
|
139
137
|
<span class="desc">Retries</span>
|
|
140
138
|
</a>
|
|
141
139
|
</li>
|
|
142
140
|
<li class="scheduled col-sm-1">
|
|
143
141
|
<a href="/sidekiq/scheduled">
|
|
144
|
-
<span class="count">0</span>
|
|
142
|
+
<span id="txtScheduled" class="count">0</span>
|
|
145
143
|
<span class="desc">Scheduled</span>
|
|
146
144
|
</a>
|
|
147
145
|
</li>
|
|
148
146
|
<li class="dead col-sm-1">
|
|
149
147
|
<a href="/sidekiq/morgue">
|
|
150
|
-
<span class="count">4</span>
|
|
148
|
+
<span id="txtDead" class="count">4</span>
|
|
151
149
|
<span class="desc">Dead</span>
|
|
152
150
|
</a>
|
|
153
151
|
</li>
|
|
@@ -236,6 +234,7 @@
|
|
|
236
234
|
|
|
237
235
|
</table>
|
|
238
236
|
<input class="btn btn-primary btn-xs pull-left" type="submit" name="retry" value="Revive" />
|
|
237
|
+
<input class="btn btn-secondary btn-xs pull-left" type="submit" name="export" value="Export" />
|
|
239
238
|
<input class="btn btn-danger btn-xs pull-left" type="submit" name="delete" value="Bury" />
|
|
240
239
|
</form>
|
|
241
240
|
|
|
@@ -244,6 +243,11 @@
|
|
|
244
243
|
<input class="btn btn-danger btn-xs pull-right" type="submit" name="delete" value="Bury All" data-confirm="Are you sure?" />
|
|
245
244
|
</form>
|
|
246
245
|
|
|
246
|
+
<form action="/sidekiq/undertaker/morgue/HardWorker/RuntimeError/1_hour/export" method="post">
|
|
247
|
+
<input type='hidden' name='authenticity_token' value='stubbed-csrf-token'/>
|
|
248
|
+
<input class="btn btn-secondary btn-xs pull-right" type="submit" name="export" value="Export All" />
|
|
249
|
+
</form>
|
|
250
|
+
|
|
247
251
|
<form action="/sidekiq/undertaker/morgue/HardWorker/RuntimeError/1_hour/retry" method="post">
|
|
248
252
|
<input type='hidden' name='authenticity_token' value='stubbed-csrf-token'/>
|
|
249
253
|
<input class="btn btn-danger btn-xs pull-right" type="submit" name="retry" value="Revive All" data-confirm="Are you sure?" />
|
|
@@ -265,7 +269,7 @@
|
|
|
265
269
|
<p class="navbar-text redis-url" title="redis://127.0.0.1:6379/0">redis://127.0.0.1:6379/0</p>
|
|
266
270
|
</li>
|
|
267
271
|
<li>
|
|
268
|
-
<p class="navbar-text server-utc-time">20:57:00 UTC</p>
|
|
272
|
+
<p id="serverUtcTime" class="navbar-text server-utc-time">20:57:00 UTC</p>
|
|
269
273
|
</li>
|
|
270
274
|
<li>
|
|
271
275
|
<p class="navbar-text"><a style="color: gray;" href="https://github.com/mperham/sidekiq/wiki">docs</a></p>
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
<meta name="google" content="notranslate" />
|
|
19
19
|
|
|
20
20
|
</head>
|
|
21
|
-
<body class="admin" data-
|
|
21
|
+
<body class="admin" data-locale="en">
|
|
22
22
|
<div class="navbar navbar-default navbar-fixed-top">
|
|
23
23
|
<div class="container-fluid">
|
|
24
24
|
<div class="navbar-header" data-navbar="static">
|
|
@@ -29,9 +29,8 @@
|
|
|
29
29
|
</button>
|
|
30
30
|
<div class="navbar-toggle collapsed navbar-livereload">
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
<a
|
|
34
|
-
|
|
32
|
+
<a class="live-poll-start live-poll btn btn-primary">Live Poll</a>
|
|
33
|
+
<a class="live-poll-stop live-poll btn btn-primary active">Stop Polling</a>
|
|
35
34
|
|
|
36
35
|
|
|
37
36
|
|
|
@@ -95,9 +94,8 @@
|
|
|
95
94
|
<li class="navbar-livereload">
|
|
96
95
|
<div class="poll-wrapper">
|
|
97
96
|
|
|
98
|
-
|
|
99
|
-
<a
|
|
100
|
-
|
|
97
|
+
<a class="live-poll-start live-poll btn btn-primary">Live Poll</a>
|
|
98
|
+
<a class="live-poll-stop live-poll btn btn-primary active">Stop Polling</a>
|
|
101
99
|
|
|
102
100
|
|
|
103
101
|
|
|
@@ -114,40 +112,40 @@
|
|
|
114
112
|
<div class="col-sm-12 summary_bar">
|
|
115
113
|
<ul class="list-unstyled summary row">
|
|
116
114
|
<li class="processed col-sm-1">
|
|
117
|
-
<span class="count">0</span>
|
|
115
|
+
<span id="txtProcessed" class="count">0</span>
|
|
118
116
|
<span class="desc">Processed</span>
|
|
119
117
|
</li>
|
|
120
118
|
<li class="failed col-sm-1">
|
|
121
|
-
<span class="count">0</span>
|
|
119
|
+
<span id="txtFailed" class="count">0</span>
|
|
122
120
|
<span class="desc">Failed</span>
|
|
123
121
|
</li>
|
|
124
122
|
<li class="busy col-sm-1">
|
|
125
123
|
<a href="/sidekiq/busy">
|
|
126
|
-
<span class="count">0</span>
|
|
124
|
+
<span id="txtBusy" class="count">0</span>
|
|
127
125
|
<span class="desc">Busy</span>
|
|
128
126
|
</a>
|
|
129
127
|
</li>
|
|
130
128
|
<li class="enqueued col-sm-1">
|
|
131
129
|
<a href="/sidekiq/queues">
|
|
132
|
-
<span class="count">0</span>
|
|
130
|
+
<span id="txtEnqueued" class="count">0</span>
|
|
133
131
|
<span class="desc">Enqueued</span>
|
|
134
132
|
</a>
|
|
135
133
|
</li>
|
|
136
134
|
<li class="retries col-sm-1">
|
|
137
135
|
<a href="/sidekiq/retries">
|
|
138
|
-
<span class="count">0</span>
|
|
136
|
+
<span id="txtRetries" class="count">0</span>
|
|
139
137
|
<span class="desc">Retries</span>
|
|
140
138
|
</a>
|
|
141
139
|
</li>
|
|
142
140
|
<li class="scheduled col-sm-1">
|
|
143
141
|
<a href="/sidekiq/scheduled">
|
|
144
|
-
<span class="count">0</span>
|
|
142
|
+
<span id="txtScheduled" class="count">0</span>
|
|
145
143
|
<span class="desc">Scheduled</span>
|
|
146
144
|
</a>
|
|
147
145
|
</li>
|
|
148
146
|
<li class="dead col-sm-1">
|
|
149
147
|
<a href="/sidekiq/morgue">
|
|
150
|
-
<span class="count">54</span>
|
|
148
|
+
<span id="txtDead" class="count">54</span>
|
|
151
149
|
<span class="desc">Dead</span>
|
|
152
150
|
</a>
|
|
153
151
|
</li>
|
|
@@ -1262,6 +1260,7 @@
|
|
|
1262
1260
|
|
|
1263
1261
|
</table>
|
|
1264
1262
|
<input class="btn btn-primary btn-xs pull-left" type="submit" name="retry" value="Revive" />
|
|
1263
|
+
<input class="btn btn-secondary btn-xs pull-left" type="submit" name="export" value="Export" />
|
|
1265
1264
|
<input class="btn btn-danger btn-xs pull-left" type="submit" name="delete" value="Bury" />
|
|
1266
1265
|
</form>
|
|
1267
1266
|
|
|
@@ -1270,6 +1269,11 @@
|
|
|
1270
1269
|
<input class="btn btn-danger btn-xs pull-right" type="submit" name="delete" value="Bury All" data-confirm="Are you sure?" />
|
|
1271
1270
|
</form>
|
|
1272
1271
|
|
|
1272
|
+
<form action="/sidekiq/undertaker/morgue/HardWorker/RuntimeError/1_hour/export" method="post">
|
|
1273
|
+
<input type='hidden' name='authenticity_token' value='stubbed-csrf-token'/>
|
|
1274
|
+
<input class="btn btn-secondary btn-xs pull-right" type="submit" name="export" value="Export All" />
|
|
1275
|
+
</form>
|
|
1276
|
+
|
|
1273
1277
|
<form action="/sidekiq/undertaker/morgue/HardWorker/RuntimeError/1_hour/retry" method="post">
|
|
1274
1278
|
<input type='hidden' name='authenticity_token' value='stubbed-csrf-token'/>
|
|
1275
1279
|
<input class="btn btn-danger btn-xs pull-right" type="submit" name="retry" value="Revive All" data-confirm="Are you sure?" />
|
|
@@ -1291,7 +1295,7 @@
|
|
|
1291
1295
|
<p class="navbar-text redis-url" title="redis://127.0.0.1:6379/0">redis://127.0.0.1:6379/0</p>
|
|
1292
1296
|
</li>
|
|
1293
1297
|
<li>
|
|
1294
|
-
<p class="navbar-text server-utc-time">20:57:00 UTC</p>
|
|
1298
|
+
<p id="serverUtcTime" class="navbar-text server-utc-time">20:57:00 UTC</p>
|
|
1295
1299
|
</li>
|
|
1296
1300
|
<li>
|
|
1297
1301
|
<p class="navbar-text"><a style="color: gray;" href="https://github.com/mperham/sidekiq/wiki">docs</a></p>
|
|
@@ -45,21 +45,21 @@ module Sidekiq
|
|
|
45
45
|
let(:dead_job2) do
|
|
46
46
|
DeadJob.new(
|
|
47
47
|
job: job2, # 'A', 'E1'
|
|
48
|
-
time_elapsed_since_failure: 10 + 60 * 60,
|
|
48
|
+
time_elapsed_since_failure: 10 + (60 * 60),
|
|
49
49
|
bucket_name: "3_hours"
|
|
50
50
|
)
|
|
51
51
|
end
|
|
52
52
|
let(:dead_job3) do
|
|
53
53
|
DeadJob.new(
|
|
54
54
|
job: job3, # 'B', 'E1'
|
|
55
|
-
time_elapsed_since_failure: 10 + 60 * 60,
|
|
55
|
+
time_elapsed_since_failure: 10 + (60 * 60),
|
|
56
56
|
bucket_name: "3_hours"
|
|
57
57
|
)
|
|
58
58
|
end
|
|
59
59
|
let(:dead_job4) do
|
|
60
60
|
DeadJob.new(
|
|
61
61
|
job: job4, # 'B', 'E2'
|
|
62
|
-
time_elapsed_since_failure: 10 + 60 * 60 * 24,
|
|
62
|
+
time_elapsed_since_failure: 10 + (60 * 60 * 24),
|
|
63
63
|
bucket_name: "1_day"
|
|
64
64
|
)
|
|
65
65
|
end
|
|
@@ -9,7 +9,7 @@ module Sidekiq
|
|
|
9
9
|
let(:job1) do
|
|
10
10
|
instance_double(Sidekiq::JobRecord, item: {
|
|
11
11
|
"class" => "HardWorkTask",
|
|
12
|
-
"failed_at" => Time.now.to_i - 5 * 60,
|
|
12
|
+
"failed_at" => Time.now.to_i - (5 * 60),
|
|
13
13
|
"error_class" => "NoMethodError"
|
|
14
14
|
})
|
|
15
15
|
end
|
|
@@ -17,7 +17,7 @@ module Sidekiq
|
|
|
17
17
|
let(:job2) do
|
|
18
18
|
instance_double(Sidekiq::JobRecord, item: {
|
|
19
19
|
"class" => "HardWorkTask",
|
|
20
|
-
"failed_at" => Time.now.to_i - 2 * 60 * 60,
|
|
20
|
+
"failed_at" => Time.now.to_i - (2 * 60 * 60),
|
|
21
21
|
"error_class" => "RandomError"
|
|
22
22
|
})
|
|
23
23
|
end
|
|
@@ -25,7 +25,7 @@ module Sidekiq
|
|
|
25
25
|
let(:job3) do
|
|
26
26
|
instance_double(Sidekiq::JobRecord, item: {
|
|
27
27
|
"class" => "LazyWorkTask",
|
|
28
|
-
"failed_at" => Time.now.to_i - 2 * 60 * 60,
|
|
28
|
+
"failed_at" => Time.now.to_i - (2 * 60 * 60),
|
|
29
29
|
"error_class" => "NoMethodError"
|
|
30
30
|
})
|
|
31
31
|
end
|
|
@@ -6,6 +6,7 @@ require "sidekiq/api"
|
|
|
6
6
|
require "sidekiq/web"
|
|
7
7
|
require "sinatra"
|
|
8
8
|
require "rack/test"
|
|
9
|
+
require "stringio"
|
|
9
10
|
|
|
10
11
|
module Sidekiq
|
|
11
12
|
# rubocop:disable Metrics/ModuleLength
|
|
@@ -205,6 +206,67 @@ module Sidekiq
|
|
|
205
206
|
end
|
|
206
207
|
end
|
|
207
208
|
|
|
209
|
+
describe "import" do
|
|
210
|
+
subject { post "/undertaker/import_jobs", "upload_file" => file }
|
|
211
|
+
|
|
212
|
+
let(:file) do
|
|
213
|
+
Rack::Test::UploadedFile.new(StringIO.new(file_content), file_content_type, original_filename: file_name)
|
|
214
|
+
end
|
|
215
|
+
let(:job) do
|
|
216
|
+
opts = default_job_opts.merge({ "class" => "SuperHardWorking" })
|
|
217
|
+
|
|
218
|
+
build_job(opts)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
context "when the file is valid" do
|
|
222
|
+
let(:file_content) { [job.item].to_json }
|
|
223
|
+
let(:file_name) { "jobs.json" }
|
|
224
|
+
let(:file_content_type) { "application/json" }
|
|
225
|
+
|
|
226
|
+
it "redirects the response" do
|
|
227
|
+
subject
|
|
228
|
+
expect(last_response.status).to eq 302
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
it "adds the jobs to the deadset" do
|
|
232
|
+
expect { subject }.to change { Sidekiq::DeadSet.new.size }.from(4).to(5)
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
context "when the file type is not valid" do
|
|
237
|
+
let(:file_content) { "" }
|
|
238
|
+
let(:file_name) { "jobs.zip" }
|
|
239
|
+
let(:file_content_type) { "application/zip" }
|
|
240
|
+
|
|
241
|
+
it "returns status 400" do
|
|
242
|
+
subject
|
|
243
|
+
expect(last_response.status).to eq 400
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
context "when the file type is a json but not a Sidekiq Job" do
|
|
248
|
+
let(:file_content) { "{am_i_a_job: \"no\"}" }
|
|
249
|
+
let(:file_name) { "jobs.json" }
|
|
250
|
+
let(:file_content_type) { "application/json" }
|
|
251
|
+
|
|
252
|
+
it "returns status 400" do
|
|
253
|
+
subject
|
|
254
|
+
expect(last_response.status).to eq 400
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
context "when the content of the file is not a json" do
|
|
259
|
+
let(:file_content) { "DEFINETLY NOT A JSON" }
|
|
260
|
+
let(:file_name) { "jobs.json" }
|
|
261
|
+
let(:file_content_type) { "application/json" }
|
|
262
|
+
|
|
263
|
+
it "returns status 400" do
|
|
264
|
+
subject
|
|
265
|
+
expect(last_response.status).to eq 400
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
|
|
208
270
|
describe "retry" do
|
|
209
271
|
context "when job class, error and bucket are given" do
|
|
210
272
|
subject { post "/undertaker/morgue/HardWorker/RuntimeError/1_hour/retry" }
|
|
@@ -262,6 +324,50 @@ module Sidekiq
|
|
|
262
324
|
end
|
|
263
325
|
end
|
|
264
326
|
|
|
327
|
+
describe "export" do
|
|
328
|
+
context "when job class, error and bucket are given" do
|
|
329
|
+
subject { post "/undertaker/morgue/HardWorker/RuntimeError/1_hour/export" }
|
|
330
|
+
|
|
331
|
+
let(:expected_redirect_url) { "http://example.org/undertaker/morgue/HardWorker/RuntimeError/1_hour" }
|
|
332
|
+
let(:expected_content_disposition_header) { "attachment; filename=\"2018-12-16_20-57.json\"" }
|
|
333
|
+
|
|
334
|
+
let(:params) do
|
|
335
|
+
{ "job_class" => "HardWorker", "error_class" => "RuntimeError", "bucket_name" => "1_hour" }
|
|
336
|
+
end
|
|
337
|
+
let(:dead_jobs_set) { [dead_job1, dead_job2] }
|
|
338
|
+
let(:dead_job1) { Sidekiq::Undertaker::DeadJob.to_dead_job(Sidekiq::DeadSet.new.find_job(jid1)) }
|
|
339
|
+
let(:dead_job2) { Sidekiq::Undertaker::DeadJob.to_dead_job(Sidekiq::DeadSet.new.find_job(jid2)) }
|
|
340
|
+
|
|
341
|
+
before do
|
|
342
|
+
allow(Sidekiq::Undertaker::JobFilter).to receive(:filter_dead_jobs).with(params)
|
|
343
|
+
.and_return(dead_jobs_set)
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
it "exports the dead jobs" do
|
|
347
|
+
subject
|
|
348
|
+
expect(last_response.status).to eq 200
|
|
349
|
+
expect(last_response.content_type).to eq "application/json"
|
|
350
|
+
expect(last_response.headers["Content-Disposition"]).to eq expected_content_disposition_header
|
|
351
|
+
expect(last_response.body).to eq dead_jobs_set.map { |t| t.job.item }.to_json
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
context "when there are more jobs than the current CHUNK_SIZE" do
|
|
355
|
+
before do
|
|
356
|
+
stub_const("Sidekiq::Undertaker::WebExtension::APIHelpers::EXPORT_CHUNK_SIZE", 1)
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
let(:expected_content_disposition_header) { "attachment; filename=\"HardWorker_2018-12-16_20-57.zip\"" }
|
|
360
|
+
|
|
361
|
+
it "exports the dead jobs" do
|
|
362
|
+
subject
|
|
363
|
+
expect(last_response.status).to eq 200
|
|
364
|
+
expect(last_response.content_type).to eq "application/zip"
|
|
365
|
+
expect(last_response.headers["Content-Disposition"]).to eq expected_content_disposition_header
|
|
366
|
+
end
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
|
|
265
371
|
describe "specific jobs" do
|
|
266
372
|
let(:dead_job) { Sidekiq::DeadSet.new.find_job(jid1) }
|
|
267
373
|
|
|
@@ -282,6 +388,15 @@ module Sidekiq
|
|
|
282
388
|
post "/undertaker/morgue", "key[]=#{job_refs[0]}&retry=Retry+Now"
|
|
283
389
|
end
|
|
284
390
|
|
|
391
|
+
it "exports specific dead job now" do
|
|
392
|
+
post "/undertaker/morgue", "key[]=#{job_refs[0]}&export=now"
|
|
393
|
+
|
|
394
|
+
expect(last_response.status).to eq 200
|
|
395
|
+
expect(last_response.content_type).to eq "application/json"
|
|
396
|
+
expect(last_response.headers["Content-Disposition"]).to eq "attachment; filename=\"2018-12-16_20-57.json\""
|
|
397
|
+
expect(last_response.body).to eq [dead_job.item].to_json
|
|
398
|
+
end
|
|
399
|
+
|
|
285
400
|
it "redirects on specific retry post" do
|
|
286
401
|
post("/undertaker/morgue",
|
|
287
402
|
"key[]=#{job_refs[0]}&retry=Retry+Now",
|
data/web/locales/en.yml
CHANGED
data/web/views/filter.erb
CHANGED
|
@@ -32,3 +32,19 @@
|
|
|
32
32
|
</tr>
|
|
33
33
|
<% end %>
|
|
34
34
|
</table>
|
|
35
|
+
|
|
36
|
+
<header class="row header">
|
|
37
|
+
<div class="col-sm-12">
|
|
38
|
+
<h3>
|
|
39
|
+
Import Jobs
|
|
40
|
+
</h3>
|
|
41
|
+
</div>
|
|
42
|
+
</header>
|
|
43
|
+
|
|
44
|
+
<form enctype="multipart/form-data" method="post" action='<%="#{root_path}undertaker/import_jobs"%>'>
|
|
45
|
+
<%= respond_to?(:csrf_tag) && csrf_tag %>
|
|
46
|
+
<input type="file" id=upload_file" name="upload_file" >
|
|
47
|
+
<button class="btn btn-danger" style="margin-top: 10px" type="submit">
|
|
48
|
+
Import
|
|
49
|
+
</button>
|
|
50
|
+
</form>
|
data/web/views/morgue.erb
CHANGED
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
<% end %>
|
|
57
57
|
</table>
|
|
58
58
|
<input class="btn btn-primary btn-xs pull-left" type="submit" name="retry" value="<%= t('UndertakerRevive') %>" />
|
|
59
|
+
<input class="btn btn-secondary btn-xs pull-left" type="submit" name="export" value="<%= t('UndertakerExport') %>" />
|
|
59
60
|
<input class="btn btn-danger btn-xs pull-left" type="submit" name="delete" value="<%= t('UndertakerBury') %>" />
|
|
60
61
|
</form>
|
|
61
62
|
|
|
@@ -64,6 +65,11 @@
|
|
|
64
65
|
<input class="btn btn-danger btn-xs pull-right" type="submit" name="delete" value="<%= t('UndertakerBuryAll') %>" data-confirm="<%= t('AreYouSure') %>" />
|
|
65
66
|
</form>
|
|
66
67
|
|
|
68
|
+
<form action="<%= "#{root_path}undertaker/morgue/#{@req_job_class}/#{@req_error_class}/#{@req_bucket_name}/export" %>" method="post">
|
|
69
|
+
<%= respond_to?(:csrf_tag) && csrf_tag %>
|
|
70
|
+
<input class="btn btn-secondary btn-xs pull-right" type="submit" name="export" value="<%= t('UndertakerExportAll') %>" />
|
|
71
|
+
</form>
|
|
72
|
+
|
|
67
73
|
<form action="<%= "#{root_path}undertaker/morgue/#{@req_job_class}/#{@req_error_class}/#{@req_bucket_name}/retry" %>" method="post">
|
|
68
74
|
<%= respond_to?(:csrf_tag) && csrf_tag %>
|
|
69
75
|
<input class="btn btn-danger btn-xs pull-right" type="submit" name="retry" value="<%= t('UndertakerReviveAll') %>" data-confirm="<%= t('AreYouSure') %>" />
|