redis-reconnect_with_readonly 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +16 -5
- data/bin/try +3 -1
- data/lib/redis/reconnect_with_readonly.rb +59 -7
- data/lib/redis/reconnect_with_readonly/version.rb +2 -2
- data/redis-reconnect_with_readonly.gemspec +2 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 15ff6c001cad1dccfdde9ba2c50f13b9993e432c
|
4
|
+
data.tar.gz: 8b631aa7157e62ff540abdb75c2f4972e617879b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 923f28e0401979e5a86a68a628a516cc3fd56f7347f0125635fcb6e7bde0a9b0fa2be07147211c90c7d3301582ad78ad59a89bd184a6b7ba61a6c28eba98c110
|
7
|
+
data.tar.gz: 39729e0ea98fbc89a64e1e56111a08823bf3e2c291899760fdbc0d8df22dd074e44e4b4ab851ee456f5fb2fa9dca30540492a549e0d5547e862b1b2b15ead996
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Redis::ReconnectWithReadonly
|
2
2
|
|
3
|
-
Reconnect your redis connection if `Redis::CommandError READONLY You can't write against a read only slave.`
|
3
|
+
Reconnect your redis connection if `Redis::CommandError READONLY You can't write against a read only slave.` occurs because of failover.
|
4
4
|
|
5
5
|
When redis cluster failovers, the redis master is depromoted to slave and will be READONLY. Such case we have to reconnect redis connection so that new connection goes to new master which is writable.
|
6
6
|
|
@@ -26,6 +26,21 @@ Or install it yourself as:
|
|
26
26
|
require 'redis/reconnect_with_readonly'
|
27
27
|
```
|
28
28
|
|
29
|
+
## Configuration
|
30
|
+
|
31
|
+
This gem tries reconnection `reconnect_attempts` times.
|
32
|
+
It will wait `2 ^ num of retries` second interval on each retry.
|
33
|
+
The waiting interval can be suppressed up to `max_retry_interval`.
|
34
|
+
|
35
|
+
```
|
36
|
+
Redis::ReconnectWithReadonly.reconnect_attempts = 1
|
37
|
+
Redis::ReconnectWithReadonly.max_retry_interval = 3600
|
38
|
+
```
|
39
|
+
|
40
|
+
## Implementation
|
41
|
+
|
42
|
+
This gem monkey patches `Redis::Client`.
|
43
|
+
|
29
44
|
## Development
|
30
45
|
|
31
46
|
```
|
@@ -44,10 +59,6 @@ $ bin/console
|
|
44
59
|
> redis.set('key', 'val')
|
45
60
|
```
|
46
61
|
|
47
|
-
## Implementation
|
48
|
-
|
49
|
-
This gem monkey patches `Redis::Client#read`.
|
50
|
-
|
51
62
|
## Contributing
|
52
63
|
|
53
64
|
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/redis-reconnect_with_readonly. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
data/bin/try
CHANGED
@@ -4,7 +4,9 @@ require "bundler/setup"
|
|
4
4
|
require "redis/reconnect_with_readonly"
|
5
5
|
require 'logger'
|
6
6
|
|
7
|
-
|
7
|
+
Redis::ReconnectWithReadonly.reconnect_attempts = 5
|
8
|
+
Redis::ReconnectWithReadonly.max_retry_interval = 3
|
8
9
|
|
10
|
+
logger = Logger.new(STDOUT)
|
9
11
|
redis = Redis.new(host: 'localhost', port: '6380', logger: logger)
|
10
12
|
redis.set('key', 'val')
|
@@ -3,19 +3,71 @@ require 'redis'
|
|
3
3
|
require 'redis/client'
|
4
4
|
require 'redis/errors'
|
5
5
|
|
6
|
+
class Redis
|
7
|
+
class ReconnectWithReadonly
|
8
|
+
@reconnect_attempts = 1
|
9
|
+
@max_retry_interval = 3600 # sec
|
10
|
+
|
11
|
+
class << self
|
12
|
+
attr_accessor :reconnect_attempts, :max_retry_interval
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
6
17
|
class Redis
|
7
18
|
class ReadonlyConnectionError < ConnectionError; end
|
8
19
|
|
9
20
|
class Client
|
10
|
-
def
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
21
|
+
def reconnect_with_readonly(&block)
|
22
|
+
retries = 0
|
23
|
+
begin
|
24
|
+
yield block
|
25
|
+
rescue CommandError => e
|
26
|
+
if e.message =~ /READONLY/
|
27
|
+
if retries < (max_retries = ReconnectWithReadonly.reconnect_attempts)
|
28
|
+
interval = [2**retries, ReconnectWithReadonly.max_retry_interval].min
|
29
|
+
logger.info {
|
30
|
+
"Reconnect with readonly: #{e.message} " \
|
31
|
+
"(retries: #{retries}/#{max_retries}) (wait: #{interval}sec)"
|
32
|
+
} if logger
|
33
|
+
sleep interval
|
34
|
+
retries += 1
|
35
|
+
retry
|
36
|
+
else
|
37
|
+
logger.info {
|
38
|
+
"Reconnect with readonly: Give up " \
|
39
|
+
"(retries: #{retries}/#{max_retries})"
|
40
|
+
} if logger
|
41
|
+
end
|
42
|
+
else
|
43
|
+
raise
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def call_with_reconnect_with_readonly(command, &block)
|
49
|
+
reconnect_with_readonly do
|
50
|
+
call_without_reconnect_with_readonly(command, &block)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def call_loop_with_reconnect_with_readonly(command, &block)
|
55
|
+
reconnect_with_readonly do
|
56
|
+
call_loop_without_reconnect_with_readonly(command, &block)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def call_pipeline_with_reconnect_with_readonly(command, &block)
|
61
|
+
reconnect_with_readonly do
|
62
|
+
call_pipeline_without_reconnect_with_readonly(command, &block)
|
15
63
|
end
|
16
64
|
end
|
17
65
|
|
18
|
-
alias :
|
19
|
-
alias :
|
66
|
+
alias :call_without_reconnect_with_readonly :call
|
67
|
+
alias :call :call_with_reconnect_with_readonly
|
68
|
+
alias :call_loop_without_reconnect_with_readonly :call_loop
|
69
|
+
alias :call_loop :call_loop_with_reconnect_with_readonly
|
70
|
+
alias :call_pipeline_without_reconnect_with_readonly :call_pipeline
|
71
|
+
alias :call_pipeline :call_pipeline_with_reconnect_with_readonly
|
20
72
|
end
|
21
73
|
end
|
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Naotoshi Seo"]
|
10
10
|
spec.email = ["sonots@gmail.com"]
|
11
11
|
|
12
|
-
spec.summary = %q{Reconnect redis if Redis::CommandError READONLY
|
13
|
-
spec.description = %q{Reconnect redis if Redis::CommandError READONLY
|
12
|
+
spec.summary = %q{Reconnect redis if Redis::CommandError READONLY occurs.}
|
13
|
+
spec.description = %q{Reconnect redis if Redis::CommandError READONLY occurs.}
|
14
14
|
spec.homepage = "https://github.com/sonots/redis-reconnect_with_readonly."
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis-reconnect_with_readonly
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Naotoshi Seo
|
@@ -52,7 +52,7 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '10.0'
|
55
|
-
description: Reconnect redis if Redis::CommandError READONLY
|
55
|
+
description: Reconnect redis if Redis::CommandError READONLY occurs.
|
56
56
|
email:
|
57
57
|
- sonots@gmail.com
|
58
58
|
executables: []
|
@@ -97,5 +97,5 @@ rubyforge_project:
|
|
97
97
|
rubygems_version: 2.5.1
|
98
98
|
signing_key:
|
99
99
|
specification_version: 4
|
100
|
-
summary: Reconnect redis if Redis::CommandError READONLY
|
100
|
+
summary: Reconnect redis if Redis::CommandError READONLY occurs.
|
101
101
|
test_files: []
|