sidekiq-undertaker 1.0.0.rc01

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +6 -0
  3. data/.gitignore +22 -0
  4. data/.rubocop.yml +5 -0
  5. data/.rubocop_todo.yml +23 -0
  6. data/.travis.yml +53 -0
  7. data/Demo_Filter.png +0 -0
  8. data/Demo_Job_Filter.png +0 -0
  9. data/Demo_Morgue_1_Job.png +0 -0
  10. data/Demo_Morgue_all.png +0 -0
  11. data/Gemfile +11 -0
  12. data/LICENSE.txt +21 -0
  13. data/README.md +95 -0
  14. data/Rakefile +34 -0
  15. data/lib/sidekiq/undertaker.rb +16 -0
  16. data/lib/sidekiq/undertaker/bucket.rb +29 -0
  17. data/lib/sidekiq/undertaker/dead_job.rb +64 -0
  18. data/lib/sidekiq/undertaker/job_distributor.rb +64 -0
  19. data/lib/sidekiq/undertaker/job_filter.rb +46 -0
  20. data/lib/sidekiq/undertaker/version.rb +7 -0
  21. data/lib/sidekiq/undertaker/web_extension.rb +37 -0
  22. data/lib/sidekiq/undertaker/web_extension/api_helpers.rb +120 -0
  23. data/sidekiq-undertaker.gemspec +55 -0
  24. data/spec/fixtures/approvals/sidekiq_undertaker_webextension/show_filter/when_filter_page_is_called/behaves_like_a_page/the_displayed_page_is_correct.approved.txt +240 -0
  25. data/spec/fixtures/approvals/sidekiq_undertaker_webextension/show_filter/when_job_classbucket_page_is_called/behaves_like_a_page/the_displayed_page_is_correct.approved.txt +241 -0
  26. data/spec/fixtures/approvals/sidekiq_undertaker_webextension/show_filter/when_job_classbucket_page_is_polled/behaves_like_a_page/the_displayed_page_is_correct.approved.txt +241 -0
  27. 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.approved.txt +316 -0
  28. 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.approved.txt +274 -0
  29. data/spec/sidekiq/undertaker/bucket_spec.rb +26 -0
  30. data/spec/sidekiq/undertaker/dead_jobs_spec.rb +90 -0
  31. data/spec/sidekiq/undertaker/job_distributor_spec.rb +104 -0
  32. data/spec/sidekiq/undertaker/job_filter_spec.rb +105 -0
  33. data/spec/sidekiq/undertaker/web_extension_spec.rb +270 -0
  34. data/spec/spec_helper.rb +76 -0
  35. data/web/locales/en.yml +5 -0
  36. data/web/views/filter.erb +34 -0
  37. data/web/views/filter_job_class.erb +35 -0
  38. data/web/views/morgue.erb +75 -0
  39. metadata +378 -0
@@ -0,0 +1,316 @@
1
+ <!doctype html>
2
+ <html dir="ltr">
3
+ <head>
4
+ <title>[TEST] Sidekiq</title>
5
+ <meta charset="utf-8" />
6
+ <meta name="viewport" content="width=device-width,initial-scale=1.0" />
7
+
8
+ <link href="/sidekiq/stylesheets/bootstrap.css" media="screen" rel="stylesheet" type="text/css" />
9
+
10
+
11
+ <link href="/sidekiq/stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" />
12
+
13
+
14
+ <link rel="shortcut icon" type="image/ico" href="/sidekiq/images/favicon.ico" />
15
+ <script type="text/javascript" src="/sidekiq/javascripts/application.js"></script>
16
+ <meta name="google" content="notranslate" />
17
+
18
+ </head>
19
+ <body class="admin" data-poll-path="" data-locale="en">
20
+ <div class="navbar navbar-default navbar-fixed-top">
21
+ <div class="container-fluid">
22
+ <div class="navbar-header" data-navbar="static">
23
+ <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-menu">
24
+ <span class="icon-bar"></span>
25
+ <span class="icon-bar"></span>
26
+ <span class="icon-bar"></span>
27
+ </button>
28
+ <div class="navbar-toggle collapsed navbar-livereload">
29
+
30
+
31
+ <a id="live-poll" class="btn btn-primary" href="/sidekiq/undertaker/morgue/all/all/total_dead?poll=true">Live Poll</a>
32
+
33
+
34
+
35
+
36
+ </div>
37
+ <a class="navbar-brand" href="/sidekiq/">
38
+ Sidekiq
39
+ <span class="status">
40
+ <i class="status-sprite status-idle"></i>
41
+ idle
42
+ </span>
43
+
44
+ </a>
45
+ </div>
46
+
47
+ <div class="collapse navbar-collapse" id="navbar-menu">
48
+ <ul class="nav navbar-nav" data-navbar="static">
49
+
50
+
51
+ <li class="">
52
+ <a href="/sidekiq/">Dashboard</a>
53
+ </li>
54
+
55
+
56
+
57
+ <li class="">
58
+ <a href="/sidekiq/busy">Busy</a>
59
+ </li>
60
+
61
+
62
+
63
+ <li class="">
64
+ <a href="/sidekiq/queues">Queues</a>
65
+ </li>
66
+
67
+
68
+
69
+ <li class="">
70
+ <a href="/sidekiq/retries">Retries</a>
71
+ </li>
72
+
73
+
74
+
75
+ <li class="">
76
+ <a href="/sidekiq/scheduled">Scheduled</a>
77
+ </li>
78
+
79
+
80
+
81
+ <li class="">
82
+ <a href="/sidekiq/morgue">Dead</a>
83
+ </li>
84
+
85
+
86
+
87
+
88
+ <li class="" data-navbar="custom-tab">
89
+ <a href="/sidekiq/undertaker/filter">Undertaker</a>
90
+ </li>
91
+
92
+
93
+ <li class="navbar-livereload">
94
+ <div class="poll-wrapper">
95
+
96
+
97
+ <a id="live-poll" class="btn btn-primary" href="/sidekiq/undertaker/morgue/all/all/total_dead?poll=true">Live Poll</a>
98
+
99
+
100
+
101
+
102
+ </div>
103
+ </li>
104
+ </ul>
105
+ </div>
106
+ </div>
107
+ </div>
108
+
109
+ <div id="page">
110
+ <div class="container">
111
+ <div class="row">
112
+ <div class="col-sm-12 summary_bar">
113
+ <ul class="list-unstyled summary row">
114
+ <li class="processed col-sm-1">
115
+ <span class="count">0</span>
116
+ <span class="desc">Processed</span>
117
+ </li>
118
+ <li class="failed col-sm-1">
119
+ <span class="count">0</span>
120
+ <span class="desc">Failed</span>
121
+ </li>
122
+ <li class="busy col-sm-1">
123
+ <a href="/sidekiq/busy">
124
+ <span class="count">0</span>
125
+ <span class="desc">Busy</span>
126
+ </a>
127
+ </li>
128
+ <li class="enqueued col-sm-1">
129
+ <a href="/sidekiq/queues">
130
+ <span class="count">0</span>
131
+ <span class="desc">Enqueued</span>
132
+ </a>
133
+ </li>
134
+ <li class="retries col-sm-1">
135
+ <a href="/sidekiq/retries">
136
+ <span class="count">0</span>
137
+ <span class="desc">Retries</span>
138
+ </a>
139
+ </li>
140
+ <li class="scheduled col-sm-1">
141
+ <a href="/sidekiq/scheduled">
142
+ <span class="count">0</span>
143
+ <span class="desc">Scheduled</span>
144
+ </a>
145
+ </li>
146
+ <li class="dead col-sm-1">
147
+ <a href="/sidekiq/morgue">
148
+ <span class="count">4</span>
149
+ <span class="desc">Dead</span>
150
+ </a>
151
+ </li>
152
+ </ul>
153
+
154
+ </div>
155
+
156
+ <div class="col-sm-12">
157
+ <header class="row head">
158
+ <div class="col-sm-12">
159
+ <h3>
160
+ <b>4</b> dead jobs
161
+ of <b>all</b> class
162
+ with <b>all</b> exception
163
+ in <b>total_dead</b> bucket
164
+ </h3>
165
+ </div>
166
+ <div class="col-sm-12">
167
+
168
+ </div>
169
+ </header>
170
+
171
+
172
+ <form action="/sidekiq/undertaker/morgue" method="post">
173
+ <input type='hidden' name='authenticity_token' value=''/>
174
+ <table class="table table-striped table-bordered table-white">
175
+ <thead>
176
+ <tr>
177
+ <th width="20px" class="table-checkbox">
178
+ <label>
179
+ <input type="checkbox" class="check_all" />
180
+ </label>
181
+ </th>
182
+ <th width="25%">Last Retry</th>
183
+ <th>Queue</th>
184
+ <th>Job</th>
185
+ <th>Arguments</th>
186
+ <th>Error</th>
187
+ </tr>
188
+ </thead>
189
+
190
+ <tr>
191
+ <td class="table-checkbox">
192
+ <label>
193
+ <input type='checkbox' name='key[]' value='1544993820.0-bfa4a272cdcac8bfac7b9f1a' />
194
+ </label>
195
+ </td>
196
+ <td>
197
+ <a href="/sidekiq/morgue/1544993820.0-bfa4a272cdcac8bfac7b9f1a"><time class="ltr" dir="ltr" title="2018-12-16T20:57:00Z" datetime="2018-12-16T20:57:00Z">2018-12-16 20:57:00 UTC</time></a>
198
+ </td>
199
+ <td>
200
+ <a href="/sidekiq/queues/foo">foo</a>
201
+ </td>
202
+ <td>HardWorker1</td>
203
+ <td>
204
+ <div class="args">&quot;asdf&quot;, 1234</div>
205
+ </td>
206
+ <td>
207
+ <div>NoMethodError: Some fake message</div>
208
+ </td>
209
+ </tr>
210
+
211
+ <tr>
212
+ <td class="table-checkbox">
213
+ <label>
214
+ <input type='checkbox' name='key[]' value='1544993820.0-4416aa76eb8cf03f56a49220' />
215
+ </label>
216
+ </td>
217
+ <td>
218
+ <a href="/sidekiq/morgue/1544993820.0-4416aa76eb8cf03f56a49220"><time class="ltr" dir="ltr" title="2018-12-16T20:57:00Z" datetime="2018-12-16T20:57:00Z">2018-12-16 20:57:00 UTC</time></a>
219
+ </td>
220
+ <td>
221
+ <a href="/sidekiq/queues/foo">foo</a>
222
+ </td>
223
+ <td>HardWorker</td>
224
+ <td>
225
+ <div class="args">&quot;asdf&quot;, 1234</div>
226
+ </td>
227
+ <td>
228
+ <div>RuntimeError: Some fake message</div>
229
+ </td>
230
+ </tr>
231
+
232
+ <tr>
233
+ <td class="table-checkbox">
234
+ <label>
235
+ <input type='checkbox' name='key[]' value='1544993820.0-34e79a46b1956d3a1180767b' />
236
+ </label>
237
+ </td>
238
+ <td>
239
+ <a href="/sidekiq/morgue/1544993820.0-34e79a46b1956d3a1180767b"><time class="ltr" dir="ltr" title="2018-12-16T20:57:00Z" datetime="2018-12-16T20:57:00Z">2018-12-16 20:57:00 UTC</time></a>
240
+ </td>
241
+ <td>
242
+ <a href="/sidekiq/queues/foo">foo</a>
243
+ </td>
244
+ <td>HardWorker</td>
245
+ <td>
246
+ <div class="args">&quot;asdf&quot;, 1234</div>
247
+ </td>
248
+ <td>
249
+ <div>RuntimeError: Some fake message</div>
250
+ </td>
251
+ </tr>
252
+
253
+ <tr>
254
+ <td class="table-checkbox">
255
+ <label>
256
+ <input type='checkbox' name='key[]' value='1544993820.0-8d08674fce759ac75d1a6e75' />
257
+ </label>
258
+ </td>
259
+ <td>
260
+ <a href="/sidekiq/morgue/1544993820.0-8d08674fce759ac75d1a6e75"><time class="ltr" dir="ltr" title="2018-12-16T20:57:00Z" datetime="2018-12-16T20:57:00Z">2018-12-16 20:57:00 UTC</time></a>
261
+ </td>
262
+ <td>
263
+ <a href="/sidekiq/queues/foo">foo</a>
264
+ </td>
265
+ <td>HardWorker</td>
266
+ <td>
267
+ <div class="args">&quot;asdf&quot;, 1234</div>
268
+ </td>
269
+ <td>
270
+ <div>NoMethodError: Some fake message</div>
271
+ </td>
272
+ </tr>
273
+
274
+ </table>
275
+ <input class="btn btn-primary btn-xs pull-left" type="submit" name="retry" value="Revive" />
276
+ <input class="btn btn-danger btn-xs pull-left" type="submit" name="delete" value="Bury" />
277
+ </form>
278
+
279
+ <form action="/sidekiq/undertaker/morgue/all/all/total_dead/delete" method="post">
280
+ <input type='hidden' name='authenticity_token' value=''/>
281
+ <input class="btn btn-danger btn-xs pull-right" type="submit" name="delete" value="Bury All" data-confirm="Are you sure?" />
282
+ </form>
283
+
284
+ <form action="/sidekiq/undertaker/morgue/all/all/total_dead/retry" method="post">
285
+ <input type='hidden' name='authenticity_token' value=''/>
286
+ <input class="btn btn-danger btn-xs pull-right" type="submit" name="retry" value="Revive All" data-confirm="Are you sure?" />
287
+ </form>
288
+
289
+
290
+ </div>
291
+ </div>
292
+ </div>
293
+ </div>
294
+ <div class="navbar navbar-fixed-bottom navbar-inverse ltr">
295
+ <div class="navbar-inner">
296
+ <div class="container text-center">
297
+ <ul class="nav">
298
+ <li>
299
+ <p class="navbar-text product-version">Sidekiq v*EXCLUDED*</p>
300
+ </li>
301
+ <li>
302
+ <p class="navbar-text redis-url" title="redis://127.0.0.1:6379/0">redis://127.0.0.1:6379/0</p>
303
+ </li>
304
+ <li>
305
+ <p class="navbar-text server-utc-time">20:57:00 UTC</p>
306
+ </li>
307
+ <li>
308
+ <p class="navbar-text"><a style="color: gray;" href="https://github.com/mperham/sidekiq/wiki">docs</a></p>
309
+ </li>
310
+ </ul>
311
+ </div>
312
+ </div>
313
+ </div>
314
+
315
+ </body>
316
+ </html>
@@ -0,0 +1,274 @@
1
+ <!doctype html>
2
+ <html dir="ltr">
3
+ <head>
4
+ <title>[TEST] Sidekiq</title>
5
+ <meta charset="utf-8" />
6
+ <meta name="viewport" content="width=device-width,initial-scale=1.0" />
7
+
8
+ <link href="/sidekiq/stylesheets/bootstrap.css" media="screen" rel="stylesheet" type="text/css" />
9
+
10
+
11
+ <link href="/sidekiq/stylesheets/application.css" media="screen" rel="stylesheet" type="text/css" />
12
+
13
+
14
+ <link rel="shortcut icon" type="image/ico" href="/sidekiq/images/favicon.ico" />
15
+ <script type="text/javascript" src="/sidekiq/javascripts/application.js"></script>
16
+ <meta name="google" content="notranslate" />
17
+
18
+ </head>
19
+ <body class="admin" data-poll-path="" data-locale="en">
20
+ <div class="navbar navbar-default navbar-fixed-top">
21
+ <div class="container-fluid">
22
+ <div class="navbar-header" data-navbar="static">
23
+ <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-menu">
24
+ <span class="icon-bar"></span>
25
+ <span class="icon-bar"></span>
26
+ <span class="icon-bar"></span>
27
+ </button>
28
+ <div class="navbar-toggle collapsed navbar-livereload">
29
+
30
+
31
+ <a id="live-poll" class="btn btn-primary" href="/sidekiq/undertaker/morgue/HardWorker/RuntimeError/1_hour?poll=true">Live Poll</a>
32
+
33
+
34
+
35
+
36
+ </div>
37
+ <a class="navbar-brand" href="/sidekiq/">
38
+ Sidekiq
39
+ <span class="status">
40
+ <i class="status-sprite status-idle"></i>
41
+ idle
42
+ </span>
43
+
44
+ </a>
45
+ </div>
46
+
47
+ <div class="collapse navbar-collapse" id="navbar-menu">
48
+ <ul class="nav navbar-nav" data-navbar="static">
49
+
50
+
51
+ <li class="">
52
+ <a href="/sidekiq/">Dashboard</a>
53
+ </li>
54
+
55
+
56
+
57
+ <li class="">
58
+ <a href="/sidekiq/busy">Busy</a>
59
+ </li>
60
+
61
+
62
+
63
+ <li class="">
64
+ <a href="/sidekiq/queues">Queues</a>
65
+ </li>
66
+
67
+
68
+
69
+ <li class="">
70
+ <a href="/sidekiq/retries">Retries</a>
71
+ </li>
72
+
73
+
74
+
75
+ <li class="">
76
+ <a href="/sidekiq/scheduled">Scheduled</a>
77
+ </li>
78
+
79
+
80
+
81
+ <li class="">
82
+ <a href="/sidekiq/morgue">Dead</a>
83
+ </li>
84
+
85
+
86
+
87
+
88
+ <li class="" data-navbar="custom-tab">
89
+ <a href="/sidekiq/undertaker/filter">Undertaker</a>
90
+ </li>
91
+
92
+
93
+ <li class="navbar-livereload">
94
+ <div class="poll-wrapper">
95
+
96
+
97
+ <a id="live-poll" class="btn btn-primary" href="/sidekiq/undertaker/morgue/HardWorker/RuntimeError/1_hour?poll=true">Live Poll</a>
98
+
99
+
100
+
101
+
102
+ </div>
103
+ </li>
104
+ </ul>
105
+ </div>
106
+ </div>
107
+ </div>
108
+
109
+ <div id="page">
110
+ <div class="container">
111
+ <div class="row">
112
+ <div class="col-sm-12 summary_bar">
113
+ <ul class="list-unstyled summary row">
114
+ <li class="processed col-sm-1">
115
+ <span class="count">0</span>
116
+ <span class="desc">Processed</span>
117
+ </li>
118
+ <li class="failed col-sm-1">
119
+ <span class="count">0</span>
120
+ <span class="desc">Failed</span>
121
+ </li>
122
+ <li class="busy col-sm-1">
123
+ <a href="/sidekiq/busy">
124
+ <span class="count">0</span>
125
+ <span class="desc">Busy</span>
126
+ </a>
127
+ </li>
128
+ <li class="enqueued col-sm-1">
129
+ <a href="/sidekiq/queues">
130
+ <span class="count">0</span>
131
+ <span class="desc">Enqueued</span>
132
+ </a>
133
+ </li>
134
+ <li class="retries col-sm-1">
135
+ <a href="/sidekiq/retries">
136
+ <span class="count">0</span>
137
+ <span class="desc">Retries</span>
138
+ </a>
139
+ </li>
140
+ <li class="scheduled col-sm-1">
141
+ <a href="/sidekiq/scheduled">
142
+ <span class="count">0</span>
143
+ <span class="desc">Scheduled</span>
144
+ </a>
145
+ </li>
146
+ <li class="dead col-sm-1">
147
+ <a href="/sidekiq/morgue">
148
+ <span class="count">4</span>
149
+ <span class="desc">Dead</span>
150
+ </a>
151
+ </li>
152
+ </ul>
153
+
154
+ </div>
155
+
156
+ <div class="col-sm-12">
157
+ <header class="row head">
158
+ <div class="col-sm-12">
159
+ <h3>
160
+ <b>2</b> dead jobs
161
+ of <b>HardWorker</b> class
162
+ with <b>RuntimeError</b> exception
163
+ in <b>1_hour</b> bucket
164
+ </h3>
165
+ </div>
166
+ <div class="col-sm-12">
167
+
168
+ </div>
169
+ </header>
170
+
171
+
172
+ <form action="/sidekiq/undertaker/morgue" method="post">
173
+ <input type='hidden' name='authenticity_token' value=''/>
174
+ <table class="table table-striped table-bordered table-white">
175
+ <thead>
176
+ <tr>
177
+ <th width="20px" class="table-checkbox">
178
+ <label>
179
+ <input type="checkbox" class="check_all" />
180
+ </label>
181
+ </th>
182
+ <th width="25%">Last Retry</th>
183
+ <th>Queue</th>
184
+ <th>Job</th>
185
+ <th>Arguments</th>
186
+ <th>Error</th>
187
+ </tr>
188
+ </thead>
189
+
190
+ <tr>
191
+ <td class="table-checkbox">
192
+ <label>
193
+ <input type='checkbox' name='key[]' value='1544993820.0-4416aa76eb8cf03f56a49220' />
194
+ </label>
195
+ </td>
196
+ <td>
197
+ <a href="/sidekiq/morgue/1544993820.0-4416aa76eb8cf03f56a49220"><time class="ltr" dir="ltr" title="2018-12-16T20:57:00Z" datetime="2018-12-16T20:57:00Z">2018-12-16 20:57:00 UTC</time></a>
198
+ </td>
199
+ <td>
200
+ <a href="/sidekiq/queues/foo">foo</a>
201
+ </td>
202
+ <td>HardWorker</td>
203
+ <td>
204
+ <div class="args">&quot;asdf&quot;, 1234</div>
205
+ </td>
206
+ <td>
207
+ <div>RuntimeError: Some fake message</div>
208
+ </td>
209
+ </tr>
210
+
211
+ <tr>
212
+ <td class="table-checkbox">
213
+ <label>
214
+ <input type='checkbox' name='key[]' value='1544993820.0-34e79a46b1956d3a1180767b' />
215
+ </label>
216
+ </td>
217
+ <td>
218
+ <a href="/sidekiq/morgue/1544993820.0-34e79a46b1956d3a1180767b"><time class="ltr" dir="ltr" title="2018-12-16T20:57:00Z" datetime="2018-12-16T20:57:00Z">2018-12-16 20:57:00 UTC</time></a>
219
+ </td>
220
+ <td>
221
+ <a href="/sidekiq/queues/foo">foo</a>
222
+ </td>
223
+ <td>HardWorker</td>
224
+ <td>
225
+ <div class="args">&quot;asdf&quot;, 1234</div>
226
+ </td>
227
+ <td>
228
+ <div>RuntimeError: Some fake message</div>
229
+ </td>
230
+ </tr>
231
+
232
+ </table>
233
+ <input class="btn btn-primary btn-xs pull-left" type="submit" name="retry" value="Revive" />
234
+ <input class="btn btn-danger btn-xs pull-left" type="submit" name="delete" value="Bury" />
235
+ </form>
236
+
237
+ <form action="/sidekiq/undertaker/morgue/HardWorker/RuntimeError/1_hour/delete" method="post">
238
+ <input type='hidden' name='authenticity_token' value=''/>
239
+ <input class="btn btn-danger btn-xs pull-right" type="submit" name="delete" value="Bury All" data-confirm="Are you sure?" />
240
+ </form>
241
+
242
+ <form action="/sidekiq/undertaker/morgue/HardWorker/RuntimeError/1_hour/retry" method="post">
243
+ <input type='hidden' name='authenticity_token' value=''/>
244
+ <input class="btn btn-danger btn-xs pull-right" type="submit" name="retry" value="Revive All" data-confirm="Are you sure?" />
245
+ </form>
246
+
247
+
248
+ </div>
249
+ </div>
250
+ </div>
251
+ </div>
252
+ <div class="navbar navbar-fixed-bottom navbar-inverse ltr">
253
+ <div class="navbar-inner">
254
+ <div class="container text-center">
255
+ <ul class="nav">
256
+ <li>
257
+ <p class="navbar-text product-version">Sidekiq v*EXCLUDED*</p>
258
+ </li>
259
+ <li>
260
+ <p class="navbar-text redis-url" title="redis://127.0.0.1:6379/0">redis://127.0.0.1:6379/0</p>
261
+ </li>
262
+ <li>
263
+ <p class="navbar-text server-utc-time">20:57:00 UTC</p>
264
+ </li>
265
+ <li>
266
+ <p class="navbar-text"><a style="color: gray;" href="https://github.com/mperham/sidekiq/wiki">docs</a></p>
267
+ </li>
268
+ </ul>
269
+ </div>
270
+ </div>
271
+ </div>
272
+
273
+ </body>
274
+ </html>