sidekiq-circuit-breaker 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile.lock +1 -1
- data/lib/sidekiq/circuit_breaker.rb +2 -1
- data/lib/sidekiq/circuit_breaker/api.rb +13 -2
- data/lib/sidekiq/circuit_breaker/manager.rb +3 -3
- data/lib/sidekiq/circuit_breaker/middleware.rb +2 -91
- data/lib/sidekiq/circuit_breaker/middleware/client.rb +51 -0
- data/lib/sidekiq/circuit_breaker/middleware/server.rb +39 -0
- data/lib/sidekiq/circuit_breaker/scope.rb +18 -0
- data/lib/sidekiq/circuit_breaker/version.rb +1 -1
- data/lib/sidekiq/circuit_breaker/worker.rb +0 -22
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e51ce2527ccdcb2cf1081f47c5e37fffed8043a264c9749dcbe6d1d6ec409e44
|
4
|
+
data.tar.gz: eb6f8fbd9e30cc88c18b82aa51a8474d71dbcc3ef461e5470934010371ae1c67
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 42befd4cf2b41db3690590426eefeba7548fed8cc4aab59af943eec1fb4ab75454a8cbc0496e9e6178c9e3b1add247296505367ce9c2bed90aa634d7f06d27a7
|
7
|
+
data.tar.gz: 1efbecc602fcebbeaa07481e2e92599ad990ef44130f7528edc30d60801c2bfac41aa3c8dcbe59c0b9a035e8cbfb220c32e2fcaa3dc7cd9fceab62ce0ad2d064
|
data/CHANGELOG.md
ADDED
data/Gemfile.lock
CHANGED
@@ -15,6 +15,17 @@ module Sidekiq
|
|
15
15
|
true
|
16
16
|
end
|
17
17
|
|
18
|
+
def close_circuit(scope)
|
19
|
+
raise ArgumentError, 'scope must not be nil' if scope.nil?
|
20
|
+
Sidekiq.redis do |conn|
|
21
|
+
conn.del(open_key(scope))
|
22
|
+
# reset failure count
|
23
|
+
conn.del(failure_key(scope))
|
24
|
+
end
|
25
|
+
true
|
26
|
+
|
27
|
+
end
|
28
|
+
|
18
29
|
def register_failure_for_scope(scope, ttl = 120)
|
19
30
|
raise ArgumentError, 'scope must not be nil' if scope.nil?
|
20
31
|
key = failure_key(scope)
|
@@ -36,13 +47,13 @@ module Sidekiq
|
|
36
47
|
end
|
37
48
|
end
|
38
49
|
|
39
|
-
def
|
50
|
+
def time_to_close_the_circuit(scope)
|
40
51
|
Sidekiq.redis do |conn|
|
41
52
|
conn.ttl(open_key(scope))
|
42
53
|
end
|
43
54
|
end
|
44
55
|
|
45
|
-
def
|
56
|
+
def circuit_open?(scope)
|
46
57
|
Sidekiq.redis do |conn|
|
47
58
|
conn.exists(open_key(scope))
|
48
59
|
end
|
@@ -15,7 +15,7 @@ module Sidekiq
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def open?
|
18
|
-
|
18
|
+
circuit_open?(@scope)
|
19
19
|
end
|
20
20
|
|
21
21
|
def closed?
|
@@ -30,8 +30,8 @@ module Sidekiq
|
|
30
30
|
open_circuit(@scope, @options.max_open_time)
|
31
31
|
end
|
32
32
|
|
33
|
-
def
|
34
|
-
|
33
|
+
def time_to_close
|
34
|
+
time_to_close_the_circuit(@scope)
|
35
35
|
end
|
36
36
|
|
37
37
|
def register_failure
|
@@ -1,94 +1,5 @@
|
|
1
|
-
require 'sidekiq/circuit_breaker/
|
2
|
-
require 'sidekiq/circuit_breaker/middleware'
|
3
|
-
require 'sidekiq/client'
|
4
|
-
|
5
|
-
module Sidekiq
|
6
|
-
module CircuitBreaker
|
7
|
-
module Middleware
|
8
|
-
class Client
|
9
|
-
def call(worker_class, msg, queue, redis_pool)
|
10
|
-
begin
|
11
|
-
worker = constantize(worker_class)
|
12
|
-
rescue NameError
|
13
|
-
return yield
|
14
|
-
end
|
15
|
-
|
16
|
-
circuit_breaker = worker.respond_to?(:sidekiq_circuit_breaker_enabled?)
|
17
|
-
return yield unless circuit_breaker
|
18
|
-
|
19
|
-
options = worker.sidekiq_circuit_breaker_options
|
20
|
-
scope = extract_scope(options, msg) || worker_class
|
21
|
-
|
22
|
-
mgr = CircuitBreaker::Manager.new(scope, options)
|
23
|
-
if mgr.open? && msg['at'].nil?
|
24
|
-
msg['at'] = (Time.now + (mgr.time_to_open + additional_seconds)).to_f
|
25
|
-
end
|
26
|
-
|
27
|
-
yield
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
def additional_seconds
|
33
|
-
rand(3..10)
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def extract_scope(options, msg)
|
39
|
-
scope = options.scope
|
40
|
-
return scope if scope.is_a?(String)
|
41
|
-
return unless scope.respond_to?(:call)
|
42
|
-
|
43
|
-
options.scope.call(*msg['args'])
|
44
|
-
end
|
45
|
-
|
46
|
-
def constantize(str)
|
47
|
-
names = str.split('::')
|
48
|
-
names.shift if names.empty? || names.first.empty?
|
49
|
-
|
50
|
-
names.inject(Object) do |constant, name|
|
51
|
-
constant.const_defined?(name, false) ? constant.const_get(name, false) : constant.const_missing(name)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
class Server
|
57
|
-
def call(worker, msg, queue)
|
58
|
-
circuit_breaker_enabled = worker.class.respond_to?(:sidekiq_circuit_breaker_enabled?)
|
59
|
-
return yield unless circuit_breaker_enabled
|
60
|
-
|
61
|
-
def worker.perform(*args)
|
62
|
-
manager = sidekiq_circuit_breaker_manager(args)
|
63
|
-
|
64
|
-
if manager.open?
|
65
|
-
begin
|
66
|
-
Sidekiq::Client.push(
|
67
|
-
'class' => self.class,
|
68
|
-
'args' => args
|
69
|
-
)
|
70
|
-
return
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
super(*args)
|
75
|
-
end
|
76
|
-
|
77
|
-
manager = worker.sidekiq_circuit_breaker_manager(msg['args'])
|
78
|
-
|
79
|
-
begin
|
80
|
-
yield
|
81
|
-
rescue => e
|
82
|
-
manager.evaluate_failure
|
83
|
-
raise e
|
84
|
-
end
|
85
|
-
|
86
|
-
manager.register_success
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
1
|
+
require 'sidekiq/circuit_breaker/middleware/client'
|
2
|
+
require 'sidekiq/circuit_breaker/middleware/server'
|
92
3
|
|
93
4
|
Sidekiq.configure_client do |config|
|
94
5
|
config.client_middleware do |chain|
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'sidekiq/client'
|
2
|
+
require 'sidekiq/circuit_breaker/manager'
|
3
|
+
require 'sidekiq/circuit_breaker/scope'
|
4
|
+
|
5
|
+
module Sidekiq
|
6
|
+
module CircuitBreaker
|
7
|
+
module Middleware
|
8
|
+
class Client
|
9
|
+
include Sidekiq::CircuitBreaker::Scope
|
10
|
+
|
11
|
+
def call(worker_class, msg, queue, redis_pool)
|
12
|
+
begin
|
13
|
+
worker = constantize(worker_class)
|
14
|
+
rescue NameError
|
15
|
+
return yield
|
16
|
+
end
|
17
|
+
|
18
|
+
circuit_breaker = worker.respond_to?(:sidekiq_circuit_breaker_enabled?)
|
19
|
+
return yield unless circuit_breaker
|
20
|
+
|
21
|
+
options = worker.sidekiq_circuit_breaker_options
|
22
|
+
scope = extract_scope(worker_class, msg, options)
|
23
|
+
|
24
|
+
mgr = CircuitBreaker::Manager.new(scope, options)
|
25
|
+
if mgr.open? && msg['at'].nil?
|
26
|
+
msg['at'] = (Time.now + (mgr.time_to_close + additional_seconds)).to_f
|
27
|
+
end
|
28
|
+
|
29
|
+
yield
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def additional_seconds
|
35
|
+
rand(3..10)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def constantize(str)
|
41
|
+
names = str.split('::')
|
42
|
+
names.shift if names.empty? || names.first.empty?
|
43
|
+
|
44
|
+
names.inject(Object) do |constant, name|
|
45
|
+
constant.const_defined?(name, false) ? constant.const_get(name, false) : constant.const_missing(name)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'sidekiq/circuit_breaker/scope'
|
2
|
+
|
3
|
+
module Sidekiq
|
4
|
+
module CircuitBreaker
|
5
|
+
module Middleware
|
6
|
+
class Server
|
7
|
+
include Sidekiq::CircuitBreaker::Scope
|
8
|
+
|
9
|
+
def call(worker, msg, queue)
|
10
|
+
circuit_breaker_enabled = worker.class.respond_to?(:sidekiq_circuit_breaker_enabled?)
|
11
|
+
return yield unless circuit_breaker_enabled
|
12
|
+
|
13
|
+
options = worker.class.sidekiq_circuit_breaker_options
|
14
|
+
scope = extract_scope(worker.class.name, msg, options)
|
15
|
+
manager = Manager.new(scope, options)
|
16
|
+
resquedule_job(worker, msg) and return if manager.open?
|
17
|
+
|
18
|
+
begin
|
19
|
+
yield
|
20
|
+
rescue => e
|
21
|
+
manager.evaluate_failure
|
22
|
+
raise e
|
23
|
+
end
|
24
|
+
|
25
|
+
manager.register_success
|
26
|
+
end
|
27
|
+
|
28
|
+
def resquedule_job(worker, msg)
|
29
|
+
Sidekiq::Client.push(
|
30
|
+
'class' => worker.class.name,
|
31
|
+
'args' => msg['args']
|
32
|
+
)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Sidekiq
|
2
|
+
module CircuitBreaker
|
3
|
+
module Scope
|
4
|
+
def extract_scope(worker_class_name, msg, options)
|
5
|
+
from_setup =
|
6
|
+
begin
|
7
|
+
scope = options.scope
|
8
|
+
return scope if scope.is_a?(String)
|
9
|
+
return unless scope.respond_to?(:call)
|
10
|
+
|
11
|
+
options.scope.call(*msg['args'])
|
12
|
+
end
|
13
|
+
|
14
|
+
from_setup || worker_class_name
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -7,28 +7,6 @@ module Sidekiq
|
|
7
7
|
base.extend(ClassMethods)
|
8
8
|
end
|
9
9
|
|
10
|
-
def sidekiq_circuit_breaker_manager(args)
|
11
|
-
options = self.class.sidekiq_circuit_breaker_options
|
12
|
-
scope = scope(args)
|
13
|
-
CircuitBreaker::Manager.new(scope, options)
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def scope(args)
|
19
|
-
options = self.class.sidekiq_circuit_breaker_options
|
20
|
-
extract_scope(options, args) || self.class.name
|
21
|
-
end
|
22
|
-
|
23
|
-
def extract_scope(options, args)
|
24
|
-
scope = options.scope
|
25
|
-
return scope if scope.is_a?(String)
|
26
|
-
return unless scope.respond_to?(:call)
|
27
|
-
|
28
|
-
options.scope.call(*args)
|
29
|
-
end
|
30
|
-
|
31
|
-
|
32
10
|
module ClassMethods
|
33
11
|
def sidekiq_circuit_breaker_enabled?
|
34
12
|
true
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq-circuit-breaker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nando Sousa
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-08-
|
11
|
+
date: 2018-08-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sidekiq
|
@@ -76,6 +76,7 @@ files:
|
|
76
76
|
- ".gitignore"
|
77
77
|
- ".rspec"
|
78
78
|
- ".travis.yml"
|
79
|
+
- CHANGELOG.md
|
79
80
|
- Gemfile
|
80
81
|
- Gemfile.lock
|
81
82
|
- LICENSE.txt
|
@@ -88,6 +89,9 @@ files:
|
|
88
89
|
- lib/sidekiq/circuit_breaker/configuration.rb
|
89
90
|
- lib/sidekiq/circuit_breaker/manager.rb
|
90
91
|
- lib/sidekiq/circuit_breaker/middleware.rb
|
92
|
+
- lib/sidekiq/circuit_breaker/middleware/client.rb
|
93
|
+
- lib/sidekiq/circuit_breaker/middleware/server.rb
|
94
|
+
- lib/sidekiq/circuit_breaker/scope.rb
|
91
95
|
- lib/sidekiq/circuit_breaker/version.rb
|
92
96
|
- lib/sidekiq/circuit_breaker/worker.rb
|
93
97
|
- sidekiq-circuit-breaker.gemspec
|