sidekiq-status 0.5.4 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -2
- data/CHANGELOG.md +23 -0
- data/Gemfile +4 -0
- data/README.md +35 -10
- data/lib/sidekiq-status.rb +2 -2
- data/lib/sidekiq-status/client_middleware.rb +17 -2
- data/lib/sidekiq-status/server_middleware.rb +3 -0
- data/lib/sidekiq-status/storage.rb +2 -3
- data/lib/sidekiq-status/version.rb +1 -1
- data/lib/sidekiq-status/web.rb +43 -22
- data/spec/lib/sidekiq-status/client_middleware_spec.rb +14 -0
- data/spec/lib/sidekiq-status/server_middleware_spec.rb +28 -1
- data/spec/lib/sidekiq-status/web_spec.rb +4 -1
- data/spec/lib/sidekiq-status_spec.rb +1 -0
- data/spec/spec_helper.rb +5 -3
- data/spec/support/test_jobs.rb +12 -0
- data/web/sidekiq-status-web.png +0 -0
- data/web/views/statuses.erb +25 -12
- metadata +5 -4
- data/CHANGELOG +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c3bd23f9fe0e80f8354ca3860fbeb5e5f7ca44d
|
4
|
+
data.tar.gz: 1ad626cad36a7f56fab5f4ca89350c55879a2d86
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 46cbab187b63bc2fb458e7530180a7f0b41858067213346297ec45dc62bdd04db997b2e2031205cf426d3e6eafe9921c4d22491cbcb7f86be0dda4875e3ac8d6
|
7
|
+
data.tar.gz: e187d76f19d38d903df4258d8a55627da09e5cf4a9faf20b51ce16f682206cbe526142a4c88b8abb3fa993ab2bca7e21866dcd9e5e4591fe937fb3ce7c1810cb
|
data/.travis.yml
CHANGED
@@ -3,13 +3,14 @@ rvm:
|
|
3
3
|
- 2.0
|
4
4
|
- 2.1
|
5
5
|
- 2.2
|
6
|
-
- jruby
|
7
6
|
- rbx-2
|
8
7
|
gemfile:
|
9
8
|
- gemfiles/Gemfile.sidekiq-2
|
10
9
|
- Gemfile
|
10
|
+
before_install:
|
11
|
+
- gem update --system
|
12
|
+
- gem update bundler
|
11
13
|
services: redis
|
12
14
|
matrix:
|
13
15
|
allow_failures:
|
14
|
-
- rvm: jruby
|
15
16
|
- rvm: rbx-2
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Version 0.6.0
|
2
|
+
+ Updated Web UI
|
3
|
+
+ Will have all job statuses, previously it was showing only :working status
|
4
|
+
+ Bootstrap lables instead of badges for status
|
5
|
+
+ Added Arguments column to statuses page
|
6
|
+
+ New :interrupted status added
|
7
|
+
+ Added way to specify :expiration for Sidekiq::Status::ClientMiddleware
|
8
|
+
+ Bug fixes & Code cleaup
|
9
|
+
|
10
|
+
Version 0.5.3
|
11
|
+
+ some tweaks in web UI, separate redis namespace
|
12
|
+
|
13
|
+
Version 0.5.2
|
14
|
+
+ Sidekiq versions up to 3.3.* supported, jobs sorting options in web UI, more ruby versions
|
15
|
+
|
16
|
+
Version 0.5.1
|
17
|
+
+ dependencies versions requirements relaxed
|
18
|
+
|
19
|
+
Version 0.5.0
|
20
|
+
+ Sidekiq v3 support, redis pools support
|
21
|
+
|
22
|
+
Version 0.4.0
|
23
|
+
+ WebUI added, per-worker expiration setting enabled
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
[![Gem Version](https://badge.fury.io/rb/sidekiq-status.png)](http://badge.fury.io/rb/sidekiq-status)
|
3
3
|
[![Code Climate](https://codeclimate.com/github/utgarda/sidekiq-status.png)](https://codeclimate.com/github/utgarda/sidekiq-status)
|
4
4
|
[![Build Status](https://secure.travis-ci.org/utgarda/sidekiq-status.png)](http://travis-ci.org/utgarda/sidekiq-status)
|
5
|
+
[![Dependency Status](https://gemnasium.com/utgarda/sidekiq-status.svg)](https://gemnasium.com/utgarda/sidekiq-status)
|
6
|
+
[![Inline docs](http://inch-ci.org/github/utgarda/sidekiq-status.svg?branch=master)](http://inch-ci.org/github/utgarda/sidekiq-status)
|
5
7
|
|
6
8
|
An extension to [Sidekiq](http://github.com/mperham/sidekiq) message processing to track your jobs. Inspired
|
7
9
|
by [resque-status](http://github.com/quirkey/resque-status) and mostly copying its features, using Sidekiq's middleware.
|
@@ -23,16 +25,19 @@ require 'sidekiq-status'
|
|
23
25
|
|
24
26
|
Sidekiq.configure_client do |config|
|
25
27
|
config.client_middleware do |chain|
|
26
|
-
|
28
|
+
# accepts :expiration (optional)
|
29
|
+
chain.add Sidekiq::Status::ClientMiddleware, expiration: 30.minutes # default
|
27
30
|
end
|
28
31
|
end
|
29
32
|
|
30
33
|
Sidekiq.configure_server do |config|
|
31
34
|
config.server_middleware do |chain|
|
35
|
+
# accepts :expiration (optional)
|
32
36
|
chain.add Sidekiq::Status::ServerMiddleware, expiration: 30.minutes # default
|
33
37
|
end
|
34
38
|
config.client_middleware do |chain|
|
35
|
-
|
39
|
+
# accepts :expiration (optional)
|
40
|
+
chain.add Sidekiq::Status::ClientMiddleware, expiration: 30.minutes # default
|
36
41
|
end
|
37
42
|
end
|
38
43
|
```
|
@@ -67,21 +72,32 @@ end
|
|
67
72
|
|
68
73
|
But keep in mind that such thing will store details of job as long as expiration is set, so it may charm your Redis storage/memory consumption. Because Redis stores all data in RAM.
|
69
74
|
|
75
|
+
### What is expiration time ?
|
76
|
+
As you noticed you can set expiration time for jobs globally by expiration option while adding middleware or writing a expiration method on each worker this expiration time is nothing but
|
77
|
+
|
78
|
+
+ [Redis expire time](http://redis.io/commands/expire), also know as TTL(time to live)
|
79
|
+
+ After expiration time all the info like status, update_time etc. about the worker disappears.
|
80
|
+
+ It is advised to set this expiration time greater than time required for completion of the job.
|
81
|
+
+ Default expiration time is 30 minutes.
|
82
|
+
|
70
83
|
### Retrieving status
|
71
84
|
|
72
85
|
Query for job status any time later:
|
73
86
|
|
74
87
|
``` ruby
|
75
88
|
job_id = MyJob.perform_async(*args)
|
76
|
-
# :queued, :working, :complete or :
|
89
|
+
# :queued, :working, :complete, :failed or :interrupted, nil after expiry (30 minutes)
|
77
90
|
status = Sidekiq::Status::status(job_id)
|
78
|
-
Sidekiq::Status::queued?
|
79
|
-
Sidekiq::Status::working?
|
80
|
-
Sidekiq::Status::complete?
|
81
|
-
Sidekiq::Status::failed?
|
91
|
+
Sidekiq::Status::queued? job_id
|
92
|
+
Sidekiq::Status::working? job_id
|
93
|
+
Sidekiq::Status::complete? job_id
|
94
|
+
Sidekiq::Status::failed? job_id
|
95
|
+
Sidekiq::Status::interrupted? job_id
|
96
|
+
|
82
97
|
```
|
98
|
+
Important: If you try any of the above status method after the expiration time, will result into `nil` or `false`
|
83
99
|
|
84
|
-
### Tracking progress, saving and
|
100
|
+
### Tracking progress, saving, and retrieving data associated with job
|
85
101
|
|
86
102
|
``` ruby
|
87
103
|
class MyJob
|
@@ -118,13 +134,21 @@ Sidekiq::Status::pct_complete job_id #=> 5
|
|
118
134
|
```ruby
|
119
135
|
scheduled_job_id = MyJob.perform_in 3600
|
120
136
|
Sidekiq::Status.cancel scheduled_job_id #=> true
|
121
|
-
#doesn't cancel running jobs, this is more like unscheduling, therefore an alias:
|
137
|
+
# doesn't cancel running jobs, this is more like unscheduling, therefore an alias:
|
122
138
|
Sidekiq::Status.unschedule scheduled_job_id #=> true
|
139
|
+
|
140
|
+
# returns false if invalid or wrong scheduled_job_id is provided
|
141
|
+
Sidekiq::Status.unschedule some_other_unschedule_job_id #=> false
|
142
|
+
Sidekiq::Status.unschedule nil #=> false
|
143
|
+
Sidekiq::Status.unschedule '' #=> false
|
144
|
+
# Note: cancel and unschedule are alias methods.
|
123
145
|
```
|
146
|
+
Important: If you try any of the status method after the expiration time for scheduled jobs, will result into `nil` or `false`. But job will be in sidekiq's scheduled queue and will execute normally, once job is started on scheduled time you will get status info for job till expiration time defined on `Sidekiq::Status::ServerMiddleware`.
|
124
147
|
|
125
148
|
### Sidekiq web integration
|
126
149
|
|
127
|
-
Sidekiq::Status also provides an extension to Sidekiq web interface with a `/statuses
|
150
|
+
Sidekiq::Status also provides an extension to Sidekiq web interface with a `/statuses`.
|
151
|
+
![Sidekiq Status Web](https://raw.github.com/utgarda/sidekiq-status/master/web/sidekiq-status-web.png)
|
128
152
|
|
129
153
|
Setup Sidekiq web interface according to Sidekiq documentation and add the Sidekiq::Status::Web require:
|
130
154
|
|
@@ -158,6 +182,7 @@ To use `sidekiq-status` inlining, require it too in your `{test,spec}_helper.rb`
|
|
158
182
|
* Stopping jobs by id
|
159
183
|
|
160
184
|
## Thanks
|
185
|
+
* Pramod Shinde
|
161
186
|
* Clay Allsopp
|
162
187
|
* Andrew Korzhuev
|
163
188
|
* Jon Moses
|
data/lib/sidekiq-status.rb
CHANGED
@@ -8,7 +8,7 @@ require 'sidekiq-status/web' if defined?(Sidekiq::Web)
|
|
8
8
|
module Sidekiq::Status
|
9
9
|
extend Storage
|
10
10
|
DEFAULT_EXPIRY = 60 * 30
|
11
|
-
STATUS =
|
11
|
+
STATUS = [ :queued, :working, :complete, :stopped, :failed, :interrupted ].freeze
|
12
12
|
|
13
13
|
class << self
|
14
14
|
# Job status by id
|
@@ -52,7 +52,7 @@ module Sidekiq::Status
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def pct_complete(job_id)
|
55
|
-
(at(job_id)
|
55
|
+
((at(job_id) / total(job_id).to_f) * 100 ).to_i if total(job_id).to_f > 0
|
56
56
|
end
|
57
57
|
|
58
58
|
def message(job_id)
|
@@ -2,14 +2,29 @@ module Sidekiq::Status
|
|
2
2
|
# Should be in the client middleware chain
|
3
3
|
class ClientMiddleware
|
4
4
|
include Storage
|
5
|
+
|
6
|
+
# Parameterized initialization, use it when adding middleware to client chain
|
7
|
+
# chain.add Sidekiq::Status::ClientMiddleware, :expiration => 60 * 5
|
8
|
+
# @param [Hash] opts middleware initialization options
|
9
|
+
# @option opts [Fixnum] :expiration ttl for complete jobs
|
10
|
+
def initialize(opts = {})
|
11
|
+
@expiration = opts[:expiration]
|
12
|
+
end
|
13
|
+
|
5
14
|
# Uses msg['jid'] id and puts :queued status in the job's Redis hash
|
6
15
|
# @param [Class] worker_class if includes Sidekiq::Status::Worker, the job gets processed with the plugin
|
7
16
|
# @param [Array] msg job arguments
|
8
17
|
# @param [String] queue the queue's name
|
9
18
|
# @param [ConnectionPool] redis_pool optional redis connection pool
|
10
19
|
def call(worker_class, msg, queue, redis_pool=nil)
|
11
|
-
|
20
|
+
initial_metadata = {
|
21
|
+
jid: msg['jid'],
|
22
|
+
status: :queued,
|
23
|
+
worker: worker_class,
|
24
|
+
args: msg['args'].to_a.empty? ? nil : msg['args'].to_json
|
25
|
+
}
|
26
|
+
store_for_id msg['jid'], initial_metadata, @expiration, redis_pool
|
12
27
|
yield
|
13
28
|
end
|
14
29
|
end
|
15
|
-
end
|
30
|
+
end
|
@@ -38,6 +38,9 @@ module Sidekiq::Status
|
|
38
38
|
store_status worker.jid, :complete, @expiration
|
39
39
|
rescue Worker::Stopped
|
40
40
|
store_status worker.jid, :stopped, @expiration
|
41
|
+
rescue SystemExit, Interrupt
|
42
|
+
store_status worker.jid, :interrupted, @expiration
|
43
|
+
raise
|
41
44
|
rescue
|
42
45
|
store_status worker.jid, :failed, @expiration
|
43
46
|
raise
|
@@ -58,7 +58,7 @@ module Sidekiq::Status::Storage
|
|
58
58
|
# @return [String] Redis operation status code
|
59
59
|
def read_field_for_id(id, field)
|
60
60
|
Sidekiq.redis do |conn|
|
61
|
-
conn.
|
61
|
+
conn.hget(key(id), field)
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
@@ -91,8 +91,7 @@ module Sidekiq::Status::Storage
|
|
91
91
|
# A Little skecthy, I know, but the structure of these internal JSON
|
92
92
|
# is predefined in such a way where this will not catch unintentional elements,
|
93
93
|
# and this is notably faster than performing JSON.parse() for every listing:
|
94
|
-
scheduled_jobs.
|
95
|
-
nil
|
94
|
+
scheduled_jobs.select { |job_listing| job_listing.match(/\"jid\":\"#{job_id}\"/) }[0]
|
96
95
|
end
|
97
96
|
|
98
97
|
# Yields redis connection. Uses redis pool if available.
|
data/lib/sidekiq-status/web.rb
CHANGED
@@ -13,44 +13,65 @@ module Sidekiq::Status
|
|
13
13
|
path = File.join(VIEW_PATH, name.to_s) + ".erb"
|
14
14
|
File.open(path).read
|
15
15
|
end
|
16
|
+
|
17
|
+
def add_details_to_status(status)
|
18
|
+
status['label'] = status_label(status['status'])
|
19
|
+
status["pct_complete"] = pct_complete(status)
|
20
|
+
return status
|
21
|
+
end
|
22
|
+
|
23
|
+
def pct_complete(status)
|
24
|
+
return 100 if status['status'] == 'complete'
|
25
|
+
Sidekiq::Status::pct_complete(status['jid'])
|
26
|
+
end
|
27
|
+
|
28
|
+
def status_label(status)
|
29
|
+
case status
|
30
|
+
when 'complete'
|
31
|
+
'success'
|
32
|
+
when 'working'
|
33
|
+
'warning'
|
34
|
+
when 'queued'
|
35
|
+
'primary'
|
36
|
+
else
|
37
|
+
'danger'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def has_sort_by?(value)
|
42
|
+
["worker", "status", "update_time", "pct_complete", "message"].include?(value)
|
43
|
+
end
|
16
44
|
end
|
17
45
|
|
18
46
|
app.get '/statuses' do
|
19
|
-
|
47
|
+
namespace_jids = Sidekiq.redis{ |conn| conn.keys('sidekiq:status:*') }
|
48
|
+
jids = namespace_jids.map{|id_namespace| id_namespace.split(':').last }
|
20
49
|
@statuses = []
|
21
50
|
|
22
|
-
|
23
|
-
|
24
|
-
# For sidekiq < 3
|
25
|
-
args[1]
|
26
|
-
else
|
27
|
-
args[2]
|
28
|
-
end
|
29
|
-
job = Struct.new(:jid, :klass, :args).new(work["payload"]["jid"], work["payload"]["class"], work["payload"]["args"])
|
30
|
-
status = Sidekiq::Status::get_all job.jid
|
51
|
+
jids.each do |jid|
|
52
|
+
status = Sidekiq::Status::get_all jid
|
31
53
|
next if !status || status.count < 2
|
32
|
-
status
|
33
|
-
status["args"] = job.args
|
34
|
-
status["jid"] = job.jid
|
35
|
-
status["pct_complete"] = ((status["at"].to_f / status["total"].to_f) * 100).to_i if status["total"].to_f > 0
|
54
|
+
status = add_details_to_status(status)
|
36
55
|
@statuses << OpenStruct.new(status)
|
37
56
|
end
|
38
57
|
|
39
|
-
|
40
|
-
sort_by = params[:sort_by]
|
41
|
-
else
|
42
|
-
sort_by = "worker"
|
43
|
-
end
|
44
|
-
|
58
|
+
sort_by = has_sort_by?(params[:sort_by]) ? params[:sort_by] : "update_time"
|
45
59
|
sort_dir = "asc"
|
46
60
|
|
47
61
|
if params[:sort_dir] == "asc"
|
48
62
|
@statuses = @statuses.sort { |x,y| x.send(sort_by) <=> y.send(sort_by) }
|
49
|
-
else
|
63
|
+
else
|
50
64
|
sort_dir = "desc"
|
51
65
|
@statuses = @statuses.sort { |y,x| x.send(sort_by) <=> y.send(sort_by) }
|
52
66
|
end
|
53
|
-
|
67
|
+
|
68
|
+
working_jobs = @statuses.select{|job| job.status == "working"}
|
69
|
+
if working_jobs.size >= 25
|
70
|
+
@statuses = working_jobs
|
71
|
+
else
|
72
|
+
@statuses = (@statuses.size >= 25) ? @statuses.take(25) : @statuses
|
73
|
+
end
|
74
|
+
|
54
75
|
@headers = [
|
55
76
|
{ id: "worker", name: "Worker/jid", class: nil, url: nil},
|
56
77
|
{ id: "status", name: "Status", class: nil, url: nil},
|
@@ -9,6 +9,7 @@ describe Sidekiq::Status::ClientMiddleware do
|
|
9
9
|
before { redis.flushall }
|
10
10
|
|
11
11
|
describe "#call" do
|
12
|
+
before { client_middleware }
|
12
13
|
it "sets queued status" do
|
13
14
|
allow(SecureRandom).to receive(:hex).once.and_return(job_id)
|
14
15
|
expect(StubJob.perform_async(:arg1 => 'val1')).to eq(job_id)
|
@@ -38,4 +39,17 @@ describe Sidekiq::Status::ClientMiddleware do
|
|
38
39
|
end
|
39
40
|
end
|
40
41
|
end
|
42
|
+
|
43
|
+
describe ":expiration parameter" do
|
44
|
+
let(:huge_expiration) { Sidekiq::Status::DEFAULT_EXPIRY * 100 }
|
45
|
+
before do
|
46
|
+
allow(SecureRandom).to receive(:hex).once.and_return(job_id)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "overwrites default expiry value" do
|
50
|
+
client_middleware(expiration: huge_expiration)
|
51
|
+
StubJob.perform_async(:arg1 => 'val1')
|
52
|
+
expect((Sidekiq::Status::DEFAULT_EXPIRY+1)..huge_expiration).to cover redis.ttl("sidekiq:status:#{job_id}")
|
53
|
+
end
|
54
|
+
end
|
41
55
|
end
|
@@ -35,9 +35,36 @@ describe Sidekiq::Status::ServerMiddleware do
|
|
35
35
|
expect(Sidekiq::Status::failed?(job_id)).to be_truthy
|
36
36
|
end
|
37
37
|
|
38
|
+
context "sets interrupted status" do
|
39
|
+
it "on system exit signal" do
|
40
|
+
allow(SecureRandom).to receive(:hex).once.and_return(job_id)
|
41
|
+
start_server do
|
42
|
+
expect(capture_status_updates(3) {
|
43
|
+
expect(ExitedJob.perform_async).to eq(job_id)
|
44
|
+
}).to eq([job_id]*3)
|
45
|
+
end
|
46
|
+
expect(redis.hget("sidekiq:status:#{job_id}", :status)).to eq('interrupted')
|
47
|
+
expect(Sidekiq::Status::interrupted?(job_id)).to be_truthy
|
48
|
+
end
|
49
|
+
|
50
|
+
it "on interrupt signal" do
|
51
|
+
allow(SecureRandom).to receive(:hex).once.and_return(job_id)
|
52
|
+
start_server do
|
53
|
+
expect(capture_status_updates(3) {
|
54
|
+
expect(InterruptedJob.perform_async).to eq(job_id)
|
55
|
+
}).to eq([job_id]*3)
|
56
|
+
end
|
57
|
+
expect(redis.hget("sidekiq:status:#{job_id}", :status)).to eq('interrupted')
|
58
|
+
expect(Sidekiq::Status::interrupted?(job_id)).to be_truthy
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
38
63
|
it "sets status hash ttl" do
|
39
64
|
allow(SecureRandom).to receive(:hex).once.and_return(job_id)
|
40
|
-
|
65
|
+
start_server do
|
66
|
+
expect(StubJob.perform_async(:arg1 => 'val1')).to eq(job_id)
|
67
|
+
end
|
41
68
|
expect(1..Sidekiq::Status::DEFAULT_EXPIRY).to cover redis.ttl("sidekiq:status:#{job_id}")
|
42
69
|
end
|
43
70
|
end
|
@@ -18,7 +18,8 @@ describe 'sidekiq status web' do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'shows a job in progress' do
|
21
|
-
|
21
|
+
client_middleware
|
22
|
+
allow(SecureRandom).to receive(:hex).and_return(job_id)
|
22
23
|
|
23
24
|
start_server do
|
24
25
|
capture_status_updates(2) do
|
@@ -28,6 +29,8 @@ describe 'sidekiq status web' do
|
|
28
29
|
get '/statuses'
|
29
30
|
expect(last_response).to be_ok
|
30
31
|
expect(last_response.body).to match(/#{job_id}/)
|
32
|
+
expect(last_response.body).to match(/LongJob/)
|
33
|
+
expect(last_response.body).to match(/working/)
|
31
34
|
end
|
32
35
|
end
|
33
36
|
|
@@ -28,6 +28,7 @@ describe Sidekiq::Status do
|
|
28
28
|
expect(Sidekiq::Status::failed?(job_id)).to be_falsey
|
29
29
|
expect(Sidekiq::Status::complete?(job_id)).to be_falsey
|
30
30
|
expect(Sidekiq::Status::stopped?(job_id)).to be_falsey
|
31
|
+
expect(Sidekiq::Status::interrupted?(job_id)).to be_falsey
|
31
32
|
end
|
32
33
|
expect(Sidekiq::Status.status(job_id)).to eq(:complete)
|
33
34
|
expect(Sidekiq::Status.complete?(job_id)).to be_truthy
|
data/spec/spec_helper.rb
CHANGED
@@ -9,9 +9,11 @@ require 'sidekiq-status'
|
|
9
9
|
|
10
10
|
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
def client_middleware(client_middleware_options={})
|
13
|
+
Sidekiq.configure_client do |config|
|
14
|
+
config.client_middleware do |chain|
|
15
|
+
chain.add Sidekiq::Status::ClientMiddleware, client_middleware_options
|
16
|
+
end
|
15
17
|
end
|
16
18
|
end
|
17
19
|
|
data/spec/support/test_jobs.rb
CHANGED
@@ -54,6 +54,18 @@ class FailingJob < StubJob
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
+
class ExitedJob < StubJob
|
58
|
+
def perform
|
59
|
+
raise SystemExit
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class InterruptedJob < StubJob
|
64
|
+
def perform
|
65
|
+
raise Interrupt
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
57
69
|
class RetriedJob < StubJob
|
58
70
|
sidekiq_options 'retry' => 'true'
|
59
71
|
def perform()
|
Binary file
|
data/web/views/statuses.erb
CHANGED
@@ -5,28 +5,39 @@
|
|
5
5
|
}
|
6
6
|
.bar {
|
7
7
|
background-color: #2897cb;
|
8
|
+
color: white;
|
9
|
+
text-shadow: 0 0 0;
|
8
10
|
}
|
9
11
|
.message {
|
10
12
|
text-shadow: 0 0 5px white;
|
11
13
|
font-weight: bold; padding-left: 4px;
|
12
14
|
color: #333;
|
13
15
|
}
|
16
|
+
.header{
|
17
|
+
text-align: center;
|
18
|
+
}
|
14
19
|
</style>
|
15
20
|
|
16
21
|
<h3 class="wi">Recent job statuses</h3>
|
17
|
-
|
18
|
-
|
19
|
-
<table class="table table-striped table-bordered">
|
22
|
+
<table class="table table-hover table-bordered table-striped table-white">
|
20
23
|
<tr>
|
21
|
-
<th>Worker/jid</th>
|
22
|
-
<th
|
23
|
-
<th
|
24
|
-
<th style=
|
24
|
+
<th class="header">Worker/jid</th>
|
25
|
+
<th class="header">Arguments</th>
|
26
|
+
<th class="header">Status</th>
|
27
|
+
<th class="header" style="width: 10%;">Last Updated</th>
|
28
|
+
<th class="header" style="width: 45%;">Progress</th>
|
25
29
|
</tr>
|
26
30
|
<% @statuses.each do |container| %>
|
27
31
|
<tr>
|
28
|
-
<td
|
29
|
-
|
32
|
+
<td>
|
33
|
+
<div title='<%= container.jid %>'><%= container.worker %></div>
|
34
|
+
</td>
|
35
|
+
<td>
|
36
|
+
<div class='args' title='<%= container.jid %>'><%= container.args %></div>
|
37
|
+
</td>
|
38
|
+
<td style='text-align: center;'>
|
39
|
+
<div class='label label-<%= container.label %>'><%= container.status %></div>
|
40
|
+
</td>
|
30
41
|
<% secs = Time.now.to_i - container.update_time.to_i %>
|
31
42
|
<td style='text-align: center;'>
|
32
43
|
<% if secs > 0 %>
|
@@ -37,9 +48,11 @@
|
|
37
48
|
</td>
|
38
49
|
<td>
|
39
50
|
<div class="progress progress-striped" style="margin-bottom: 0">
|
40
|
-
<div class='message' style='text-align:right; padding-right:0.5em; background-color: transparent; float:right;'
|
51
|
+
<div class='message' style='text-align:right; padding-right:0.5em; background-color: transparent; float:right;'>
|
52
|
+
<%= container.message %>
|
53
|
+
</div>
|
41
54
|
<% if container.pct_complete.to_i > 0 %>
|
42
|
-
<div class="bar message" style="width: <%= container.pct_complete %>%;
|
55
|
+
<div class="bar message" style="width: <%= container.pct_complete %>%;">
|
43
56
|
<%= container.pct_complete %>%
|
44
57
|
</div>
|
45
58
|
<% end %>
|
@@ -52,4 +65,4 @@
|
|
52
65
|
<td colspan="6"></td>
|
53
66
|
</tr>
|
54
67
|
<% end %>
|
55
|
-
</table>
|
68
|
+
</table>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq-status
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evgeniy Tsvigun
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sidekiq
|
@@ -90,7 +90,7 @@ files:
|
|
90
90
|
- ".gitignore"
|
91
91
|
- ".rspec"
|
92
92
|
- ".travis.yml"
|
93
|
-
- CHANGELOG
|
93
|
+
- CHANGELOG.md
|
94
94
|
- Gemfile
|
95
95
|
- LICENSE
|
96
96
|
- README.md
|
@@ -113,6 +113,7 @@ files:
|
|
113
113
|
- spec/lib/sidekiq-status_spec.rb
|
114
114
|
- spec/spec_helper.rb
|
115
115
|
- spec/support/test_jobs.rb
|
116
|
+
- web/sidekiq-status-web.png
|
116
117
|
- web/views/statuses.erb
|
117
118
|
homepage: http://github.com/utgarda/sidekiq-status
|
118
119
|
licenses:
|
@@ -134,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
134
135
|
version: '0'
|
135
136
|
requirements: []
|
136
137
|
rubyforge_project:
|
137
|
-
rubygems_version: 2.4.5
|
138
|
+
rubygems_version: 2.4.5.1
|
138
139
|
signing_key:
|
139
140
|
specification_version: 4
|
140
141
|
summary: An extension to the sidekiq message processing to track your jobs
|
data/CHANGELOG
DELETED
@@ -1,6 +0,0 @@
|
|
1
|
-
Version 0.5.4:Mere removal of sidekiq version upper limitation
|
2
|
-
Version 0.5.3:Sidekiq some tweaks in web UI, separate redis namespace
|
3
|
-
Version 0.5.2:Sidekiq versions up to 3.3.* supported, jobs sorting options in web UI, more ruby versions
|
4
|
-
Version 0.5.1:dependencies versions requirements relaxed
|
5
|
-
Version 0.5.0:Sidekiq v3 support, redis pools support
|
6
|
-
Version 0.4.0:WebUI added, per-worker expiration setting enabled
|