redis-slave-read 0.1 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 32c1f6b501f4d1f2e013277b17194a45f555e0cf
4
+ data.tar.gz: d608989faa6527ac97a0ecc88788928dcecb0509
5
+ SHA512:
6
+ metadata.gz: e1be26d56b3b8a03279ce70954d5a166c916f3751b8b0d01c247470bf2f4232f32ce2c4a81f70e7dde8619b7c9b56f75e8eda1c3f7c5b02e102e55d582ac1948
7
+ data.tar.gz: fb782d7638f89f69daa000135a04cb841d3b9049baae79962644bb20fc34249edc7a0e83ca49ef36575c804d77b4328a1f7667b22f3cd04f3d748f2c77c7e465
data/Gemfile CHANGED
@@ -2,3 +2,4 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
  gem "rspec"
5
+ gem "rake"
data/README.md CHANGED
@@ -23,7 +23,7 @@ Rather than using a Redis instance, create a wrapper that wraps multiple Redis c
23
23
  master = Redis.new "localhost:6379"
24
24
  slave1 = Redis.new "localhost:6389"
25
25
  slave2 = Redis.new "localhost:6399"
26
- $redis = Redis::SlaveRead::Interface::HiRedis.new(master: master, slaves: [slave1, slave2])
26
+ $redis = Redis::SlaveRead::Interface::Hiredis.new(master: master, slaves: [slave1, slave2])
27
27
 
28
28
  Make sure that your slaves are set to be slaved to the master, like `slaveof localhost 6379`
29
29
 
@@ -1,29 +1,12 @@
1
+ require 'connection_pool'
2
+
1
3
  module ActiveSupport
2
4
  module Cache
3
- class RedisStore < Store
4
- # Instantiate the store.
5
- #
6
- # Example:
7
- # RedisStore.new
8
- # # => host: localhost, port: 6379, db: 0
9
- #
10
- # RedisStore.new "example.com"
11
- # # => host: example.com, port: 6379, db: 0
12
- #
13
- # RedisStore.new "example.com:23682"
14
- # # => host: example.com, port: 23682, db: 0
15
- #
16
- # RedisStore.new "example.com:23682/1"
17
- # # => host: example.com, port: 23682, db: 1
18
- #
19
- # RedisStore.new "example.com:23682/1/theplaylist"
20
- # # => host: example.com, port: 23682, db: 1, namespace: theplaylist
21
- #
22
- # RedisStore.new "localhost:6379/0", "localhost:6380/0"
23
- # # => instantiate a cluster
24
- def initialize(*addresses)
25
- @data = ::Redis::Factory.create(addresses)
26
- super(addresses.extract_options!)
5
+ class RedisStoreSlaveRead < Store
6
+ def initialize(options = {})
7
+ @pool_options = options
8
+ init_pool @pool_options
9
+ @options = {}
27
10
  end
28
11
 
29
12
  def write(name, value, options = nil)
@@ -43,7 +26,7 @@ module ActiveSupport
43
26
  instrument(:delete_matched, matcher.inspect) do
44
27
  matcher = key_matcher(matcher, options)
45
28
  begin
46
- !(keys = @data.keys(matcher)).empty? && @data.del(*keys)
29
+ @pool.with {|s| !(keys = s.keys(matcher)).empty? && s.del(*keys) }
47
30
  rescue Errno::ECONNREFUSED => e
48
31
  false
49
32
  end
@@ -57,7 +40,7 @@ module ActiveSupport
57
40
  # cache.read_multi "rabbit", "white-rabbit"
58
41
  # cache.read_multi "rabbit", "white-rabbit", :raw => true
59
42
  def read_multi(*names)
60
- values = @data.mget(*names)
43
+ values = @pool.with {|s| s.mget(*names) }
61
44
 
62
45
  # Remove the options hash before mapping keys to values
63
46
  names.extract_options!
@@ -90,7 +73,7 @@ module ActiveSupport
90
73
  # cache.read "rabbit", :raw => true # => "1"
91
74
  def increment(key, amount = 1)
92
75
  instrument(:increment, key, :amount => amount) do
93
- @data.incrby key, amount
76
+ @pool.with {|s| s.incrby key, amount }
94
77
  end
95
78
  end
96
79
 
@@ -117,36 +100,53 @@ module ActiveSupport
117
100
  # cache.read "rabbit", :raw => true # => "-1"
118
101
  def decrement(key, amount = 1)
119
102
  instrument(:decrement, key, :amount => amount) do
120
- @data.decrby key, amount
103
+ @pool.with {|s| s.decrby key, amount }
121
104
  end
122
105
  end
123
106
 
124
107
  # Clear all the data from the store.
125
108
  def clear
126
109
  instrument(:clear, nil, nil) do
127
- @data.flushdb
110
+ @pool.with {|s| s.flushdb }
128
111
  end
129
112
  end
130
113
 
131
114
  def stats
132
- @data.info
115
+ @pool.with {|s| s.info }
133
116
  end
134
117
 
135
- # Force client reconnection, useful Unicorn deployed apps.
118
+ # Force client reconnection, useful for apps deployed on forking servers.
136
119
  def reconnect
137
- @data.reconnect
120
+ init_pool @pool_options
121
+ end
122
+
123
+ def expire(key, expiry)
124
+ @pool.with {|s| s.expire key, expiry }
138
125
  end
139
126
 
140
127
  protected
128
+
129
+ def init_pool(options)
130
+ interface = options.fetch(:interface, ::Redis::SlaveRead::Interface::Hiredis)
131
+ @pool.shutdown {|node| node.disconnect } if @pool
132
+ @pool = ConnectionPool.new(:size => options.fetch(:pool_size, 1), :timeout => options.fetch(:pool_timeout, 3)) do
133
+ interface.new(
134
+ master: ::Redis::Store::Factory.create(options[:master]),
135
+ slaves: options[:slaves].map {|s| ::Redis::Store::Factory.create(s) },
136
+ read_master: false
137
+ )
138
+ end
139
+ end
140
+
141
141
  def write_entry(key, entry, options)
142
142
  method = options && options[:unless_exist] ? :setnx : :set
143
- @data.send method, key, entry, options
143
+ @pool.with {|s| s.send method, key, entry, options }
144
144
  rescue Errno::ECONNREFUSED => e
145
145
  false
146
146
  end
147
147
 
148
148
  def read_entry(key, options)
149
- entry = @data.get key, options
149
+ entry = @pool.with {|s| s.get key, options }
150
150
  if entry
151
151
  entry.is_a?(ActiveSupport::Cache::Entry) ? entry : ActiveSupport::Cache::Entry.new(entry)
152
152
  end
@@ -160,7 +160,7 @@ module ActiveSupport
160
160
  # It's really needed and use
161
161
  #
162
162
  def delete_entry(key, options)
163
- @data.del key
163
+ @pool.with {|s| s.del key }
164
164
  rescue Errno::ECONNREFUSED => e
165
165
  false
166
166
  end
@@ -1,5 +1,5 @@
1
1
  class Redis
2
2
  module SlaveRead
3
- VERSION = "0.1"
3
+ VERSION = "0.2.1"
4
4
  end
5
5
  end
@@ -17,6 +17,6 @@ Gem::Specification.new do |gem|
17
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
18
  gem.require_paths = ["lib"]
19
19
 
20
- gem.add_dependency "redis"
21
- gem.add_development_dependency "redis"
20
+ gem.add_runtime_dependency 'redis', '>= 0', '>= 0'
21
+ gem.add_runtime_dependency 'connection_pool'
22
22
  end
@@ -7,15 +7,15 @@ describe Redis::SlaveRead::Interface::Hiredis do
7
7
  subject { described_class.new master: master, slaves: slaves }
8
8
 
9
9
  it "should distribute reads between all available nodes" do
10
- master.should_receive(:get).once
11
- slaves[0].should_receive(:get).once
12
- slaves[1].should_receive(:get).once
10
+ expect(master).to receive(:get).once
11
+ expect(slaves[0]).to receive(:get).once
12
+ expect(slaves[1]).to receive(:get).once
13
13
 
14
14
  3.times { subject.get "foo" }
15
15
  end
16
16
 
17
17
  it "should always send non-reads to the master" do
18
- master.should_receive(:set).exactly(3).times
18
+ expect(master).to receive(:set).exactly(3).times
19
19
 
20
20
  3.times { subject.set "foo", "bar" }
21
21
  end
@@ -24,9 +24,9 @@ describe Redis::SlaveRead::Interface::Hiredis do
24
24
  subject { described_class.new master: master, slaves: slaves, read_master: false }
25
25
 
26
26
  it "should distribute reads between all available slaves" do
27
- master.should_receive(:get).never
28
- slaves[1].should_receive(:get).twice
29
- slaves[0].should_receive(:get).once
27
+ expect(master).to receive(:get).never
28
+ expect(slaves[1]).to receive(:get).twice
29
+ expect(slaves[0]).to receive(:get).once
30
30
 
31
31
  3.times { subject.get "foo" }
32
32
  end
@@ -34,7 +34,7 @@ describe Redis::SlaveRead::Interface::Hiredis do
34
34
 
35
35
  context "when in a multi block" do
36
36
  it "sends all commands to the master" do
37
- master.should_receive(:get).twice
37
+ expect(master).to receive(:get).twice
38
38
 
39
39
  subject.multi do
40
40
  2.times { subject.get "foo" }
@@ -44,7 +44,7 @@ describe Redis::SlaveRead::Interface::Hiredis do
44
44
 
45
45
  context "when in a pipelined block" do
46
46
  it "sends all commands to the master" do
47
- master.should_receive(:get).twice
47
+ expect(master).to receive(:get).twice
48
48
 
49
49
  subject.pipelined do
50
50
  2.times { subject.get "foo" }
@@ -54,23 +54,28 @@ describe Redis::SlaveRead::Interface::Hiredis do
54
54
 
55
55
  context "commands that distribute to all nodes" do
56
56
  it "should distribute to each node" do
57
- master.should_receive(:select).once
58
- slaves.each {|slave| slave.should_receive(:select).once }
57
+ expect(master).to receive(:select).once
58
+ slaves.each {|slave| expect(slave).to receive(:select).once }
59
59
  subject.send(:select)
60
60
  end
61
61
 
62
62
  it "should set the DB on each node" do
63
63
  subject.select 4
64
- master.client.db.should == 4
65
- slaves[0].client.db.should == 4
66
- slaves[1].client.db.should == 4
64
+ expect(master.client.db).to eq 4
65
+ expect(slaves[0].client.db).to eq 4
66
+ expect(slaves[1].client.db).to eq 4
67
67
  end
68
68
 
69
- it "should disconnect each client" do
69
+ it "should connect and disconnect each client" do
70
+ subject.connect
71
+ expect(!!master.client.connected?).to be_truthy
72
+ expect(!!slaves[0].client.connected?).to be_truthy
73
+ expect(!!slaves[1].client.connected?).to be_truthy
74
+
70
75
  subject.disconnect
71
- !!master.client.connected?.should == false
72
- !!slaves[0].client.connected?.should == false
73
- !!slaves[1].client.connected?.should == false
76
+ expect(!!master.client.connected?).to be_falsey
77
+ expect(!!slaves[0].client.connected?).to be_falsey
78
+ expect(!!slaves[1].client.connected?).to be_falsey
74
79
  end
75
80
  end
76
81
  end
metadata CHANGED
@@ -1,48 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis-slave-read
3
3
  version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: '0.1'
4
+ version: 0.2.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - Chris Heald
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-06-26 00:00:00.000000000 Z
11
+ date: 2016-04-27 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
- type: :runtime
14
+ name: redis
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
20
+ type: :runtime
22
21
  prerelease: false
23
22
  version_requirements: !ruby/object:Gem::Requirement
24
- none: false
25
23
  requirements:
26
- - - ! '>='
24
+ - - ">="
27
25
  - !ruby/object:Gem::Version
28
26
  version: '0'
29
- name: redis
30
27
  - !ruby/object:Gem::Dependency
31
- type: :development
28
+ name: connection_pool
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - ">="
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
34
+ type: :runtime
38
35
  prerelease: false
39
36
  version_requirements: !ruby/object:Gem::Requirement
40
- none: false
41
37
  requirements:
42
- - - ! '>='
38
+ - - ">="
43
39
  - !ruby/object:Gem::Version
44
40
  version: '0'
45
- name: redis
46
41
  description: Provides load balancing of reads in a cluster of Redis replicas
47
42
  email:
48
43
  - cheald@gmail.com
@@ -50,12 +45,12 @@ executables: []
50
45
  extensions: []
51
46
  extra_rdoc_files: []
52
47
  files:
53
- - .gitignore
48
+ - ".gitignore"
54
49
  - Gemfile
55
50
  - LICENSE.txt
56
51
  - README.md
57
52
  - Rakefile
58
- - lib/activesupport/lib/active_support/cache/redis_slave_read_cache.rb
53
+ - lib/active_support/cache/redis_store_slave_read.rb
59
54
  - lib/redis-slave-read.rb
60
55
  - lib/redis-slave-read/interface/base.rb
61
56
  - lib/redis-slave-read/interface/hiredis.rb
@@ -65,29 +60,27 @@ files:
65
60
  - spec/spec_helper.rb
66
61
  homepage: ''
67
62
  licenses: []
63
+ metadata: {}
68
64
  post_install_message:
69
65
  rdoc_options: []
70
66
  require_paths:
71
67
  - lib
72
68
  required_ruby_version: !ruby/object:Gem::Requirement
73
- none: false
74
69
  requirements:
75
- - - ! '>='
70
+ - - ">="
76
71
  - !ruby/object:Gem::Version
77
72
  version: '0'
78
73
  required_rubygems_version: !ruby/object:Gem::Requirement
79
- none: false
80
74
  requirements:
81
- - - ! '>='
75
+ - - ">="
82
76
  - !ruby/object:Gem::Version
83
77
  version: '0'
84
78
  requirements: []
85
79
  rubyforge_project:
86
- rubygems_version: 1.8.24
80
+ rubygems_version: 2.5.1
87
81
  signing_key:
88
- specification_version: 3
82
+ specification_version: 4
89
83
  summary: Provides load balancing of reads in a cluster of Redis replicas
90
84
  test_files:
91
85
  - spec/interface/hiredis_spec.rb
92
86
  - spec/spec_helper.rb
93
- has_rdoc: