redis-slave-read 0.1 → 0.2.1

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.
@@ -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: