sidekiq-status 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 70899fafcf4e5aa712b2df57e34700cba6d001fe
4
+ data.tar.gz: cd4801e8d4678b515f3a597438953c3430066a30
5
+ SHA512:
6
+ metadata.gz: 1669fb78f47cc77930d4b93f7c7a1537526d426cf0e99c4c5bb8b13e271ed66711e15276959a381216710aca8cfac60f90fc0790719db2c9a8f4c3faaa046a41
7
+ data.tar.gz: d7e697fdb8ee26e50f125b73b44abe2f5c796e74ad9242d76bc85964e526c33b9d81916fa49a3623c29bb55b2b9a5126b30db8e730c5668d34d1a6f7dbcfd024
data/CHANGELOG ADDED
@@ -0,0 +1 @@
1
+ Version 0.4.0:WebUI added, per-worker expiration setting enabled
data/README.md CHANGED
@@ -31,6 +31,9 @@ Sidekiq.configure_server do |config|
31
31
  config.server_middleware do |chain|
32
32
  chain.add Sidekiq::Status::ServerMiddleware, expiration: 30.minutes # default
33
33
  end
34
+ config.client_middleware do |chain|
35
+ chain.add Sidekiq::Status::ClientMiddleware
36
+ end
34
37
  end
35
38
  ```
36
39
 
@@ -46,6 +49,24 @@ class MyJob
46
49
  end
47
50
  ```
48
51
 
52
+ To overwrite expiration on worker basis and don't use global expiration for all workers write a expiration method like this below:
53
+
54
+ ``` ruby
55
+ class MyJob
56
+ include Sidekiq::Worker
57
+
58
+ def expiration
59
+ @expiration ||= 60*60*24*30 # 30 days
60
+ end
61
+
62
+ def perform(*args)
63
+ # your code goes here
64
+ end
65
+ end
66
+ ```
67
+
68
+ 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
+
49
70
  ### Retrieving status
50
71
 
51
72
  Query for job status any time later:
@@ -122,9 +143,9 @@ To use `sidekiq-status` inlining, require it too in your `{test,spec}_helper.rb`
122
143
 
123
144
  ### Features coming
124
145
  * Stopping jobs by id
125
- * Minimal web UI
126
146
 
127
147
  ## Thanks
148
+ * Clay Allsopp
128
149
  * Andrew Korzhuev
129
150
  * Jon Moses
130
151
  * Wayne Hoover
@@ -132,4 +153,4 @@ To use `sidekiq-status` inlining, require it too in your `{test,spec}_helper.rb`
132
153
 
133
154
  ## License
134
155
  MIT License , see LICENSE for more details.
135
- © 2012 - 2013 Evgeniy Tsvigun
156
+ © 2012 - 2014 Evgeniy Tsvigun
@@ -3,6 +3,7 @@ require 'sidekiq-status/storage'
3
3
  require 'sidekiq-status/worker'
4
4
  require 'sidekiq-status/client_middleware'
5
5
  require 'sidekiq-status/server_middleware'
6
+ require 'sidekiq-status/web' if defined?(Sidekiq::Web)
6
7
 
7
8
  module Sidekiq::Status
8
9
  extend Storage
@@ -24,7 +24,14 @@ module Sidekiq::Status
24
24
  def call(worker, msg, queue)
25
25
  # a way of overriding default expiration time,
26
26
  # so worker wouldn't lose its data
27
- worker.expiration = @expiration if worker.respond_to? :expiration
27
+ # and it allows also to overwrite global expiration time on worker basis
28
+ if worker.respond_to? :expiration
29
+ if !worker.expiration && worker.respond_to?(:expiration=)
30
+ worker.expiration = @expiration
31
+ else
32
+ @expiration = worker.expiration
33
+ end
34
+ end
28
35
 
29
36
  store_status worker.jid, :working, @expiration
30
37
  yield
@@ -1,5 +1,5 @@
1
1
  module Sidekiq
2
2
  module Status
3
- VERSION = "0.3.2"
3
+ VERSION = "0.4.0"
4
4
  end
5
5
  end
@@ -0,0 +1,46 @@
1
+ # adapted from https://github.com/cryo28/sidekiq_status
2
+
3
+ module Sidekiq::Status
4
+ # Hook into *Sidekiq::Web* Sinatra app which adds a new "/statuses" page
5
+ module Web
6
+ # Location of Sidekiq::Status::Web view templates
7
+ VIEW_PATH = File.expand_path('../../../web/views', __FILE__)
8
+
9
+ # @param [Sidekiq::Web] app
10
+ def self.registered(app)
11
+ app.helpers do
12
+ def sidekiq_status_template(name)
13
+ path = File.join(VIEW_PATH, name.to_s) + ".erb"
14
+ File.open(path).read
15
+ end
16
+ end
17
+
18
+ app.get '/statuses' do
19
+ queue = Sidekiq::Workers.new
20
+ @statuses = []
21
+
22
+ queue.each do |name, work, started_at|
23
+ job = Struct.new(:jid, :klass, :args).new(work["payload"]["jid"], work["payload"]["class"], work["payload"]["args"])
24
+ status = Sidekiq::Status::get_all job.jid
25
+ next if !status || status.count <= 2
26
+ status["worker"] = job.klass
27
+ status["args"] = job.args
28
+ status["jid"] = job.jid
29
+ status["pct_complete"] = ((status["num"].to_f / status["total"].to_f) * 100).to_i
30
+ @statuses << OpenStruct.new(status)
31
+ end
32
+
33
+ erb(sidekiq_status_template(:statuses))
34
+ end
35
+ end
36
+ end
37
+ end
38
+
39
+ require 'sidekiq/web' unless defined?(Sidekiq::Web)
40
+ Sidekiq::Web.register(Sidekiq::Status::Web)
41
+ if Sidekiq::Web.tabs.is_a?(Array)
42
+ # For sidekiq < 2.5
43
+ Sidekiq::Web.tabs << "statuses"
44
+ else
45
+ Sidekiq::Web.tabs["Statuses"] = "statuses"
46
+ end
@@ -40,6 +40,27 @@ describe Sidekiq::Status::ServerMiddleware do
40
40
  StubJob.perform_async(:arg1 => 'val1').should == job_id
41
41
  (1..Sidekiq::Status::DEFAULT_EXPIRY).should cover redis.ttl(job_id)
42
42
  end
43
+ end
44
+
45
+ describe ":expiration parameter" do
46
+ let(:huge_expiration) { Sidekiq::Status::DEFAULT_EXPIRY * 100 }
47
+ before do
48
+ SecureRandom.should_receive(:hex).once.and_return(job_id)
49
+ end
50
+ it "overwrites default expiry value" do
51
+ start_server(:expiration => huge_expiration) do
52
+ StubJob.perform_async(:arg1 => 'val1')
53
+ end
54
+ ((Sidekiq::Status::DEFAULT_EXPIRY+1)..huge_expiration).should cover redis.ttl(job_id)
55
+ end
43
56
 
57
+ it "can be overwritten by worker expiration method" do
58
+ overwritten_expiration = huge_expiration * 100
59
+ StubJob.any_instance.stub(expiration: overwritten_expiration)
60
+ start_server(:expiration => huge_expiration) do
61
+ StubJob.perform_async(:arg1 => 'val1')
62
+ end
63
+ ((huge_expiration+1)..overwritten_expiration).should cover redis.ttl(job_id)
64
+ end
44
65
  end
45
- end
66
+ end
@@ -10,4 +10,13 @@ describe Sidekiq::Status::Worker do
10
10
  StubJob.perform_async().should == job_id
11
11
  end
12
12
  end
13
- end
13
+
14
+ describe ".expiration" do
15
+ subject { StubJob.new }
16
+ it "allows to set/get expiration" do
17
+ expect(subject.expiration).to be_nil
18
+ subject.expiration = :val
19
+ expect(subject.expiration).to eq(:val)
20
+ end
21
+ end
22
+ end
@@ -120,19 +120,13 @@ describe Sidekiq::Status do
120
120
  end
121
121
 
122
122
  context "keeps normal Sidekiq functionality" do
123
+ let(:expiration_param) { nil }
124
+
123
125
  it "does jobs with and without included worker module" do
124
- SecureRandom.should_receive(:hex).exactly(4).times.and_return(plain_sidekiq_job_id, plain_sidekiq_job_id, job_id_1, job_id_1)
125
- start_server do
126
- capture_status_updates(12) {
127
- StubJob.perform_async.should == plain_sidekiq_job_id
128
- NoStatusConfirmationJob.perform_async(1)
129
- StubJob.perform_async.should == job_id_1
130
- NoStatusConfirmationJob.perform_async(2)
131
- }.should =~ [plain_sidekiq_job_id, job_id_1] * 6
132
- end
133
- redis.mget('NoStatusConfirmationJob_1', 'NoStatusConfirmationJob_2').should == %w(done)*2
134
- Sidekiq::Status.status(plain_sidekiq_job_id).should == :complete
135
- Sidekiq::Status.status(job_id_1).should == :complete
126
+ seed_secure_random_with_job_ids
127
+ run_2_jobs!
128
+ expect_2_jobs_are_done_and_status_eq :complete
129
+ expect_2_jobs_ttl_covers 1..Sidekiq::Status::DEFAULT_EXPIRY
136
130
  end
137
131
 
138
132
  it "retries failed jobs" do
@@ -144,6 +138,52 @@ describe Sidekiq::Status do
144
138
  end
145
139
  Sidekiq::Status.status(retried_job_id).should == :complete
146
140
  end
141
+
142
+ context ":expiration param" do
143
+ before { seed_secure_random_with_job_ids }
144
+ let(:expiration_param) { Sidekiq::Status::DEFAULT_EXPIRY * 100 }
145
+
146
+ it "allow to overwrite :expiration parameter" do
147
+ run_2_jobs!
148
+ expect_2_jobs_are_done_and_status_eq :complete
149
+ expect_2_jobs_ttl_covers (Sidekiq::Status::DEFAULT_EXPIRY+1)..expiration_param
150
+ end
151
+
152
+ it "allow to overwrite :expiration parameter by .expiration method from worker" do
153
+ overwritten_expiration = expiration_param * 100
154
+ NoStatusConfirmationJob.any_instance.stub(:expiration => overwritten_expiration)
155
+ StubJob.any_instance.stub(:expiration => overwritten_expiration)
156
+ run_2_jobs!
157
+ expect_2_jobs_are_done_and_status_eq :complete
158
+ expect_2_jobs_ttl_covers (expiration_param+1)..overwritten_expiration
159
+ end
160
+ end
161
+
162
+ def seed_secure_random_with_job_ids
163
+ SecureRandom.should_receive(:hex).exactly(4).times.and_return(plain_sidekiq_job_id, plain_sidekiq_job_id, job_id_1, job_id_1)
164
+ end
165
+
166
+ def run_2_jobs!
167
+ start_server(:expiration => expiration_param) do
168
+ capture_status_updates(12) {
169
+ StubJob.perform_async.should == plain_sidekiq_job_id
170
+ NoStatusConfirmationJob.perform_async(1)
171
+ StubJob.perform_async.should == job_id_1
172
+ NoStatusConfirmationJob.perform_async(2)
173
+ }.should =~ [plain_sidekiq_job_id, job_id_1] * 6
174
+ end
175
+ end
176
+
177
+ def expect_2_jobs_ttl_covers(range)
178
+ range.should cover redis.ttl(plain_sidekiq_job_id)
179
+ range.should cover redis.ttl(job_id_1)
180
+ end
181
+
182
+ def expect_2_jobs_are_done_and_status_eq(status)
183
+ redis.mget('NoStatusConfirmationJob_1', 'NoStatusConfirmationJob_2').should == %w(done)*2
184
+ Sidekiq::Status.status(plain_sidekiq_job_id).should == status
185
+ Sidekiq::Status.status(job_id_1).should == status
186
+ end
147
187
  end
148
188
 
149
189
  end
data/spec/spec_helper.rb CHANGED
@@ -44,7 +44,7 @@ def capture_status_updates(n, &block)
44
44
  confirmations_thread(n, "status_updates", &block).value
45
45
  end
46
46
 
47
- def start_server()
47
+ def start_server(server_middleware_options={})
48
48
  pid = Process.fork do
49
49
  $stdout.reopen File::NULL, 'w'
50
50
  $stderr.reopen File::NULL, 'w'
@@ -53,7 +53,7 @@ def start_server()
53
53
  Sidekiq.configure_server do |config|
54
54
  config.redis = Sidekiq::RedisConnection.create
55
55
  config.server_middleware do |chain|
56
- chain.add Sidekiq::Status::ServerMiddleware
56
+ chain.add Sidekiq::Status::ServerMiddleware, server_middleware_options
57
57
  end
58
58
  end
59
59
  Sidekiq::CLI.instance.run
@@ -0,0 +1,36 @@
1
+ <h3 class="wi">Recent job statuses</h3>
2
+
3
+
4
+ <table class="table table-striped table-bordered">
5
+ <tr>
6
+ <th>Worker/jid</th>
7
+ <th>Status</th>
8
+ <th>Last Updated ↆ</th>
9
+ <th>Progress</th>
10
+ <th>Message</th>
11
+ </tr>
12
+ <% @statuses.each do |container| -%>
13
+ <tr>
14
+ <td>
15
+ <%= container.worker %>
16
+ <br />
17
+ <%= container.jid %>
18
+ </td>
19
+ <td><%= container.status %></td>
20
+ <td><%= Time.at(container.update_time.to_i) %></td>
21
+ <td>
22
+ <div class="progress progress-striped" style="margin-bottom: 0">
23
+ <div class="bar" style="width: <%= container.pct_complete %>%; text-shadow: 1px 1px 1px black; background-color: #AD003D;
24
+ color: white;">
25
+ <%= container.pct_complete %>%
26
+ </div>
27
+ </div>
28
+ <td><%= container.message %></td>
29
+ </tr>
30
+ <% end -%>
31
+ <% if @statuses.empty? -%>
32
+ <tr>
33
+ <td colspan="6"></td>
34
+ </tr>
35
+ <% end -%>
36
+ </table>
metadata CHANGED
@@ -1,20 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq-status
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
5
- prerelease:
4
+ version: 0.4.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Evgeniy Tsvigun
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-09-17 00:00:00.000000000 Z
11
+ date: 2014-03-11 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: sidekiq
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
17
  - - ~>
20
18
  - !ruby/object:Gem::Version
@@ -22,7 +20,6 @@ dependencies:
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
24
  - - ~>
28
25
  - !ruby/object:Gem::Version
@@ -30,33 +27,29 @@ dependencies:
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rake
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - '>='
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - '>='
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: rspec
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0'
62
55
  description:
@@ -69,6 +62,7 @@ files:
69
62
  - .gitignore
70
63
  - .rspec
71
64
  - .travis.yml
65
+ - CHANGELOG
72
66
  - Gemfile
73
67
  - LICENSE
74
68
  - README.md
@@ -79,6 +73,7 @@ files:
79
73
  - lib/sidekiq-status/storage.rb
80
74
  - lib/sidekiq-status/testing/inline.rb
81
75
  - lib/sidekiq-status/version.rb
76
+ - lib/sidekiq-status/web.rb
82
77
  - lib/sidekiq-status/worker.rb
83
78
  - sidekiq-status.gemspec
84
79
  - spec/lib/sidekiq-status/client_middleware_spec.rb
@@ -88,30 +83,30 @@ files:
88
83
  - spec/lib/sidekiq-status_spec.rb
89
84
  - spec/spec_helper.rb
90
85
  - spec/support/test_jobs.rb
86
+ - web/views/statuses.erb
91
87
  homepage: http://github.com/utgarda/sidekiq-status
92
88
  licenses:
93
89
  - MIT
90
+ metadata: {}
94
91
  post_install_message:
95
92
  rdoc_options: []
96
93
  require_paths:
97
94
  - lib
98
95
  required_ruby_version: !ruby/object:Gem::Requirement
99
- none: false
100
96
  requirements:
101
- - - ! '>='
97
+ - - '>='
102
98
  - !ruby/object:Gem::Version
103
99
  version: '0'
104
100
  required_rubygems_version: !ruby/object:Gem::Requirement
105
- none: false
106
101
  requirements:
107
- - - ! '>='
102
+ - - '>='
108
103
  - !ruby/object:Gem::Version
109
104
  version: '0'
110
105
  requirements: []
111
106
  rubyforge_project:
112
- rubygems_version: 1.8.23
107
+ rubygems_version: 2.0.3
113
108
  signing_key:
114
- specification_version: 3
109
+ specification_version: 4
115
110
  summary: An extension to the sidekiq message processing to track your jobs
116
111
  test_files:
117
112
  - spec/lib/sidekiq-status/client_middleware_spec.rb