attentive_sidekiq 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +3 -5
- data/README.md +26 -11
- data/dump.rdb +0 -0
- data/lib/attentive_sidekiq.rb +26 -2
- data/lib/attentive_sidekiq/api.rb +9 -8
- data/lib/attentive_sidekiq/manager.rb +4 -5
- data/lib/attentive_sidekiq/version.rb +1 -1
- data/test/manager_test.rb +2 -2
- data/test/server_middleware_test.rb +7 -7
- metadata +4 -5
- data/lib/attentive_sidekiq/middleware.rb +0 -6
- data/web.png +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 710aa8d08d27aece645bef61d22be38bdf5424f5
|
4
|
+
data.tar.gz: e8dde883933212b7ea5659749d12cb810005bc2d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fd6587c4312f1e2cf96cf2bc106f509c3464f871fcb8acd08faf031ad1dd207d85ddac21d9e5eacde83dcb7e8a96f162238801d497d88bab6b284977e8775e27
|
7
|
+
data.tar.gz: 629fb700fca7a68df8054624a648319db57feb9a0f154a4a7b38a6c5a2b87df3f09888f2e13c8474455d91ffdb2956c9935741ea54288968d9267a71821cbeff
|
data/Gemfile.lock
CHANGED
@@ -1,25 +1,23 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
attentive_sidekiq (0.
|
4
|
+
attentive_sidekiq (0.3.0)
|
5
5
|
activesupport
|
6
6
|
concurrent-ruby (~> 1.0)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
activesupport (
|
11
|
+
activesupport (5.0.0.1)
|
12
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
12
13
|
i18n (~> 0.7)
|
13
|
-
json (~> 1.7, >= 1.7.7)
|
14
14
|
minitest (~> 5.1)
|
15
|
-
thread_safe (~> 0.3, >= 0.3.4)
|
16
15
|
tzinfo (~> 1.1)
|
17
16
|
byebug (9.0.6)
|
18
17
|
coderay (1.1.1)
|
19
18
|
concurrent-ruby (1.0.2)
|
20
19
|
connection_pool (2.2.1)
|
21
20
|
i18n (0.7.0)
|
22
|
-
json (1.8.3)
|
23
21
|
method_source (0.8.2)
|
24
22
|
minitest (5.9.1)
|
25
23
|
minitest-stub_any_instance (1.0.1)
|
data/README.md
CHANGED
@@ -1,24 +1,21 @@
|
|
1
|
-
|
1
|
+
Attentive Sidekiq
|
2
|
+
===========================
|
2
3
|
|
3
4
|
[![Gem Version](https://badge.fury.io/rb/attentive_sidekiq.svg)](https://badge.fury.io/rb/attentive_sidekiq)
|
4
5
|
[![Code Climate](https://codeclimate.com/github/twonegatives/attentive_sidekiq/badges/gpa.svg)](https://codeclimate.com/github/twonegatives/attentive_sidekiq)
|
5
6
|
[![CircleCI](https://circleci.com/gh/twonegatives/attentive_sidekiq.svg?style=shield)](https://circleci.com/gh/twonegatives/attentive_sidekiq)
|
6
7
|
|
8
|
+
Be aware of suddenly disappeared sidekiq jobs!
|
7
9
|
|
8
|
-
|
9
|
-
Bad things happen sometimes. Sidekiq process being killed in the middle of job processing may lead to job losage. In other words, that job will never be returned to the queue.
|
10
|
-
This case was proved by [github issues](https://github.com/mperham/sidekiq/issues/1831), [stackoverflow questions](http://stackoverflow.com/questions/35555000/current-sidekiq-job-lost-when-deploying-to-heroku) and (sadly) personal experience, and means that you are not safe from losing critical user data.
|
11
|
-
Sidekiq's author, Mike Perham, suggests purchasing Sidekiq Pro which uses another fetch mechanism. However, it [is reported](https://github.com/mperham/sidekiq/issues/2531) to still cause the same issue.
|
10
|
+
![shortsummary](https://cloud.githubusercontent.com/assets/1937799/20489411/fe726e82-b023-11e6-9528-7df519fec7dd.gif)
|
12
11
|
|
13
|
-
### About
|
14
|
-
|
15
|
-
It saves info about started jobs into additional redis hash and keeps them there till jobs are finished.
|
16
|
-
In case there appears a job being started but not finished and not being processing at the moment, you will know something bad happened.
|
12
|
+
### About
|
13
|
+
The case of disappearing sidekiq jobs was proved by [github issues](https://github.com/mperham/sidekiq/issues/1831), [stackoverflow questions](http://stackoverflow.com/questions/35555000/current-sidekiq-job-lost-when-deploying-to-heroku) and (sadly) personal experience. Attentive Sidekiq was made to protect your jobs and critical data from silent disappearing. In case there appears a job being started but not finished and not being processing at the moment, you will know this.
|
17
14
|
|
18
15
|
### Usage
|
19
16
|
Attentive Sidekiq provides you with a couple of useful API methods.
|
20
17
|
|
21
|
-
To get a hash containing all information about jobs marked as
|
18
|
+
To get a hash containing all information about jobs marked as disappeared:
|
22
19
|
```ruby
|
23
20
|
AttentiveSidekiq::Disappeared.jobs
|
24
21
|
```
|
@@ -43,7 +40,7 @@ You may also watch info about disappeared jobs in a web UI.
|
|
43
40
|
Simply make sure you have Sidekiq UI enabled, then head right to the Disappeared Jobs tab in the navbar.
|
44
41
|
The Web UI uses the API exclusively: anything you can do in the UI can be scripted with the API.
|
45
42
|
|
46
|
-
![
|
43
|
+
![webui](https://cloud.githubusercontent.com/assets/1937799/20490807/a01216d0-b028-11e6-96b7-c23fd67bdf89.png)
|
47
44
|
|
48
45
|
### Pre-requirements and notes
|
49
46
|
|
@@ -73,6 +70,24 @@ end
|
|
73
70
|
|
74
71
|
After that you can use your jobs as usual.
|
75
72
|
|
73
|
+
### Configuration
|
74
|
+
|
75
|
+
Specify desired configuration inside of `sidekiq.yml` file:
|
76
|
+
|
77
|
+
```YML
|
78
|
+
attentive:
|
79
|
+
# Time in seconds between checks for disappeared jobs
|
80
|
+
:execution_interval: 300 # default: 600
|
81
|
+
# Time limit in seconds to perform disappeared jobs check
|
82
|
+
:timeout_interval: 25 # default: 60
|
83
|
+
```
|
84
|
+
|
85
|
+
By default, Attentive Sidekiq uses `Sidekiq.logger` to log its work. You may change it in your initializer:
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
AttentiveSidekiq.logger = Logger.new("log/attentive_sidekiq.log")
|
89
|
+
```
|
90
|
+
|
76
91
|
### Suggestions? Bugs?
|
77
92
|
|
78
93
|
If you've got a question, feature suggestion or found a bug please add an [issue on GitHub](https://github.com/twonegatives/attentive_sidekiq/issues) or fork the project and send a pull request.
|
data/dump.rdb
ADDED
Binary file
|
data/lib/attentive_sidekiq.rb
CHANGED
@@ -2,7 +2,6 @@ require 'set'
|
|
2
2
|
require 'active_support/inflector'
|
3
3
|
require 'active_support/core_ext/hash'
|
4
4
|
require 'concurrent'
|
5
|
-
require 'attentive_sidekiq/middleware'
|
6
5
|
require 'attentive_sidekiq/api'
|
7
6
|
require 'attentive_sidekiq/middleware/server/attentionist'
|
8
7
|
require 'attentive_sidekiq/middleware/client/attentionist'
|
@@ -12,11 +11,36 @@ require 'sidekiq/web' unless defined?(Sidekiq::Web)
|
|
12
11
|
require 'attentive_sidekiq/web'
|
13
12
|
|
14
13
|
module AttentiveSidekiq
|
14
|
+
DEFAULTS = {
|
15
|
+
timeout_interval: 60,
|
16
|
+
execution_interval: 600,
|
17
|
+
}
|
18
|
+
|
19
|
+
REDIS_SUSPICIOUS_KEY = "attentive_observed_hash"
|
20
|
+
REDIS_DISAPPEARED_KEY = "attentive_disappeared_hash"
|
21
|
+
|
15
22
|
class << self
|
16
|
-
attr_writer :logger
|
23
|
+
attr_writer :timeout_interval, :execution_interval, :logger
|
24
|
+
|
25
|
+
def timeout_interval
|
26
|
+
return @execution_timeout if @execution_timeout
|
27
|
+
@timeout_interval = options[:timeout_interval] || DEFAULTS[:timeout_interval]
|
28
|
+
end
|
29
|
+
|
30
|
+
def execution_interval
|
31
|
+
return @execution_interval if @execution_interval
|
32
|
+
@execution_interval = options[:execution_interval] || DEFAULTS[:execution_interval]
|
33
|
+
end
|
17
34
|
|
18
35
|
def logger
|
19
36
|
@logger ||= Sidekiq.logger
|
20
37
|
end
|
38
|
+
|
39
|
+
def options
|
40
|
+
Sidekiq.options["attentive"] || {}
|
41
|
+
end
|
42
|
+
|
21
43
|
end
|
22
44
|
end
|
45
|
+
|
46
|
+
AttentiveSidekiq::Manager.instance.start! if Sidekiq.server?
|
@@ -20,17 +20,10 @@ module AttentiveSidekiq
|
|
20
20
|
def remove jid
|
21
21
|
Sidekiq.redis{|conn| conn.hdel(hash_name, jid)}
|
22
22
|
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def hash_name
|
27
|
-
self.const_get(:HASH_NAME)
|
28
|
-
end
|
29
23
|
end
|
30
24
|
end
|
31
25
|
|
32
26
|
class Disappeared < RedisBasedHash
|
33
|
-
HASH_NAME = AttentiveSidekiq::Middleware::REDIS_DISAPPEARED_KEY
|
34
27
|
STATUS_DETECTED = 'detected'
|
35
28
|
STATUS_REQUEUED = 'requeued'
|
36
29
|
|
@@ -47,11 +40,19 @@ module AttentiveSidekiq
|
|
47
40
|
record['class'].constantize.perform_async(*record['args'])
|
48
41
|
base_add(record.merge('status' => STATUS_REQUEUED))
|
49
42
|
end
|
43
|
+
|
44
|
+
def hash_name
|
45
|
+
AttentiveSidekiq::REDIS_DISAPPEARED_KEY
|
46
|
+
end
|
50
47
|
end
|
51
48
|
end
|
52
49
|
|
53
50
|
class Suspicious < RedisBasedHash
|
54
|
-
|
51
|
+
class << self
|
52
|
+
def hash_name
|
53
|
+
AttentiveSidekiq::REDIS_SUSPICIOUS_KEY
|
54
|
+
end
|
55
|
+
end
|
55
56
|
end
|
56
57
|
|
57
58
|
class Active
|
@@ -29,12 +29,11 @@ module AttentiveSidekiq
|
|
29
29
|
private
|
30
30
|
|
31
31
|
def options
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
{
|
33
|
+
execution_interval: AttentiveSidekiq.execution_interval,
|
34
|
+
timeout_interval: AttentiveSidekiq.timeout_interval
|
35
|
+
}
|
35
36
|
end
|
36
37
|
|
37
38
|
end
|
38
39
|
end
|
39
|
-
|
40
|
-
AttentiveSidekiq::Manager.instance.start! if Sidekiq.server?
|
data/test/manager_test.rb
CHANGED
@@ -35,11 +35,11 @@ class ManagerTest < Minitest::Test
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def suspicious_now
|
38
|
-
Sidekiq.redis{|conn| conn.hvals(AttentiveSidekiq::
|
38
|
+
Sidekiq.redis{|conn| conn.hvals(AttentiveSidekiq::REDIS_SUSPICIOUS_KEY)}.map{|i| JSON.parse(i)}
|
39
39
|
end
|
40
40
|
|
41
41
|
def disappeared_now
|
42
|
-
from_redis = Sidekiq.redis{|conn| conn.hvals(AttentiveSidekiq::
|
42
|
+
from_redis = Sidekiq.redis{|conn| conn.hvals(AttentiveSidekiq::REDIS_DISAPPEARED_KEY)}
|
43
43
|
from_redis.map{|i| JSON.parse(i).except('noticed_at', 'status')}
|
44
44
|
end
|
45
45
|
end
|
@@ -78,21 +78,21 @@ class ServerMiddlewareTest < Minitest::Test
|
|
78
78
|
assert_equal 0, DefaultQueue.instance.size
|
79
79
|
HardWorker.perform_async(1)
|
80
80
|
assert_equal 1, DefaultQueue.instance.size
|
81
|
-
assert_equal 0, Sidekiq.redis{|conn| conn.hvals(AttentiveSidekiq::
|
81
|
+
assert_equal 0, Sidekiq.redis{|conn| conn.hvals(AttentiveSidekiq::REDIS_SUSPICIOUS_KEY)}.size
|
82
82
|
end
|
83
83
|
|
84
84
|
it "marks job as suspicious as soon as it is started" do
|
85
|
-
assert_equal 0, Sidekiq.redis{|conn| conn.hvals(AttentiveSidekiq::
|
85
|
+
assert_equal 0, Sidekiq.redis{|conn| conn.hvals(AttentiveSidekiq::REDIS_SUSPICIOUS_KEY)}.size
|
86
86
|
HardWorker.perform_async(2, 100_000)
|
87
87
|
Thread.new{
|
88
88
|
SidekiqEmulator.instance.process_jobs
|
89
89
|
}
|
90
90
|
sleep(1) # TODO: refactor this somehow
|
91
|
-
assert_equal 1, Sidekiq.redis{|conn| conn.hvals(AttentiveSidekiq::
|
91
|
+
assert_equal 1, Sidekiq.redis{|conn| conn.hvals(AttentiveSidekiq::REDIS_SUSPICIOUS_KEY)}.size
|
92
92
|
end
|
93
93
|
|
94
94
|
it "removes suspicious mark as soon as job is finished succesfully" do
|
95
|
-
assert_equal 0, Sidekiq.redis{|conn| conn.hvals(AttentiveSidekiq::
|
95
|
+
assert_equal 0, Sidekiq.redis{|conn| conn.hvals(AttentiveSidekiq::REDIS_SUSPICIOUS_KEY)}.size
|
96
96
|
HardWorker.perform_async(2, 1)
|
97
97
|
Thread.new{
|
98
98
|
@mutex.synchronize{
|
@@ -101,11 +101,11 @@ class ServerMiddlewareTest < Minitest::Test
|
|
101
101
|
}
|
102
102
|
}
|
103
103
|
@mutex.synchronize{ @stopper.wait(@mutex) }
|
104
|
-
assert_equal 0, Sidekiq.redis{|conn| conn.hvals(AttentiveSidekiq::
|
104
|
+
assert_equal 0, Sidekiq.redis{|conn| conn.hvals(AttentiveSidekiq::REDIS_SUSPICIOUS_KEY)}.size
|
105
105
|
end
|
106
106
|
|
107
107
|
it "removes suspicious mark as soon as job failed" do
|
108
|
-
assert_equal 0, Sidekiq.redis{|conn| conn.hvals(AttentiveSidekiq::
|
108
|
+
assert_equal 0, Sidekiq.redis{|conn| conn.hvals(AttentiveSidekiq::REDIS_SUSPICIOUS_KEY)}.size
|
109
109
|
HardWorker.perform_async(2, -1)
|
110
110
|
Thread.new{
|
111
111
|
@mutex.synchronize{
|
@@ -114,7 +114,7 @@ class ServerMiddlewareTest < Minitest::Test
|
|
114
114
|
}
|
115
115
|
}
|
116
116
|
@mutex.synchronize{ @stopper.wait(@mutex) }
|
117
|
-
assert_equal 0, Sidekiq.redis{|conn| conn.hvals(AttentiveSidekiq::
|
117
|
+
assert_equal 0, Sidekiq.redis{|conn| conn.hvals(AttentiveSidekiq::REDIS_SUSPICIOUS_KEY)}.size
|
118
118
|
end
|
119
119
|
end
|
120
120
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: attentive_sidekiq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- twonegatives
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-11-
|
11
|
+
date: 2016-11-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sidekiq
|
@@ -164,10 +164,10 @@ files:
|
|
164
164
|
- Rakefile
|
165
165
|
- attentive_sidekiq.gemspec
|
166
166
|
- circle.yml
|
167
|
+
- dump.rdb
|
167
168
|
- lib/attentive_sidekiq.rb
|
168
169
|
- lib/attentive_sidekiq/api.rb
|
169
170
|
- lib/attentive_sidekiq/manager.rb
|
170
|
-
- lib/attentive_sidekiq/middleware.rb
|
171
171
|
- lib/attentive_sidekiq/middleware/client/attentionist.rb
|
172
172
|
- lib/attentive_sidekiq/middleware/server/attentionist.rb
|
173
173
|
- lib/attentive_sidekiq/updater_observer.rb
|
@@ -181,7 +181,6 @@ files:
|
|
181
181
|
- test/server_middleware_test.rb
|
182
182
|
- test/test_helper.rb
|
183
183
|
- test/web_test.rb
|
184
|
-
- web.png
|
185
184
|
homepage: http://rubygems.org/gems/attentive_sidekiq
|
186
185
|
licenses:
|
187
186
|
- MIT
|
@@ -202,7 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
202
201
|
version: '0'
|
203
202
|
requirements: []
|
204
203
|
rubyforge_project:
|
205
|
-
rubygems_version: 2.
|
204
|
+
rubygems_version: 2.4.5
|
206
205
|
signing_key:
|
207
206
|
specification_version: 4
|
208
207
|
summary: Make your sidekiq to be attentive to lost jobs
|
data/web.png
DELETED
Binary file
|