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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 99bf3c8d0b6f2e6f28e9d495afed579f9840898c
4
- data.tar.gz: d8e6e5295fbf9e8de451f956ee4a1fa999cc843b
3
+ metadata.gz: 15ff6c001cad1dccfdde9ba2c50f13b9993e432c
4
+ data.tar.gz: 8b631aa7157e62ff540abdb75c2f4972e617879b
5
5
  SHA512:
6
- metadata.gz: 0a7ee1b9cf6d59033fbd1b28067438e0802581354383d1ac156bcb3ad9b2a8a2dbd1ee9fb5d4f0db299bcc2fcce67bf7c527b41e9c6e3381bffdf84beae63a4b
7
- data.tar.gz: 959ca49d8e7bba3323c5080e89d2e587db66e1f1bfec18e0e5221f2c43e9425cf647c6718ceda91742cd7ffa6bc01cada2b5d9a6fdaf8b2901f9b059349da24f
6
+ metadata.gz: 923f28e0401979e5a86a68a628a516cc3fd56f7347f0125635fcb6e7bde0a9b0fa2be07147211c90c7d3301582ad78ad59a89bd184a6b7ba61a6c28eba98c110
7
+ data.tar.gz: 39729e0ea98fbc89a64e1e56111a08823bf3e2c291899760fdbc0d8df22dd074e44e4b4ab851ee456f5fb2fa9dca30540492a549e0d5547e862b1b2b15ead996
@@ -1,3 +1,8 @@
1
+ # 0.1.1 (2016-08-24)
2
+
3
+ * Make configurable `reconnect_attempts` and `max_retry_interval`
4
+
1
5
  # 0.1.0 (2016-08-24)
2
6
 
3
7
  First version
8
+
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.` appears because of failover.
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
- logger = Logger.new(STDOUT)
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 read_with_reconnect_with_readonly
11
- reply = read_without_reconnect_with_readonly
12
- if reply.is_a?(CommandError)
13
- logger.info { "Reconnect: #{reply.message}" } if logger
14
- raise Redis::ReadonlyConnectionError.new(reply.message)
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 :read_without_reconnect_with_readonly :read
19
- alias :read :read_with_reconnect_with_readonly
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
@@ -1,5 +1,5 @@
1
1
  class Redis
2
- module ReconnectWithReadonly
3
- VERSION = "0.1.0"
2
+ class ReconnectWithReadonly
3
+ VERSION = "0.1.1"
4
4
  end
5
5
  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 appears.}
13
- spec.description = %q{Reconnect redis if Redis::CommandError READONLY appears.}
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.0
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 appears.
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 appears.
100
+ summary: Reconnect redis if Redis::CommandError READONLY occurs.
101
101
  test_files: []