sidekiq-status 1.1.0 → 2.1.3
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/.gitignore +1 -0
- data/.gitlab-ci.yml +17 -0
- data/.travis.yml +10 -6
- data/Appraisals +6 -6
- data/CHANGELOG.md +27 -59
- data/README.md +17 -24
- data/gemfiles/{sidekiq_4.x.gemfile → sidekiq_6.1.gemfile} +1 -1
- data/gemfiles/{sidekiq_3.x.gemfile → sidekiq_6.x.gemfile} +1 -1
- data/lib/sidekiq-status/client_middleware.rb +4 -2
- data/lib/sidekiq-status/server_middleware.rb +1 -1
- data/lib/sidekiq-status/storage.rb +5 -5
- data/lib/sidekiq-status/version.rb +1 -1
- data/lib/sidekiq-status/web.rb +24 -7
- data/sidekiq-status.gemspec +2 -2
- data/spec/lib/sidekiq-status/client_middleware_spec.rb +3 -3
- data/spec/lib/sidekiq-status/server_middleware_spec.rb +28 -10
- data/spec/lib/sidekiq-status/web_spec.rb +34 -1
- data/spec/lib/sidekiq-status_spec.rb +6 -6
- data/spec/support/test_jobs.rb +32 -3
- data/web/views/status.erb +26 -7
- data/web/views/status_not_found.erb +3 -2
- data/web/views/statuses.erb +22 -12
- metadata +13 -13
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 73189e5075131660e13e76ce8e8eeedd84953c90998941dd73a16825dc96d951
|
|
4
|
+
data.tar.gz: 5923bc75138cee22d8b5edcc5fbb9ad42dad4e0d89f29df74df68656a73adadc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: '09e500e508e3a0d309e5d817a0fb7e1f58b9013f32284608ae5e2512bd556d07e7846c240789a2df4d5790f0aa183b3623181fd14acb12fd14a863ae354f627e'
|
|
7
|
+
data.tar.gz: 37b1eb9dec966fc8d8645c0ea4139d9a4cee715aca5c5b988881d63599d77e4d7cc564472a3f72e58923b8fb903ed0254c123821dafa2122c622e0dfc5b1e3ca
|
data/.gitignore
CHANGED
data/.gitlab-ci.yml
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
dependency_scanning:
|
|
2
|
+
image: docker:stable
|
|
3
|
+
variables:
|
|
4
|
+
DOCKER_DRIVER: overlay2
|
|
5
|
+
allow_failure: true
|
|
6
|
+
services:
|
|
7
|
+
- docker:stable-dind
|
|
8
|
+
script:
|
|
9
|
+
- export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
|
|
10
|
+
- docker run
|
|
11
|
+
--env DEP_SCAN_DISABLE_REMOTE_CHECKS="${DEP_SCAN_DISABLE_REMOTE_CHECKS:-false}"
|
|
12
|
+
--volume "$PWD:/code"
|
|
13
|
+
--volume /var/run/docker.sock:/var/run/docker.sock
|
|
14
|
+
"registry.gitlab.com/gitlab-org/security-products/dependency-scanning:$SP_VERSION" /code
|
|
15
|
+
artifacts:
|
|
16
|
+
reports:
|
|
17
|
+
dependency_scanning: gl-dependency-scanning-report.json
|
data/.travis.yml
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
language: ruby
|
|
2
2
|
rvm:
|
|
3
|
-
- 2.
|
|
4
|
-
- 2.
|
|
5
|
-
-
|
|
6
|
-
-
|
|
3
|
+
- 2.6
|
|
4
|
+
- 2.7
|
|
5
|
+
- 3.0
|
|
6
|
+
- ruby-head
|
|
7
7
|
gemfile:
|
|
8
|
-
- gemfiles/sidekiq_3.x.gemfile
|
|
9
|
-
- gemfiles/sidekiq_4.x.gemfile
|
|
10
8
|
- gemfiles/sidekiq_5.x.gemfile
|
|
9
|
+
- gemfiles/sidekiq_6.1.gemfile
|
|
10
|
+
- gemfiles/sidekiq_6.x.gemfile
|
|
11
11
|
before_install:
|
|
12
12
|
- gem update --system
|
|
13
13
|
- gem update bundler
|
|
14
14
|
services: redis
|
|
15
15
|
notifications:
|
|
16
16
|
email: false
|
|
17
|
+
matrix:
|
|
18
|
+
fast_finish: true
|
|
19
|
+
allow_failures:
|
|
20
|
+
- rvm: ruby-head
|
data/Appraisals
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
appraise "sidekiq-
|
|
2
|
-
gem "sidekiq", "~>
|
|
1
|
+
appraise "sidekiq-5.x" do
|
|
2
|
+
gem "sidekiq", "~> 5"
|
|
3
3
|
end
|
|
4
4
|
|
|
5
|
-
appraise "sidekiq-
|
|
6
|
-
gem "sidekiq", "~>
|
|
5
|
+
appraise "sidekiq-6.1" do
|
|
6
|
+
gem "sidekiq", "~> 6.1"
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
appraise "sidekiq-
|
|
10
|
-
gem "sidekiq", "~>
|
|
9
|
+
appraise "sidekiq-6.x" do
|
|
10
|
+
gem "sidekiq", "~> 6"
|
|
11
11
|
end
|
data/CHANGELOG.md
CHANGED
|
@@ -1,59 +1,27 @@
|
|
|
1
|
-
**Version
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
**Version 1.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
**Version 1.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
**Version 1.0
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
**Version 0.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
**Version 0.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
+ Sidekiq 4.2 and 5 now supported
|
|
29
|
-
+ Added full support for ActiveJob
|
|
30
|
-
+ Updated Web UI
|
|
31
|
-
+ Styling updated to stay consistent with Sidekiq UI
|
|
32
|
-
+ Added header sorting
|
|
33
|
-
+ Fixed argument formatting
|
|
34
|
-
+ Times now display using natural language via ChronicDuration
|
|
35
|
-
+ Test suite fixed
|
|
36
|
-
|
|
37
|
-
**Version 0.6.0**
|
|
38
|
-
+ Updated Web UI
|
|
39
|
-
+ Will have all job statuses, previously it was showing only :working status
|
|
40
|
-
+ Bootstrap lables instead of badges for status
|
|
41
|
-
+ Added Arguments column to statuses page
|
|
42
|
-
+ New :interrupted status added
|
|
43
|
-
+ Added way to specify :expiration for Sidekiq::Status::ClientMiddleware
|
|
44
|
-
+ Bug fixes & Code cleaup
|
|
45
|
-
|
|
46
|
-
**Version 0.5.3**
|
|
47
|
-
+ some tweaks in web UI, separate redis namespace
|
|
48
|
-
|
|
49
|
-
**Version 0.5.2**
|
|
50
|
-
+ Sidekiq versions up to 3.3.* supported, jobs sorting options in web UI, more ruby versions
|
|
51
|
-
|
|
52
|
-
**Version 0.5.1**
|
|
53
|
-
+ dependencies versions requirements relaxed
|
|
54
|
-
|
|
55
|
-
**Version 0.5.0**
|
|
56
|
-
+ Sidekiq v3 support, redis pools support
|
|
57
|
-
|
|
58
|
-
**Version 0.4.0**
|
|
59
|
-
+ WebUI added, per-worker expiration setting enabled
|
|
1
|
+
**Version 2.1.3**
|
|
2
|
+
* Fixes redis deprecation warnings (https://github.com/kenaniah/sidekiq-status/issues/11)
|
|
3
|
+
|
|
4
|
+
**Version 2.1.2**
|
|
5
|
+
* Casts values to strings when HTML-encoding
|
|
6
|
+
|
|
7
|
+
**Version 2.1.1**
|
|
8
|
+
* Ensures parameter outputs are properly HTML-encoded
|
|
9
|
+
|
|
10
|
+
**Version 2.1.0**
|
|
11
|
+
* Adds support for Sidekiq 6.2.2+ (https://github.com/mperham/sidekiq/issues/4955)
|
|
12
|
+
|
|
13
|
+
**Version 2.0.2**
|
|
14
|
+
* Fixes for dark mode theme
|
|
15
|
+
|
|
16
|
+
**Version 2.0.1**
|
|
17
|
+
* Adds support for dark mode to the job status page
|
|
18
|
+
|
|
19
|
+
**Version 2.0.0**
|
|
20
|
+
* Adds support for Ruby 2.7, 3.0
|
|
21
|
+
* Adds support for Sidekiq 6.x
|
|
22
|
+
* Removes support for Ruby 2.3, 2.4, 2.5
|
|
23
|
+
* Removes support for Sidekiq 3.x, 4.x
|
|
24
|
+
|
|
25
|
+
**Versions 1.1.4 and prior**
|
|
26
|
+
|
|
27
|
+
See https://github.com/utgarda/sidekiq-status/blob/master/CHANGELOG.md.
|
data/README.md
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
# Sidekiq::Status
|
|
2
|
-
[](
|
|
3
|
-
[](https://gemnasium.com/utgarda/sidekiq-status)
|
|
6
|
-
[](http://inch-ci.org/github/utgarda/sidekiq-status)
|
|
2
|
+
[](https://badge.fury.io/rb/sidekiq-status)
|
|
3
|
+
[](https://www.travis-ci.com/github/kenaniah/sidekiq-status)
|
|
4
|
+
[](https://inch-ci.org/github/kenaniah/sidekiq-status)
|
|
7
5
|
|
|
8
|
-
|
|
9
|
-
by [resque-status](http://github.com/quirkey/resque-status) and mostly copying its features, using Sidekiq's middleware.
|
|
6
|
+
Sidekiq-status is an extension to [Sidekiq](https://github.com/mperham/sidekiq) that tracks information about your Sidekiq and provides a UI to that purpose. It was inspired by [resque-status](https://github.com/quirkey/resque-status).
|
|
10
7
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Supports the latest versions of Sidekiq and all the way back to 3.x.
|
|
8
|
+
Requires Ruby 2.6+ and Sidekiq 5.0+ or newer.
|
|
14
9
|
|
|
15
10
|
## Installation
|
|
16
11
|
|
|
@@ -20,18 +15,18 @@ Add this line to your application's Gemfile:
|
|
|
20
15
|
gem 'sidekiq-status'
|
|
21
16
|
```
|
|
22
17
|
|
|
23
|
-
And then execute:
|
|
24
|
-
|
|
25
|
-
```bash
|
|
26
|
-
$ bundle
|
|
27
|
-
```
|
|
28
|
-
|
|
29
18
|
Or install it yourself as:
|
|
30
19
|
|
|
31
20
|
```bash
|
|
32
21
|
gem install sidekiq-status
|
|
33
22
|
```
|
|
34
23
|
|
|
24
|
+
#### Migrating to Version 2.x from 1.x
|
|
25
|
+
|
|
26
|
+
Version 2.0.0 was published in order to add support for Ruby 3.0 and Sidekiq 6.x and to remove support for versions of both that are now end-of-life. **You should be able to upgrade cleanly from version 1.x to 2.x provided you are running Sidekiq 5.x or newer.**
|
|
27
|
+
|
|
28
|
+
Sidekiq-status version 1.1.4 provides support all the way back to Sidekiq 3.x and was maintained at https://github.com/utgarda/sidekiq-status/.
|
|
29
|
+
|
|
35
30
|
## Setup Checklist
|
|
36
31
|
|
|
37
32
|
To get started:
|
|
@@ -63,9 +58,7 @@ Sidekiq.configure_server do |config|
|
|
|
63
58
|
end
|
|
64
59
|
```
|
|
65
60
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
After that you can use your jobs as usual. You need to also include the `Sidekiq::Status::Worker` module in your jobs if you want the additional functionality of tracking progress and storing / retrieving job data.
|
|
61
|
+
Include the `Sidekiq::Status::Worker` module in your jobs if you want the additional functionality of tracking progress and storing / retrieving job data.
|
|
69
62
|
|
|
70
63
|
``` ruby
|
|
71
64
|
class MyJob
|
|
@@ -78,7 +71,7 @@ class MyJob
|
|
|
78
71
|
end
|
|
79
72
|
```
|
|
80
73
|
|
|
81
|
-
|
|
74
|
+
Note: _only jobs that include `Sidekiq::Status::Worker`_ will have their statuses tracked.
|
|
82
75
|
|
|
83
76
|
To overwrite expiration on a per-worker basis, write an expiration method like the one below:
|
|
84
77
|
|
|
@@ -105,7 +98,7 @@ As sidekiq-status stores information about jobs in Redis, it is necessary to set
|
|
|
105
98
|
|
|
106
99
|
As explained above, the default expiration may also be overridden on a per-job basis by defining it within the job itself via a method called `#expiration`.
|
|
107
100
|
|
|
108
|
-
The expiration time set will be used as the [Redis expire time](
|
|
101
|
+
The expiration time set will be used as the [Redis expire time](https://redis.io/commands/expire), which is also known as the TTL (time to live). Once the expiration time has passed, all information about the job's status and any custom data stored via sidekiq-status will disappear.
|
|
109
102
|
|
|
110
103
|
It is advised that you set the expiration time greater than the amount of time required to complete the job.
|
|
111
104
|
|
|
@@ -131,7 +124,7 @@ Important: If you try any of the above status method after the expiration time,
|
|
|
131
124
|
|
|
132
125
|
### ActiveJob Support
|
|
133
126
|
|
|
134
|
-
|
|
127
|
+
This gem also supports ActiveJob jobs. Their status will be tracked automatically.
|
|
135
128
|
|
|
136
129
|
To also enable job progress tracking and data storage features, simply add the `Sidekiq::Status::Worker` module to your base class, like below:
|
|
137
130
|
|
|
@@ -216,11 +209,11 @@ This gem provides an extension to Sidekiq's web interface with an index at `/sta
|
|
|
216
209
|
|
|
217
210
|

|
|
218
211
|
|
|
219
|
-
|
|
212
|
+
Information for an individual job may be found at `/statuses/:job_id`.
|
|
220
213
|
|
|
221
214
|

|
|
222
215
|
|
|
223
|
-
|
|
216
|
+
Note: _only jobs that include `Sidekiq::Status::Worker`_ will be reported in the web interface.
|
|
224
217
|
|
|
225
218
|
#### Adding the Web Interface
|
|
226
219
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
require 'sidekiq/api'
|
|
2
|
+
JOB_CLASS = Sidekiq.constants.include?(:JobRecord) ? Sidekiq::JobRecord : Sidekiq::Job
|
|
3
|
+
|
|
2
4
|
module Sidekiq::Status
|
|
3
5
|
# Should be in the client middleware chain
|
|
4
6
|
class ClientMiddleware
|
|
@@ -34,7 +36,7 @@ module Sidekiq::Status
|
|
|
34
36
|
initial_metadata = {
|
|
35
37
|
jid: msg['jid'],
|
|
36
38
|
status: :queued,
|
|
37
|
-
worker:
|
|
39
|
+
worker: JOB_CLASS.new(msg, queue).display_class,
|
|
38
40
|
args: display_args(msg, queue)
|
|
39
41
|
}
|
|
40
42
|
store_for_id msg['jid'], initial_metadata, job_class.new.expiration || @expiration, redis_pool
|
|
@@ -45,7 +47,7 @@ module Sidekiq::Status
|
|
|
45
47
|
end
|
|
46
48
|
|
|
47
49
|
def display_args(msg, queue)
|
|
48
|
-
job =
|
|
50
|
+
job = JOB_CLASS.new(msg, queue)
|
|
49
51
|
return job.display_args.to_a.empty? ? nil : job.display_args.to_json
|
|
50
52
|
rescue Exception => e
|
|
51
53
|
# For Sidekiq ~> 2.7
|
|
@@ -13,10 +13,10 @@ module Sidekiq::Status::Storage
|
|
|
13
13
|
# @return [String] Redis operation status code
|
|
14
14
|
def store_for_id(id, status_updates, expiration = nil, redis_pool=nil)
|
|
15
15
|
redis_connection(redis_pool) do |conn|
|
|
16
|
-
conn.multi do
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
conn.multi do |pipeline|
|
|
17
|
+
pipeline.hmset key(id), 'update_time', Time.now.to_i, *(status_updates.to_a.flatten(1))
|
|
18
|
+
pipeline.expire key(id), (expiration || Sidekiq::Status::DEFAULT_EXPIRY)
|
|
19
|
+
pipeline.publish "status_updates", id
|
|
20
20
|
end[0]
|
|
21
21
|
end
|
|
22
22
|
end
|
|
@@ -90,7 +90,7 @@ module Sidekiq::Status::Storage
|
|
|
90
90
|
# - end: end score (i.e. +inf or a unix timestamp)
|
|
91
91
|
# - offset: current progress through (all) jobs (e.g.: 100 if you want jobs from 100 to BATCH_LIMIT)
|
|
92
92
|
def schedule_batch(options)
|
|
93
|
-
options[:conn].zrangebyscore "schedule", options[:start], options[:end],
|
|
93
|
+
options[:conn].zrangebyscore "schedule", options[:start], options[:end], limit: [options[:offset], BATCH_LIMIT]
|
|
94
94
|
end
|
|
95
95
|
|
|
96
96
|
# Searches the jobs Array for the job_id
|
data/lib/sidekiq-status/web.rb
CHANGED
|
@@ -8,6 +8,7 @@ module Sidekiq::Status
|
|
|
8
8
|
|
|
9
9
|
DEFAULT_PER_PAGE_OPTS = [25, 50, 100].freeze
|
|
10
10
|
DEFAULT_PER_PAGE = 25
|
|
11
|
+
COMMON_STATUS_HASH_KEYS = %w(update_time jid status worker args label pct_complete total at message)
|
|
11
12
|
|
|
12
13
|
class << self
|
|
13
14
|
def per_page_opts= arr
|
|
@@ -47,9 +48,14 @@ module Sidekiq::Status
|
|
|
47
48
|
def add_details_to_status(status)
|
|
48
49
|
status['label'] = status_label(status['status'])
|
|
49
50
|
status["pct_complete"] ||= pct_complete(status)
|
|
51
|
+
status["custom"] = process_custom_data(status)
|
|
50
52
|
return status
|
|
51
53
|
end
|
|
52
54
|
|
|
55
|
+
def process_custom_data(hash)
|
|
56
|
+
hash.reject { |key, _| COMMON_STATUS_HASH_KEYS.include?(key) }
|
|
57
|
+
end
|
|
58
|
+
|
|
53
59
|
def pct_complete(status)
|
|
54
60
|
return 100 if status['status'] == 'complete'
|
|
55
61
|
Sidekiq::Status::pct_complete(status['jid']) || 0
|
|
@@ -75,8 +81,11 @@ module Sidekiq::Status
|
|
|
75
81
|
|
|
76
82
|
app.get '/statuses' do
|
|
77
83
|
|
|
78
|
-
|
|
79
|
-
|
|
84
|
+
jids = Sidekiq.redis do |conn|
|
|
85
|
+
conn.scan_each(match: 'sidekiq:status:*', count: 100).map do |key|
|
|
86
|
+
key.split(':').last
|
|
87
|
+
end.uniq
|
|
88
|
+
end
|
|
80
89
|
@statuses = []
|
|
81
90
|
|
|
82
91
|
jids.each do |jid|
|
|
@@ -96,6 +105,10 @@ module Sidekiq::Status
|
|
|
96
105
|
@statuses = @statuses.sort { |y,x| (x[sort_by] <=> y[sort_by]) || 1 }
|
|
97
106
|
end
|
|
98
107
|
|
|
108
|
+
if params[:status] && params[:status] != "all"
|
|
109
|
+
@statuses = @statuses.select {|job_status| job_status["status"] == params[:status] }
|
|
110
|
+
end
|
|
111
|
+
|
|
99
112
|
# Sidekiq pagination
|
|
100
113
|
@total_size = @statuses.count
|
|
101
114
|
@count = params[:per_page] ? params[:per_page].to_i : Sidekiq::Status::Web.default_per_page
|
|
@@ -123,7 +136,7 @@ module Sidekiq::Status
|
|
|
123
136
|
job = Sidekiq::Status::get_all params['jid']
|
|
124
137
|
|
|
125
138
|
if job.empty?
|
|
126
|
-
halt [404, {"Content-Type" => "text/html"}, [erb(sidekiq_status_template(:status_not_found))]]
|
|
139
|
+
throw :halt, [404, {"Content-Type" => "text/html"}, [erb(sidekiq_status_template(:status_not_found))]]
|
|
127
140
|
else
|
|
128
141
|
@status = add_details_to_status(job)
|
|
129
142
|
erb(sidekiq_status_template(:status))
|
|
@@ -135,21 +148,25 @@ module Sidekiq::Status
|
|
|
135
148
|
job = Sidekiq::RetrySet.new.find_job(params[:jid])
|
|
136
149
|
job ||= Sidekiq::DeadSet.new.find_job(params[:jid])
|
|
137
150
|
job.retry if job
|
|
138
|
-
halt [302, { "Location" => request.referer }, []]
|
|
151
|
+
throw :halt, [302, { "Location" => request.referer }, []]
|
|
139
152
|
end
|
|
140
153
|
|
|
141
154
|
# Removes a completed job from the status list
|
|
142
155
|
app.delete '/statuses' do
|
|
143
156
|
Sidekiq::Status.delete(params[:jid])
|
|
144
|
-
halt [302, { "Location" => request.referer }, []]
|
|
157
|
+
throw :halt, [302, { "Location" => request.referer }, []]
|
|
145
158
|
end
|
|
146
159
|
end
|
|
147
160
|
end
|
|
148
161
|
end
|
|
149
162
|
|
|
150
|
-
|
|
163
|
+
unless defined?(Sidekiq::Web)
|
|
164
|
+
require 'delegate' # Needed for sidekiq 5.x
|
|
165
|
+
require 'sidekiq/web'
|
|
166
|
+
end
|
|
167
|
+
|
|
151
168
|
Sidekiq::Web.register(Sidekiq::Status::Web)
|
|
152
|
-
["per_page", "sort_by", "sort_dir"].each do |key|
|
|
169
|
+
["per_page", "sort_by", "sort_dir", "status"].each do |key|
|
|
153
170
|
Sidekiq::WebHelpers::SAFE_QPARAMS.push(key)
|
|
154
171
|
end
|
|
155
172
|
if Sidekiq::Web.tabs.is_a?(Array)
|
data/sidekiq-status.gemspec
CHANGED
|
@@ -5,7 +5,7 @@ Gem::Specification.new do |gem|
|
|
|
5
5
|
gem.authors = ['Evgeniy Tsvigun', 'Kenaniah Cerny']
|
|
6
6
|
gem.email = ['utgarda@gmail.com', 'kenaniah@gmail.com']
|
|
7
7
|
gem.summary = 'An extension to the sidekiq message processing to track your jobs'
|
|
8
|
-
gem.homepage = '
|
|
8
|
+
gem.homepage = 'https://github.com/kenaniah/sidekiq-status'
|
|
9
9
|
gem.license = 'MIT'
|
|
10
10
|
|
|
11
11
|
gem.files = `git ls-files`.split($\)
|
|
@@ -14,7 +14,7 @@ Gem::Specification.new do |gem|
|
|
|
14
14
|
gem.require_paths = ['lib']
|
|
15
15
|
gem.version = Sidekiq::Status::VERSION
|
|
16
16
|
|
|
17
|
-
gem.add_dependency 'sidekiq', '>=
|
|
17
|
+
gem.add_dependency 'sidekiq', '>= 5.0'
|
|
18
18
|
gem.add_dependency 'chronic_duration'
|
|
19
19
|
gem.add_development_dependency 'appraisal'
|
|
20
20
|
gem.add_development_dependency 'colorize'
|
|
@@ -12,13 +12,13 @@ describe Sidekiq::Status::ClientMiddleware do
|
|
|
12
12
|
describe "without :expiration parameter" do
|
|
13
13
|
|
|
14
14
|
it "sets queued status" do
|
|
15
|
-
expect(StubJob.perform_async arg1
|
|
15
|
+
expect(StubJob.perform_async 'arg1' => 'val1').to eq(job_id)
|
|
16
16
|
expect(redis.hget("sidekiq:status:#{job_id}", :status)).to eq('queued')
|
|
17
17
|
expect(Sidekiq::Status::queued?(job_id)).to be_truthy
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
it "sets status hash ttl" do
|
|
21
|
-
expect(StubJob.perform_async arg1
|
|
21
|
+
expect(StubJob.perform_async 'arg1' => 'val1').to eq(job_id)
|
|
22
22
|
expect(1..Sidekiq::Status::DEFAULT_EXPIRY).to cover redis.ttl("sidekiq:status:#{job_id}")
|
|
23
23
|
end
|
|
24
24
|
|
|
@@ -50,7 +50,7 @@ describe Sidekiq::Status::ClientMiddleware do
|
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
it "overwrites default expiry value" do
|
|
53
|
-
StubJob.perform_async arg1
|
|
53
|
+
StubJob.perform_async 'arg1' => 'val1'
|
|
54
54
|
expect((Sidekiq::Status::DEFAULT_EXPIRY+1)..huge_expiration).to cover redis.ttl("sidekiq:status:#{job_id}")
|
|
55
55
|
end
|
|
56
56
|
|
|
@@ -10,7 +10,7 @@ describe Sidekiq::Status::ServerMiddleware do
|
|
|
10
10
|
allow(SecureRandom).to receive(:hex).once.and_return(job_id)
|
|
11
11
|
start_server do
|
|
12
12
|
thread = redis_thread 4, "status_updates", "job_messages_#{job_id}"
|
|
13
|
-
expect(ConfirmationJob.perform_async arg1
|
|
13
|
+
expect(ConfirmationJob.perform_async 'arg1' => 'val1').to eq(job_id)
|
|
14
14
|
expect(thread.value).to eq([
|
|
15
15
|
job_id,
|
|
16
16
|
job_id,
|
|
@@ -36,21 +36,39 @@ describe Sidekiq::Status::ServerMiddleware do
|
|
|
36
36
|
it "sets failed status when Exception raised" do
|
|
37
37
|
allow(SecureRandom).to receive(:hex).once.and_return(job_id)
|
|
38
38
|
start_server do
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
expect(capture_status_updates(3) {
|
|
40
|
+
expect(FailingHardJob.perform_async).to eq(job_id)
|
|
41
|
+
}).to eq([job_id]*3)
|
|
42
42
|
end
|
|
43
43
|
expect(redis.hget("sidekiq:status:#{job_id}", :status)).to eq('failed')
|
|
44
44
|
expect(Sidekiq::Status::failed?(job_id)).to be_truthy
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
+
context "when Sidekiq::Status::Worker is not included in the job" do
|
|
48
|
+
it "should not set a failed status" do
|
|
49
|
+
allow(SecureRandom).to receive(:hex).once.and_return(job_id)
|
|
50
|
+
start_server do
|
|
51
|
+
expect(FailingNoStatusJob.perform_async).to eq(job_id)
|
|
52
|
+
end
|
|
53
|
+
expect(redis.hget("sidekiq:status:#{job_id}", :status)).to be_nil
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "should not set any status when Exception raised" do
|
|
57
|
+
allow(SecureRandom).to receive(:hex).once.and_return(job_id)
|
|
58
|
+
start_server do
|
|
59
|
+
expect(FailingHardNoStatusJob.perform_async).to eq(job_id)
|
|
60
|
+
end
|
|
61
|
+
expect(redis.hget("sidekiq:status:#{job_id}", :status)).to be_nil
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
47
65
|
context "sets interrupted status" do
|
|
48
66
|
it "on system exit signal" do
|
|
49
67
|
allow(SecureRandom).to receive(:hex).once.and_return(job_id)
|
|
50
68
|
start_server do
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
69
|
+
expect(capture_status_updates(3) {
|
|
70
|
+
expect(ExitedJob.perform_async).to eq(job_id)
|
|
71
|
+
}).to eq([job_id]*3)
|
|
54
72
|
end
|
|
55
73
|
expect(redis.hget("sidekiq:status:#{job_id}", :status)).to eq('interrupted')
|
|
56
74
|
expect(Sidekiq::Status::interrupted?(job_id)).to be_truthy
|
|
@@ -72,7 +90,7 @@ describe Sidekiq::Status::ServerMiddleware do
|
|
|
72
90
|
it "sets status hash ttl" do
|
|
73
91
|
allow(SecureRandom).to receive(:hex).once.and_return(job_id)
|
|
74
92
|
start_server do
|
|
75
|
-
expect(StubJob.perform_async arg1
|
|
93
|
+
expect(StubJob.perform_async 'arg1' => 'val1').to eq(job_id)
|
|
76
94
|
end
|
|
77
95
|
expect(1..Sidekiq::Status::DEFAULT_EXPIRY).to cover redis.ttl("sidekiq:status:#{job_id}")
|
|
78
96
|
end
|
|
@@ -86,7 +104,7 @@ describe Sidekiq::Status::ServerMiddleware do
|
|
|
86
104
|
|
|
87
105
|
it "overwrites default expiry value" do
|
|
88
106
|
start_server(:expiration => huge_expiration) do
|
|
89
|
-
StubJob.perform_async arg1
|
|
107
|
+
StubJob.perform_async 'arg1' => 'val1'
|
|
90
108
|
end
|
|
91
109
|
expect((Sidekiq::Status::DEFAULT_EXPIRY-1)..huge_expiration).to cover redis.ttl("sidekiq:status:#{job_id}")
|
|
92
110
|
end
|
|
@@ -95,7 +113,7 @@ describe Sidekiq::Status::ServerMiddleware do
|
|
|
95
113
|
overwritten_expiration = huge_expiration * 100
|
|
96
114
|
allow_any_instance_of(StubJob).to receive(:expiration).and_return(overwritten_expiration)
|
|
97
115
|
start_server(:expiration => huge_expiration) do
|
|
98
|
-
StubJob.perform_async arg1
|
|
116
|
+
StubJob.perform_async 'arg1' => 'val1'
|
|
99
117
|
end
|
|
100
118
|
expect((huge_expiration+1)..overwritten_expiration).to cover redis.ttl("sidekiq:status:#{job_id}")
|
|
101
119
|
end
|
|
@@ -13,6 +13,7 @@ describe 'sidekiq status web' do
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
before do
|
|
16
|
+
env 'rack.session', csrf: Base64.urlsafe_encode64('token')
|
|
16
17
|
client_middleware
|
|
17
18
|
allow(SecureRandom).to receive(:hex).and_return(job_id)
|
|
18
19
|
end
|
|
@@ -31,6 +32,27 @@ describe 'sidekiq status web' do
|
|
|
31
32
|
expect(last_response.body).to match(/working/)
|
|
32
33
|
end
|
|
33
34
|
|
|
35
|
+
it 'allows filtering the list of jobs by status' do
|
|
36
|
+
capture_status_updates(2) do
|
|
37
|
+
LongJob.perform_async(0.5)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
get '/statuses?status=working'
|
|
41
|
+
expect(last_response).to be_ok
|
|
42
|
+
expect(last_response.body).to match(/#{job_id}/)
|
|
43
|
+
expect(last_response.body).to match(/LongJob/)
|
|
44
|
+
expect(last_response.body).to match(/working/)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'allows filtering the list of jobs by completed status' do
|
|
48
|
+
capture_status_updates(2) do
|
|
49
|
+
LongJob.perform_async(0.5)
|
|
50
|
+
end
|
|
51
|
+
get '/statuses?status=completed'
|
|
52
|
+
expect(last_response).to be_ok
|
|
53
|
+
expect(last_response.body).to_not match(/LongJob/)
|
|
54
|
+
end
|
|
55
|
+
|
|
34
56
|
it 'shows a single job in progress' do
|
|
35
57
|
capture_status_updates(2) do
|
|
36
58
|
LongJob.perform_async(1, 'another argument')
|
|
@@ -39,10 +61,21 @@ describe 'sidekiq status web' do
|
|
|
39
61
|
get "/statuses/#{job_id}"
|
|
40
62
|
expect(last_response).to be_ok
|
|
41
63
|
expect(last_response.body).to match(/#{job_id}/)
|
|
42
|
-
expect(last_response.body).to match(/1
|
|
64
|
+
expect(last_response.body).to match(/1,"another argument"/)
|
|
43
65
|
expect(last_response.body).to match(/working/)
|
|
44
66
|
end
|
|
45
67
|
|
|
68
|
+
it 'shows custom data for a single job' do
|
|
69
|
+
capture_status_updates(3) do
|
|
70
|
+
CustomDataJob.perform_async
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
get "/statuses/#{job_id}"
|
|
74
|
+
expect(last_response).to be_ok
|
|
75
|
+
expect(last_response.body).to match(/mister_cat/)
|
|
76
|
+
expect(last_response.body).to match(/meow/)
|
|
77
|
+
end
|
|
78
|
+
|
|
46
79
|
it 'show an error when the requested job ID is not found' do
|
|
47
80
|
get '/statuses/12345'
|
|
48
81
|
expect(last_response).to be_not_found
|
|
@@ -105,7 +105,7 @@ describe Sidekiq::Status do
|
|
|
105
105
|
second_job = LongJob.perform_in(3600)
|
|
106
106
|
expect(second_job).to eq(job_id_1)
|
|
107
107
|
|
|
108
|
-
initial_schedule = redis.zrange "schedule", 0, -1,
|
|
108
|
+
initial_schedule = redis.zrange "schedule", 0, -1, withscores: true
|
|
109
109
|
expect(initial_schedule.size).to be(2)
|
|
110
110
|
expect(initial_schedule.select {|scheduled_job| JSON.parse(scheduled_job[0])["jid"] == job_id }.size).to be(1)
|
|
111
111
|
|
|
@@ -113,7 +113,7 @@ describe Sidekiq::Status do
|
|
|
113
113
|
# Unused, therefore unfound => false
|
|
114
114
|
expect(Sidekiq::Status.cancel(unused_id)).to be_falsey
|
|
115
115
|
|
|
116
|
-
remaining_schedule = redis.zrange "schedule", 0, -1,
|
|
116
|
+
remaining_schedule = redis.zrange "schedule", 0, -1, withscores: true
|
|
117
117
|
expect(remaining_schedule.size).to be(initial_schedule.size - 1)
|
|
118
118
|
expect(remaining_schedule.select {|scheduled_job| JSON.parse(scheduled_job[0])["jid"] == job_id }.size).to be(0)
|
|
119
119
|
end
|
|
@@ -126,14 +126,14 @@ describe Sidekiq::Status do
|
|
|
126
126
|
returned_job_id = LongJob.perform_at(scheduled_time)
|
|
127
127
|
expect(returned_job_id).to eq(job_id)
|
|
128
128
|
|
|
129
|
-
initial_schedule = redis.zrange "schedule", 0, -1,
|
|
129
|
+
initial_schedule = redis.zrange "schedule", 0, -1, withscores: true
|
|
130
130
|
expect(initial_schedule.size).to be(1)
|
|
131
131
|
# wrong time, therefore unfound => false
|
|
132
132
|
expect(Sidekiq::Status.cancel(returned_job_id, (scheduled_time + 1))).to be_falsey
|
|
133
|
-
expect((redis.zrange "schedule", 0, -1,
|
|
133
|
+
expect((redis.zrange "schedule", 0, -1, withscores: true).size).to be(1)
|
|
134
134
|
# same id, same time, deletes
|
|
135
135
|
expect(Sidekiq::Status.cancel(returned_job_id, (scheduled_time))).to be_truthy
|
|
136
|
-
expect(redis.zrange "schedule", 0, -1,
|
|
136
|
+
expect(redis.zrange "schedule", 0, -1, withscores: true).to be_empty
|
|
137
137
|
end
|
|
138
138
|
end
|
|
139
139
|
end
|
|
@@ -159,7 +159,7 @@ describe Sidekiq::Status do
|
|
|
159
159
|
end
|
|
160
160
|
|
|
161
161
|
it "retries failed jobs" do
|
|
162
|
-
allow(SecureRandom).to receive(:hex).and_return(retried_job_id)
|
|
162
|
+
allow(SecureRandom).to receive(:hex).exactly(3).times.and_return(retried_job_id)
|
|
163
163
|
start_server do
|
|
164
164
|
expect(capture_status_updates(3) {
|
|
165
165
|
expect(RetriedJob.perform_async()).to eq(retried_job_id)
|
data/spec/support/test_jobs.rb
CHANGED
|
@@ -10,6 +10,16 @@ class StubJob
|
|
|
10
10
|
end
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
+
class StubNoStatusJob
|
|
14
|
+
include Sidekiq::Worker
|
|
15
|
+
|
|
16
|
+
sidekiq_options 'retry' => false
|
|
17
|
+
|
|
18
|
+
def perform(*args)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
|
|
13
23
|
class ExpiryJob < StubJob
|
|
14
24
|
def expiration
|
|
15
25
|
15
|
|
@@ -31,6 +41,13 @@ class DataJob < StubJob
|
|
|
31
41
|
end
|
|
32
42
|
end
|
|
33
43
|
|
|
44
|
+
class CustomDataJob < StubJob
|
|
45
|
+
def perform
|
|
46
|
+
store({mister_cat: 'meow'})
|
|
47
|
+
sleep 0.5
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
34
51
|
class ProgressJob < StubJob
|
|
35
52
|
def perform
|
|
36
53
|
total 500
|
|
@@ -62,6 +79,12 @@ class FailingJob < StubJob
|
|
|
62
79
|
end
|
|
63
80
|
end
|
|
64
81
|
|
|
82
|
+
class FailingNoStatusJob < StubNoStatusJob
|
|
83
|
+
def perform
|
|
84
|
+
raise StandardError
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
65
88
|
class RetryAndFailJob < StubJob
|
|
66
89
|
sidekiq_options retry: 1
|
|
67
90
|
|
|
@@ -76,6 +99,12 @@ class FailingHardJob < StubJob
|
|
|
76
99
|
end
|
|
77
100
|
end
|
|
78
101
|
|
|
102
|
+
class FailingHardNoStatusJob < StubNoStatusJob
|
|
103
|
+
def perform
|
|
104
|
+
raise Exception
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
79
108
|
class ExitedJob < StubJob
|
|
80
109
|
def perform
|
|
81
110
|
raise SystemExit
|
|
@@ -90,13 +119,13 @@ end
|
|
|
90
119
|
|
|
91
120
|
class RetriedJob < StubJob
|
|
92
121
|
|
|
93
|
-
sidekiq_options
|
|
122
|
+
sidekiq_options retry: true
|
|
94
123
|
sidekiq_retry_in do |count| 3 end # 3 second delay > job timeout in test suite
|
|
95
124
|
|
|
96
|
-
def perform
|
|
125
|
+
def perform
|
|
97
126
|
Sidekiq.redis do |conn|
|
|
98
127
|
key = "RetriedJob_#{jid}"
|
|
99
|
-
|
|
128
|
+
if [0, false].include? conn.exists(key)
|
|
100
129
|
conn.set key, 'tried'
|
|
101
130
|
raise StandardError
|
|
102
131
|
end
|
data/web/views/status.erb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
<% require 'cgi'; def h(v); CGI.escape_html(v.to_s); end %>
|
|
1
2
|
<style>
|
|
2
3
|
.progress {
|
|
3
4
|
background-color: #C8E1ED;
|
|
@@ -14,9 +15,9 @@
|
|
|
14
15
|
</style>
|
|
15
16
|
|
|
16
17
|
<h3>
|
|
17
|
-
Job Status: <%= @status["jid"] %>
|
|
18
|
-
<span class='label label-<%= @status["label"] %>'>
|
|
19
|
-
<%= @status["status"] %>
|
|
18
|
+
Job Status: <%= h @status["jid"] %>
|
|
19
|
+
<span class='label label-<%= h @status["label"] %>'>
|
|
20
|
+
<%= h @status["status"] %>
|
|
20
21
|
</span>
|
|
21
22
|
</h3>
|
|
22
23
|
|
|
@@ -28,16 +29,16 @@
|
|
|
28
29
|
</div>
|
|
29
30
|
</div>
|
|
30
31
|
|
|
31
|
-
<div class="panel panel-default">
|
|
32
|
+
<div class="panel panel-default" style="background-color: inherit">
|
|
32
33
|
<div class="panel-body">
|
|
33
|
-
<h4><%= @status["worker"] %></h4>
|
|
34
|
+
<h4><%= h @status["worker"] %></h4>
|
|
34
35
|
|
|
35
36
|
<div class="row">
|
|
36
37
|
<div class="col-sm-2">
|
|
37
38
|
<strong>Arguments</strong>
|
|
38
39
|
</div>
|
|
39
40
|
<div class="col-sm-10">
|
|
40
|
-
<p><%= @status["args"].empty? ? "<i>none</i>" : @status["args"] %></p>
|
|
41
|
+
<p><%= @status["args"].empty? ? "<i>none</i>" : h(@status["args"]) %></p>
|
|
41
42
|
</div>
|
|
42
43
|
</div>
|
|
43
44
|
|
|
@@ -46,7 +47,7 @@
|
|
|
46
47
|
<strong>Message</strong>
|
|
47
48
|
</div>
|
|
48
49
|
<div class="col-sm-10">
|
|
49
|
-
<p><%= @status["message"] || "<i>none</i>" %></p>
|
|
50
|
+
<p><%= h(@status["message"]) || "<i>none</i>" %></p>
|
|
50
51
|
</div>
|
|
51
52
|
</div>
|
|
52
53
|
|
|
@@ -65,6 +66,24 @@
|
|
|
65
66
|
</p>
|
|
66
67
|
</div>
|
|
67
68
|
</div>
|
|
69
|
+
|
|
70
|
+
<% if @status["custom"].any? %>
|
|
71
|
+
<hr>
|
|
72
|
+
<% @status["custom"].each do |key, val| %>
|
|
73
|
+
<div class="row">
|
|
74
|
+
<div class="col-sm-2">
|
|
75
|
+
<strong><%= key %></strong>
|
|
76
|
+
</div>
|
|
77
|
+
<div class="col-sm-10">
|
|
78
|
+
<% if val && val.include?("\n") %>
|
|
79
|
+
<pre><%= h val %></pre>
|
|
80
|
+
<% else %>
|
|
81
|
+
<p><%= h(val) || "<i>none</i>" %></p>
|
|
82
|
+
<% end %>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
<% end %>
|
|
86
|
+
<% end %>
|
|
68
87
|
</div>
|
|
69
88
|
</div>
|
|
70
89
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
<% require 'cgi'; def h(v); CGI.escape_html(v.to_s); end %>
|
|
2
|
+
<h3>Job Status: <%= h params[:jid] %></h3>
|
|
2
3
|
|
|
3
|
-
<div
|
|
4
|
+
<div role="alert">
|
|
4
5
|
<strong>Uh oh!</strong> That job can't be found. It may have expired already.
|
|
5
6
|
</div>
|
data/web/views/statuses.erb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
<% require 'cgi'; def h(v); CGI.escape_html(v.to_s); end %>
|
|
1
2
|
<style>
|
|
2
3
|
.progress {
|
|
3
4
|
background-color: #C8E1ED;
|
|
@@ -38,7 +39,7 @@
|
|
|
38
39
|
display: flex;
|
|
39
40
|
align-items: center;
|
|
40
41
|
}
|
|
41
|
-
.nav-container .per-page {
|
|
42
|
+
.nav-container .per-page, .filter-status {
|
|
42
43
|
display: flex;
|
|
43
44
|
align-items: center;
|
|
44
45
|
margin: 20px 0 20px 10px;
|
|
@@ -57,6 +58,15 @@ function setPerPage(select){
|
|
|
57
58
|
<h3 class="wi">Recent job statuses</h3>
|
|
58
59
|
<div class="nav-container">
|
|
59
60
|
<%= erb :_paging, locals: { url: "#{root_path}statuses" } %>
|
|
61
|
+
<div class="filter-status">
|
|
62
|
+
Filter Status:
|
|
63
|
+
<select class="form-control" onchange="setPerPage(this)">
|
|
64
|
+
<% (['all', 'complete', 'failed', 'interrupted', 'queued', 'retrying', 'stopped', 'working']).each do |status| %>
|
|
65
|
+
<option data-url="?<%= qparams(status: status)%>" value="<%= status %>" <%= 'selected="selected"' if status == (params[:status]) %>><%= status %></option>
|
|
66
|
+
<% end %>
|
|
67
|
+
</select>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
60
70
|
<div class="per-page">
|
|
61
71
|
Per page:
|
|
62
72
|
<select class="form-control" onchange="setPerPage(this)">
|
|
@@ -67,11 +77,11 @@ function setPerPage(select){
|
|
|
67
77
|
</div>
|
|
68
78
|
</div>
|
|
69
79
|
</div>
|
|
70
|
-
<table class="table table-hover table-bordered table-striped
|
|
80
|
+
<table class="table table-hover table-bordered table-striped">
|
|
71
81
|
<tr>
|
|
72
|
-
<% @headers.each do |
|
|
73
|
-
<th class="header <%= h[:class] %> header_<%= h[:id] %>">
|
|
74
|
-
<a href="<%= h[:url] %>"><%= h[:name] %></a>
|
|
82
|
+
<% @headers.each do |hdr| %>
|
|
83
|
+
<th class="header <%= h hdr[:class] %> header_<%= h hdr[:id] %>">
|
|
84
|
+
<a href="<%= h hdr[:url] %>"><%= h hdr[:name] %></a>
|
|
75
85
|
</th>
|
|
76
86
|
<% end %>
|
|
77
87
|
<th class="header">
|
|
@@ -81,13 +91,13 @@ function setPerPage(select){
|
|
|
81
91
|
<% @statuses.each do |container| %>
|
|
82
92
|
<tr>
|
|
83
93
|
<td>
|
|
84
|
-
<div title='<%= container["jid"] %>'><a href="<%= root_path %>statuses/<%= container["jid"] %>"><%= container["worker"] %></a></div>
|
|
94
|
+
<div title='<%= h container["jid"] %>'><a href="<%= root_path %>statuses/<%= h container["jid"] %>"><%= h container["worker"] %></a></div>
|
|
85
95
|
</td>
|
|
86
96
|
<td>
|
|
87
|
-
<div class='args' title='<%= container["jid"] %>'><%= container["args"] %></div>
|
|
97
|
+
<div class='args' title='<%= h container["jid"] %>'><%= h container["args"] %></div>
|
|
88
98
|
</td>
|
|
89
99
|
<td style='text-align: center;'>
|
|
90
|
-
<div class='label label-<%= container["label"] %>'><%= container["status"] %></div>
|
|
100
|
+
<div class='label label-<%= h container["label"] %>'><%= h container["status"] %></div>
|
|
91
101
|
</td>
|
|
92
102
|
<% secs = Time.now.to_i - container["update_time"].to_i %>
|
|
93
103
|
<td style='text-align: center; white-space: nowrap;' title="<%= Time.at(container["update_time"].to_i) %>">
|
|
@@ -100,11 +110,11 @@ function setPerPage(select){
|
|
|
100
110
|
<td>
|
|
101
111
|
<div class="progress progress-striped" style="margin-bottom: 0">
|
|
102
112
|
<div class='message' style='text-align:right; padding-right:0.5em; background-color: transparent; float:right;'>
|
|
103
|
-
<%= container["message"] %>
|
|
113
|
+
<%= h container["message"] %>
|
|
104
114
|
</div>
|
|
105
115
|
<% if container["pct_complete"].to_i > 0 %>
|
|
106
|
-
<div class="bar message" style="width: <%= container["pct_complete"] %>%;">
|
|
107
|
-
<%= container["pct_complete"] %>%
|
|
116
|
+
<div class="bar message" style="width: <%= h container["pct_complete"] %>%;">
|
|
117
|
+
<%= h container["pct_complete"] %>%
|
|
108
118
|
</div>
|
|
109
119
|
<% end %>
|
|
110
120
|
</div>
|
|
@@ -112,7 +122,7 @@ function setPerPage(select){
|
|
|
112
122
|
<td>
|
|
113
123
|
<div class="actions">
|
|
114
124
|
<form action="statuses" method="post">
|
|
115
|
-
<input type="hidden" name="jid" value="<%= container["jid"] %>" />
|
|
125
|
+
<input type="hidden" name="jid" value="<%= h container["jid"] %>" />
|
|
116
126
|
<%= csrf_tag %>
|
|
117
127
|
<% if container["status"] == "complete" %>
|
|
118
128
|
<input type="hidden" name="_method" value="delete" />
|
metadata
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sidekiq-status
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 2.1.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Evgeniy Tsvigun
|
|
8
8
|
- Kenaniah Cerny
|
|
9
|
-
autorequire:
|
|
9
|
+
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date:
|
|
12
|
+
date: 2022-02-03 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: sidekiq
|
|
@@ -17,14 +17,14 @@ dependencies:
|
|
|
17
17
|
requirements:
|
|
18
18
|
- - ">="
|
|
19
19
|
- !ruby/object:Gem::Version
|
|
20
|
-
version: '
|
|
20
|
+
version: '5.0'
|
|
21
21
|
type: :runtime
|
|
22
22
|
prerelease: false
|
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
|
24
24
|
requirements:
|
|
25
25
|
- - ">="
|
|
26
26
|
- !ruby/object:Gem::Version
|
|
27
|
-
version: '
|
|
27
|
+
version: '5.0'
|
|
28
28
|
- !ruby/object:Gem::Dependency
|
|
29
29
|
name: chronic_duration
|
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -123,7 +123,7 @@ dependencies:
|
|
|
123
123
|
- - ">="
|
|
124
124
|
- !ruby/object:Gem::Version
|
|
125
125
|
version: '0'
|
|
126
|
-
description:
|
|
126
|
+
description:
|
|
127
127
|
email:
|
|
128
128
|
- utgarda@gmail.com
|
|
129
129
|
- kenaniah@gmail.com
|
|
@@ -132,6 +132,7 @@ extensions: []
|
|
|
132
132
|
extra_rdoc_files: []
|
|
133
133
|
files:
|
|
134
134
|
- ".gitignore"
|
|
135
|
+
- ".gitlab-ci.yml"
|
|
135
136
|
- ".rspec"
|
|
136
137
|
- ".travis.yml"
|
|
137
138
|
- Appraisals
|
|
@@ -140,9 +141,9 @@ files:
|
|
|
140
141
|
- LICENSE
|
|
141
142
|
- README.md
|
|
142
143
|
- Rakefile
|
|
143
|
-
- gemfiles/sidekiq_3.x.gemfile
|
|
144
|
-
- gemfiles/sidekiq_4.x.gemfile
|
|
145
144
|
- gemfiles/sidekiq_5.x.gemfile
|
|
145
|
+
- gemfiles/sidekiq_6.1.gemfile
|
|
146
|
+
- gemfiles/sidekiq_6.x.gemfile
|
|
146
147
|
- lib/sidekiq-status.rb
|
|
147
148
|
- lib/sidekiq-status/client_middleware.rb
|
|
148
149
|
- lib/sidekiq-status/server_middleware.rb
|
|
@@ -167,11 +168,11 @@ files:
|
|
|
167
168
|
- web/views/status.erb
|
|
168
169
|
- web/views/status_not_found.erb
|
|
169
170
|
- web/views/statuses.erb
|
|
170
|
-
homepage:
|
|
171
|
+
homepage: https://github.com/kenaniah/sidekiq-status
|
|
171
172
|
licenses:
|
|
172
173
|
- MIT
|
|
173
174
|
metadata: {}
|
|
174
|
-
post_install_message:
|
|
175
|
+
post_install_message:
|
|
175
176
|
rdoc_options: []
|
|
176
177
|
require_paths:
|
|
177
178
|
- lib
|
|
@@ -186,9 +187,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
186
187
|
- !ruby/object:Gem::Version
|
|
187
188
|
version: '0'
|
|
188
189
|
requirements: []
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
signing_key:
|
|
190
|
+
rubygems_version: 3.2.32
|
|
191
|
+
signing_key:
|
|
192
192
|
specification_version: 4
|
|
193
193
|
summary: An extension to the sidekiq message processing to track your jobs
|
|
194
194
|
test_files:
|