sidekiq-status 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml 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