redis-sentinel 1.4.1 → 1.5.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 +4 -4
- data/CHANGELOG.md +21 -0
- data/README.md +19 -0
- data/Rakefile +9 -1
- data/example/redis-master.conf +1 -1
- data/example/redis-slave.conf +1 -1
- data/lib/redis-sentinel.rb +1 -0
- data/lib/redis-sentinel/client.rb +101 -25
- data/lib/redis-sentinel/redis.rb +13 -0
- data/lib/redis-sentinel/version.rb +1 -1
- data/spec/redis-sentinel/client_spec.rb +65 -5
- data/spec/redis-sentinel/em_client_spec.rb +2 -1
- metadata +19 -20
- data/.ruby-gemset +0 -1
- data/.ruby-version +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 822e055ecb4e148a1bf08b701e21f6712c519373
|
4
|
+
data.tar.gz: de6b225b065c14d3e429f19a94aa786aa728c9f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b6a20ab1e214763b79a47aa0122ea054e45ee9527512a1a56ffc27f6caea384c495d153fe229cb184459e8482805eef7d3377387a83ed377c0d0710952ecda2
|
7
|
+
data.tar.gz: 00e40455360c4969dca6f38cfe2aa9707ead89f04e4a0eff35565ac3977c471979acc23f22ff18524337867d942734ab37dc3c0a44a3fff3b3012c017f8350f7
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 1.5.0
|
4
|
+
|
5
|
+
* Subscribe +switch-master again
|
6
|
+
* Prevents master discovery to get stuck in endless loop if sentinels
|
7
|
+
are not available
|
8
|
+
* Always reconnect at least once, even if reconnect timeout is 0
|
9
|
+
* Catch networking errors which bubble up past redis
|
10
|
+
|
11
|
+
## 1.4.4
|
12
|
+
|
13
|
+
* Allow client to return list of slaves
|
14
|
+
* Fix compatibility issues with ruby 1.8.7
|
15
|
+
|
16
|
+
## 1.4.3
|
17
|
+
|
18
|
+
* Fix for pipelined requests and readonly calls
|
19
|
+
|
20
|
+
## 1.4.2
|
21
|
+
|
22
|
+
* Fix sentinel reconnection broken
|
23
|
+
|
3
24
|
## 1.4.1
|
4
25
|
|
5
26
|
* Fix only one sentinel client reconnect issue
|
data/README.md
CHANGED
@@ -37,6 +37,11 @@ Sentinels can also be specified using a URI. This URI syntax is required when us
|
|
37
37
|
config.cache_store = :redis_store, { master_name: "master1",
|
38
38
|
sentinels: ['sentinel://localhost:26379', 'sentinel://localhost:26380'] }
|
39
39
|
|
40
|
+
After doing the above, you might still see `#<Redis client v3.1.0 for redis://localhost:6379/0>`.
|
41
|
+
This is fine because redis-sentinel will only try to connect when it is actually required.
|
42
|
+
|
43
|
+
However, if none of the sentinel servers can be reached, a Redis::CannotConnectError will be thrown.
|
44
|
+
|
40
45
|
There are two additional options:
|
41
46
|
|
42
47
|
1. `:failover_reconnect_timeout` (seconds) will block for that long when
|
@@ -46,6 +51,20 @@ There are two additional options:
|
|
46
51
|
2. `:failover_reconnect_wait` (seconds) how long to sleep after each
|
47
52
|
failed reconnect during a failover event. Defaults to 0.1s.
|
48
53
|
|
54
|
+
## Slaves clients
|
55
|
+
|
56
|
+
If you need it, you can get an array of Redis clients, each pointing to one of the slaves:
|
57
|
+
|
58
|
+
client = Redis.new(master_name: "master1", sentinels: [{host: "localhost", port: 26379}, {host: "localhost", port: 26380}])
|
59
|
+
client.slaves
|
60
|
+
# => [#<Redis client v3.0.7 for redis://127.0.0.1:6380/0>, #<Redis client v3.0.7 for redis://127.0.0.1:6381/0>]
|
61
|
+
|
62
|
+
You can also get an array of all the clients (master + slaves):
|
63
|
+
|
64
|
+
client = Redis.new(master_name: "master1", sentinels: [{host: "localhost", port: 26379}, {host: "localhost", port: 26380}])
|
65
|
+
client.all_clients
|
66
|
+
# => [#<Redis client v3.0.7 for redis://127.0.0.1:6379/0>, #<Redis client v3.0.7 for redis://127.0.0.1:6380/0>, #<Redis client v3.0.7 for redis://127.0.0.1:6381/0>]
|
67
|
+
|
49
68
|
## Example
|
50
69
|
|
51
70
|
Start redis master server, listen on port 16379
|
data/Rakefile
CHANGED
@@ -8,7 +8,7 @@ require "rspec/core/rake_task"
|
|
8
8
|
|
9
9
|
|
10
10
|
RSpec::Core::RakeTask.new(:spec) do |spec|
|
11
|
-
spec.pattern = "spec
|
11
|
+
spec.pattern = "spec/redis-sentinel/client_spec.rb"
|
12
12
|
end
|
13
13
|
|
14
14
|
RSpec::Core::RakeTask.new('spec:progress') do |spec|
|
@@ -16,4 +16,12 @@ RSpec::Core::RakeTask.new('spec:progress') do |spec|
|
|
16
16
|
spec.pattern = "spec/**/*_spec.rb"
|
17
17
|
end
|
18
18
|
|
19
|
+
task :console do
|
20
|
+
require 'irb'
|
21
|
+
require 'irb/completion'
|
22
|
+
require 'redis-sentinel'
|
23
|
+
ARGV.clear
|
24
|
+
IRB.start
|
25
|
+
end
|
26
|
+
|
19
27
|
task :default => :spec
|
data/example/redis-master.conf
CHANGED
@@ -50,7 +50,7 @@ loglevel notice
|
|
50
50
|
# Specify the log file name. Also 'stdout' can be used to force
|
51
51
|
# Redis to log on the standard output. Note that if you use standard
|
52
52
|
# output for logging but daemonize, logs will be sent to /dev/null
|
53
|
-
logfile
|
53
|
+
logfile ""
|
54
54
|
|
55
55
|
# To enable logging to the system logger, just set 'syslog-enabled' to yes,
|
56
56
|
# and optionally update the other syslog parameters to suit your needs.
|
data/example/redis-slave.conf
CHANGED
@@ -50,7 +50,7 @@ loglevel notice
|
|
50
50
|
# Specify the log file name. Also 'stdout' can be used to force
|
51
51
|
# Redis to log on the standard output. Note that if you use standard
|
52
52
|
# output for logging but daemonize, logs will be sent to /dev/null
|
53
|
-
logfile
|
53
|
+
logfile ""
|
54
54
|
|
55
55
|
# To enable logging to the system logger, just set 'syslog-enabled' to yes,
|
56
56
|
# and optionally update the other syslog parameters to suit your needs.
|
data/lib/redis-sentinel.rb
CHANGED
@@ -15,6 +15,8 @@ class Redis::Client
|
|
15
15
|
@failover_reconnect_wait = fetch_option(options, :failover_reconnect_wait) ||
|
16
16
|
DEFAULT_FAILOVER_RECONNECT_WAIT_SECONDS
|
17
17
|
|
18
|
+
Thread.new { watch_sentinel } if sentinel? && !fetch_option(options, :async)
|
19
|
+
|
18
20
|
initialize_without_sentinel(options)
|
19
21
|
end
|
20
22
|
|
@@ -36,14 +38,14 @@ class Redis::Client
|
|
36
38
|
alias connect connect_with_sentinel
|
37
39
|
|
38
40
|
def sentinel?
|
39
|
-
@master_name && @sentinels_options
|
41
|
+
!!(@master_name && @sentinels_options)
|
40
42
|
end
|
41
43
|
|
42
44
|
def auto_retry_with_timeout(&block)
|
43
45
|
deadline = @failover_reconnect_timeout.to_i + Time.now.to_f
|
44
46
|
begin
|
45
47
|
block.call
|
46
|
-
rescue Redis::CannotConnectError
|
48
|
+
rescue Redis::CannotConnectError, Errno::EHOSTDOWN, Errno::EHOSTUNREACH
|
47
49
|
raise if Time.now.to_f > deadline
|
48
50
|
sleep @failover_reconnect_wait
|
49
51
|
retry
|
@@ -59,14 +61,16 @@ class Redis::Client
|
|
59
61
|
end
|
60
62
|
|
61
63
|
def refresh_sentinels_list
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
64
|
+
current_sentinel.sentinel("sentinels", @master_name).each do |response|
|
65
|
+
@sentinels_options << {:host => response[3], :port => response[5]}
|
66
|
+
end
|
67
|
+
@sentinels_options.uniq! {|h| h.values_at(:host, :port) }
|
66
68
|
end
|
67
69
|
|
68
70
|
def discover_master
|
71
|
+
attempts = 0
|
69
72
|
while true
|
73
|
+
attempts += 1
|
70
74
|
try_next_sentinel
|
71
75
|
|
72
76
|
begin
|
@@ -79,14 +83,45 @@ class Redis::Client
|
|
79
83
|
else
|
80
84
|
# A null reply
|
81
85
|
end
|
82
|
-
rescue Redis::CommandError
|
83
|
-
|
84
|
-
rescue Redis::CannotConnectError
|
85
|
-
#
|
86
|
+
rescue Redis::CommandError => e
|
87
|
+
raise unless e.message.include?("IDONTKNOW")
|
88
|
+
rescue Redis::CannotConnectError, Errno::EHOSTDOWN, Errno::EHOSTUNREACH => e
|
89
|
+
# failed to connect to current sentinel server
|
90
|
+
raise e if attempts > @sentinels_options.count
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def discover_slaves
|
96
|
+
while true
|
97
|
+
try_next_sentinel
|
98
|
+
|
99
|
+
begin
|
100
|
+
slaves_info = current_sentinel.sentinel("slaves", @master_name)
|
101
|
+
@slaves = slaves_info.map do |info|
|
102
|
+
info = Hash[*info]
|
103
|
+
::Redis.new(@options.merge(:host => info['ip'], :port => info['port'], :driver => info[:driver]))
|
104
|
+
end
|
105
|
+
|
106
|
+
break
|
107
|
+
rescue Redis::CommandError => e
|
108
|
+
raise unless e.message.include?("IDONTKNOW")
|
109
|
+
rescue Redis::CannotConnectError, Errno::EHOSTDOWN, Errno::EHOSTUNREACH
|
110
|
+
# failed to connect to current sentinel server
|
86
111
|
end
|
87
112
|
end
|
88
113
|
end
|
89
114
|
|
115
|
+
def slaves
|
116
|
+
discover_slaves
|
117
|
+
@slaves
|
118
|
+
end
|
119
|
+
|
120
|
+
def all_clients
|
121
|
+
clients = slaves
|
122
|
+
clients.unshift ::Redis.new @options
|
123
|
+
end
|
124
|
+
|
90
125
|
def disconnect_with_sentinels
|
91
126
|
current_sentinel.client.disconnect if current_sentinel
|
92
127
|
disconnect_without_sentinels
|
@@ -96,21 +131,60 @@ class Redis::Client
|
|
96
131
|
alias disconnect disconnect_with_sentinels
|
97
132
|
|
98
133
|
def call_with_readonly_protection(*args, &block)
|
99
|
-
|
100
|
-
call_without_readonly_protection(*args, &block)
|
101
|
-
rescue Redis::CommandError => e
|
102
|
-
if e.message == "READONLY You can't write against a read only slave."
|
103
|
-
reconnect
|
104
|
-
retry if (tries += 1) < 4
|
105
|
-
else
|
106
|
-
raise
|
107
|
-
end
|
134
|
+
readonly_protection_with_timeout(:call_without_readonly_protection, *args, &block)
|
108
135
|
end
|
109
136
|
|
110
137
|
alias call_without_readonly_protection call
|
111
138
|
alias call call_with_readonly_protection
|
112
139
|
|
140
|
+
def call_pipeline_with_readonly_protection(*args, &block)
|
141
|
+
readonly_protection_with_timeout(:call_pipeline_without_readonly_protection, *args, &block)
|
142
|
+
end
|
143
|
+
|
144
|
+
alias call_pipeline_without_readonly_protection call_pipeline
|
145
|
+
alias call_pipeline call_pipeline_with_readonly_protection
|
146
|
+
|
147
|
+
def watch_sentinel
|
148
|
+
while true
|
149
|
+
sentinel = Redis.new(@sentinels_options[0])
|
150
|
+
|
151
|
+
begin
|
152
|
+
sentinel.psubscribe("*") do |on|
|
153
|
+
on.pmessage do |pattern, channel, message|
|
154
|
+
next if channel != "+switch-master"
|
155
|
+
|
156
|
+
master_name, old_host, old_port, new_host, new_port = message.split(" ")
|
157
|
+
|
158
|
+
next if master_name != @master_name
|
159
|
+
|
160
|
+
@options.merge!(host: new_host, port: new_port.to_i)
|
161
|
+
|
162
|
+
@logger.debug "Failover: #{old_host}:#{old_port} => #{new_host}:#{new_port}" if @logger && @logger.debug?
|
163
|
+
|
164
|
+
disconnect
|
165
|
+
end
|
166
|
+
end
|
167
|
+
rescue Redis::CannotConnectError, Errno::EHOSTDOWN, Errno::EHOSTUNREACH
|
168
|
+
try_next_sentinel
|
169
|
+
sleep 1
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
113
174
|
private
|
175
|
+
def readonly_protection_with_timeout(method, *args, &block)
|
176
|
+
deadline = @failover_reconnect_timeout.to_i + Time.now.to_f
|
177
|
+
send(method, *args, &block)
|
178
|
+
rescue Redis::CommandError => e
|
179
|
+
if e.message.include? "READONLY You can't write against a read only slave."
|
180
|
+
reconnect
|
181
|
+
raise if Time.now.to_f > deadline
|
182
|
+
sleep @failover_reconnect_wait
|
183
|
+
retry
|
184
|
+
else
|
185
|
+
raise
|
186
|
+
end
|
187
|
+
end
|
114
188
|
|
115
189
|
def fetch_option(options, key)
|
116
190
|
options.delete(key) || options.delete(key.to_s)
|
@@ -120,14 +194,16 @@ class Redis::Client
|
|
120
194
|
return if options.nil?
|
121
195
|
|
122
196
|
sentinel_options = []
|
123
|
-
options.each do |
|
124
|
-
if
|
125
|
-
|
197
|
+
options.each do |opts|
|
198
|
+
opts = opts[:url] if opts.is_a?(Hash) && opts.key?(:url)
|
199
|
+
case opts
|
200
|
+
when Hash
|
201
|
+
sentinel_options << opts
|
126
202
|
else
|
127
|
-
uri = URI.parse(
|
203
|
+
uri = URI.parse(opts)
|
128
204
|
sentinel_options << {
|
129
|
-
|
130
|
-
|
205
|
+
:host => uri.host,
|
206
|
+
:port => uri.port
|
131
207
|
}
|
132
208
|
end
|
133
209
|
end
|
@@ -2,19 +2,36 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Redis::Client do
|
4
4
|
let(:client) { double("Client", :reconnect => true) }
|
5
|
-
let(:current_sentinel) { double("Redis", :client => client
|
5
|
+
let(:current_sentinel) { double("Redis", :client => client) }
|
6
6
|
|
7
7
|
let(:sentinels) do
|
8
8
|
[
|
9
9
|
{ :host => "localhost", :port => 26379 },
|
10
|
-
'sentinel://localhost:26380'
|
10
|
+
'sentinel://localhost:26380',
|
11
|
+
{ :url => 'sentinel://localhost:26381' },
|
12
|
+
]
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:slaves_reply) do
|
16
|
+
[
|
17
|
+
["ip", "slave-0", "port", "6379"],
|
18
|
+
["ip", "slave-1", "port", "6380"],
|
19
|
+
["ip", "slave-2", "port", "6381"]
|
11
20
|
]
|
12
21
|
end
|
13
22
|
|
14
23
|
subject { Redis::Client.new(:master_name => "master", :master_password => "foobar",
|
15
24
|
:sentinels => sentinels) }
|
16
25
|
|
17
|
-
|
26
|
+
context "new instances" do
|
27
|
+
it "should parse sentinel options" do
|
28
|
+
expect(subject.instance_variable_get(:@sentinels_options)).to match_array [
|
29
|
+
{:host=>"localhost", :port=>26379},
|
30
|
+
{:host=>"localhost", :port=>26380},
|
31
|
+
{:host=>"localhost", :port=>26381}
|
32
|
+
]
|
33
|
+
end
|
34
|
+
end
|
18
35
|
|
19
36
|
context "#sentinel?" do
|
20
37
|
it "should be true if passing sentiels and master_name options" do
|
@@ -47,6 +64,8 @@ describe Redis::Client do
|
|
47
64
|
end
|
48
65
|
|
49
66
|
context "#try_next_sentinel" do
|
67
|
+
before { allow(Redis).to receive(:new).and_return(current_sentinel) }
|
68
|
+
|
50
69
|
it "returns next sentinel server" do
|
51
70
|
expect(subject.try_next_sentinel).to eq current_sentinel
|
52
71
|
end
|
@@ -57,13 +76,15 @@ describe Redis::Client do
|
|
57
76
|
allow(subject).to receive(:current_sentinel).and_return(current_sentinel)
|
58
77
|
expect(current_sentinel).to receive(:sentinel).with("sentinels", "master").and_return([
|
59
78
|
["name", "localhost:26381", "ip", "localhost", "port", 26380],
|
60
|
-
["name", "localhost:26381", "ip", "localhost", "port", 26381]
|
79
|
+
["name", "localhost:26381", "ip", "localhost", "port", 26381],
|
80
|
+
["name", "localhost:26381", "ip", "localhost", "port", 26382],
|
61
81
|
])
|
62
82
|
subject.refresh_sentinels_list
|
63
83
|
expect(subject.instance_variable_get(:@sentinels_options)).to eq [
|
64
84
|
{:host => "localhost", :port => 26379},
|
65
85
|
{:host => "localhost", :port => 26380},
|
66
|
-
{:host => "localhost", :port => 26381}
|
86
|
+
{:host => "localhost", :port => 26381},
|
87
|
+
{:host => "localhost", :port => 26382},
|
67
88
|
]
|
68
89
|
end
|
69
90
|
end
|
@@ -90,12 +111,51 @@ describe Redis::Client do
|
|
90
111
|
expect(subject.port).to eq 8888
|
91
112
|
end
|
92
113
|
|
114
|
+
it "selects next sentinel if sentinel doesn't know" do
|
115
|
+
expect(current_sentinel).to receive(:sentinel).with("get-master-addr-by-name", "master").and_raise(Redis::CommandError.new("IDONTKNOW: No idea"))
|
116
|
+
expect(current_sentinel).to receive(:sentinel).with("get-master-addr-by-name", "master").and_return(["master", 8888])
|
117
|
+
subject.discover_master
|
118
|
+
expect(subject.host).to eq "master"
|
119
|
+
expect(subject.port).to eq 8888
|
120
|
+
end
|
121
|
+
|
122
|
+
it "raises error if try_next_sentinel raises error" do
|
123
|
+
expect(current_sentinel).to receive(:sentinel).with("get-master-addr-by-name", "master").and_raise(Redis::CommandError.new("ERR: No such command"))
|
124
|
+
expect { subject.discover_master }.to raise_error(Redis::CommandError)
|
125
|
+
end
|
126
|
+
|
93
127
|
it "raises error if try_next_sentinel raises error" do
|
94
128
|
expect(subject).to receive(:try_next_sentinel).and_raise(Redis::CannotConnectError)
|
95
129
|
expect { subject.discover_master }.to raise_error(Redis::CannotConnectError)
|
96
130
|
end
|
97
131
|
end
|
98
132
|
|
133
|
+
context "#discover_slaves" do
|
134
|
+
before do
|
135
|
+
allow(subject).to receive(:try_next_sentinel)
|
136
|
+
allow(subject).to receive(:refresh_sentinels_list)
|
137
|
+
allow(subject).to receive(:current_sentinel).and_return(current_sentinel)
|
138
|
+
expect(current_sentinel).to receive(:sentinel).with("slaves", "master").and_return(slaves_reply)
|
139
|
+
|
140
|
+
slaves = slaves_reply.map do |info|
|
141
|
+
info = Hash[*info]
|
142
|
+
double("Redis", :host => info['ip'], :port => info['port'])
|
143
|
+
end
|
144
|
+
|
145
|
+
allow(Redis).to receive(:new).and_return(*slaves)
|
146
|
+
end
|
147
|
+
|
148
|
+
it "discovers slaves correctly" do
|
149
|
+
slaves = subject.slaves
|
150
|
+
|
151
|
+
expect(slaves.size).to eq 3
|
152
|
+
3.times do |i|
|
153
|
+
expect(slaves[i].host).to eq "slave-#{i.to_s}"
|
154
|
+
expect(slaves[i].port.to_i).to eq (6379 + i)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
99
159
|
context "#auto_retry_with_timeout" do
|
100
160
|
context "no failover reconnect timeout set" do
|
101
161
|
subject { Redis::Client.new }
|
@@ -5,7 +5,8 @@ require "eventmachine"
|
|
5
5
|
describe Redis::Client do
|
6
6
|
context "#auto_retry_with_timeout" do
|
7
7
|
subject { described_class.new(:failover_reconnect_timeout => 3,
|
8
|
-
|
8
|
+
:failover_reconnect_wait => 0.1,
|
9
|
+
:async => true) }
|
9
10
|
context "configured wait time" do
|
10
11
|
|
11
12
|
it "uses the wait time and blocks em" do
|
metadata
CHANGED
@@ -1,97 +1,97 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis-sentinel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Richard Huang
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-10-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: eventmachine
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: em-synchrony
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: hiredis
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
description: another redis automatic master/slave failover solution for ruby by using
|
@@ -102,9 +102,7 @@ executables: []
|
|
102
102
|
extensions: []
|
103
103
|
extra_rdoc_files: []
|
104
104
|
files:
|
105
|
-
- .gitignore
|
106
|
-
- .ruby-gemset
|
107
|
-
- .ruby-version
|
105
|
+
- ".gitignore"
|
108
106
|
- CHANGELOG.md
|
109
107
|
- CONTRIBUTING.md
|
110
108
|
- Gemfile
|
@@ -122,6 +120,7 @@ files:
|
|
122
120
|
- lib/em-synchrony/redis-sentinel.rb
|
123
121
|
- lib/redis-sentinel.rb
|
124
122
|
- lib/redis-sentinel/client.rb
|
123
|
+
- lib/redis-sentinel/redis.rb
|
125
124
|
- lib/redis-sentinel/version.rb
|
126
125
|
- redis-sentinel.gemspec
|
127
126
|
- spec/redis-sentinel/client_spec.rb
|
@@ -136,17 +135,17 @@ require_paths:
|
|
136
135
|
- lib
|
137
136
|
required_ruby_version: !ruby/object:Gem::Requirement
|
138
137
|
requirements:
|
139
|
-
- -
|
138
|
+
- - ">="
|
140
139
|
- !ruby/object:Gem::Version
|
141
140
|
version: '0'
|
142
141
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
143
142
|
requirements:
|
144
|
-
- -
|
143
|
+
- - ">="
|
145
144
|
- !ruby/object:Gem::Version
|
146
145
|
version: '0'
|
147
146
|
requirements: []
|
148
147
|
rubyforge_project:
|
149
|
-
rubygems_version: 2.
|
148
|
+
rubygems_version: 2.2.2
|
150
149
|
signing_key:
|
151
150
|
specification_version: 4
|
152
151
|
summary: another redis automatic master/slave failover solution for ruby by using
|
data/.ruby-gemset
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
redis-sentinel
|
data/.ruby-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
ruby-2.0.0
|