Skip to content

Commit f7094ed

Browse files
authored
Add support for connection_pool gem (#215)
* Add support for connection_pool gem * Refactor ConnectionPool command send logic * Add ConnectionPool calls assertions to specs
1 parent 8543329 commit f7094ed

4 files changed

Lines changed: 99 additions & 9 deletions

File tree

lib/redis/namespace.rb

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,8 @@ def method_missing(command, *args, &block)
372372
"passthrough has been deprecated and will be removed in " +
373373
"redis-namespace 2.0 (at #{call_site})")
374374
end
375-
@redis.send(command, *args, &block)
375+
376+
wrapped_send(@redis, command, args, &block)
376377
else
377378
super
378379
end
@@ -477,7 +478,7 @@ def call_with_namespace(command, *args, &block)
477478
end
478479

479480
# Dispatch the command to Redis and store the result.
480-
result = @redis.send(command, *args, &block)
481+
result = wrapped_send(@redis, command, args, &block)
481482

482483
# Don't try to remove namespace from a Redis::Future, you can't.
483484
return result if result.is_a?(Redis::Future)
@@ -514,6 +515,16 @@ def ruby2_keywords_hash(kwargs)
514515
end
515516
end
516517

518+
def wrapped_send(redis_client, command, args = [], &block)
519+
if redis_client.class.name == "ConnectionPool"
520+
redis_client.with do |pool_connection|
521+
pool_connection.send(command, *args, &block)
522+
end
523+
else
524+
redis_client.send(command, *args, &block)
525+
end
526+
end
527+
517528
# Avoid modifying the caller's (pass-by-reference) arguments.
518529
def clone_args(arg)
519530
if arg.is_a?(Array)
@@ -531,13 +542,10 @@ def call_site
531542

532543
def namespaced_block(command, &block)
533544
if block.arity == 0
534-
redis.send(command, &block)
545+
wrapped_send(redis, command, &block)
535546
else
536-
redis.send(command) do |r|
537-
copy = dup
538-
copy.redis = r
539-
yield copy
540-
end
547+
outer_block = proc { |r| copy = dup; copy.redis = r; yield copy }
548+
wrapped_send(redis, command, &outer_block)
541549
end
542550
end
543551

redis-namespace.gemspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Gem::Specification.new do |s|
3131
s.add_development_dependency "rake"
3232
s.add_development_dependency "rspec", "~> 3.7"
3333
s.add_development_dependency "rspec-its"
34+
s.add_development_dependency "connection_pool"
3435

3536
s.description = <<description
3637
Adds a Redis::Namespace class which can be used to namespace calls

spec/deprecation_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
end
3232

3333
before(:each) do
34-
allow(redis).to receive(:unhandled) do |*args|
34+
allow(redis).to receive(:unhandled) do |*args|
3535
"unhandled(#{args.inspect})"
3636
end
3737
allow(redis).to receive(:flushdb).and_return("OK")

spec/redis_spec.rb

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# encoding: utf-8
22

33
require File.dirname(__FILE__) + '/spec_helper'
4+
require 'connection_pool'
45

56
describe "redis" do
67
@redis_version = Gem::Version.new(Redis.new.info["redis_version"])
@@ -184,6 +185,24 @@
184185
expect(@namespaced.mapped_mget('foo', 'baz', 'bar')).to eq({'foo'=>'1000', 'bar'=>'2000', 'baz' => nil})
185186
end
186187

188+
it "should utilize connection_pool while using a namespace with mget" do
189+
memo = @namespaced
190+
connection_pool = ConnectionPool.new(size: 2, timeout: 2) { Redis.new db: 15 }
191+
@namespaced = Redis::Namespace.new(:ns, redis: connection_pool)
192+
193+
expect(connection_pool).to receive(:with).and_call_original do |arg|
194+
expect(arg).to be(an_instance_of(Redis))
195+
end.at_least(:once)
196+
197+
@namespaced.set('foo', 1000)
198+
@namespaced.set('bar', 2000)
199+
expect(@namespaced.mapped_mget('foo', 'bar')).to eq({ 'foo' => '1000', 'bar' => '2000' })
200+
expect(@namespaced.mapped_mget('foo', 'baz', 'bar')).to eq({'foo'=>'1000', 'bar'=>'2000', 'baz' => nil})
201+
@redis.get('foo').should eq('bar')
202+
203+
@namespaced = memo
204+
end
205+
187206
it "should be able to use a namespace with mset" do
188207
@namespaced.mset('foo', '1000', 'bar', '2000')
189208
expect(@namespaced.mapped_mget('foo', 'bar')).to eq({ 'foo' => '1000', 'bar' => '2000' })
@@ -376,6 +395,26 @@
376395
expect(@namespaced.hgetall("foo")).to eq({"key1" => "value1"})
377396
end
378397

398+
it "should utilize connection_pool while adding namepsace to multi blocks" do
399+
memo = @namespaced
400+
connection_pool = ConnectionPool.new(size: 2, timeout: 2) { Redis.new db: 15 }
401+
@namespaced = Redis::Namespace.new(:ns, redis: connection_pool)
402+
403+
expect(connection_pool).to receive(:with).and_call_original do |arg|
404+
expect(arg).to be(an_instance_of(Redis))
405+
end.at_least(:once)
406+
407+
@namespaced.mapped_hmset "foo", {"key" => "value"}
408+
@namespaced.multi do |r|
409+
r.del "foo"
410+
r.mapped_hmset "foo", {"key1" => "value1"}
411+
end
412+
expect(@redis.get("foo")).to eq("bar")
413+
expect(@namespaced.hgetall("foo")).to eq({"key1" => "value1"})
414+
415+
@namespaced = memo
416+
end
417+
379418
it "should pass through multi commands without block" do
380419
@namespaced.mapped_hmset "foo", {"key" => "value"}
381420

@@ -387,6 +426,28 @@
387426
expect(@namespaced.hgetall("foo")).to eq({"key1" => "value1"})
388427
end
389428

429+
it "should utilize connection_pool while passing through multi commands without block" do
430+
memo = @namespaced
431+
connection_pool = ConnectionPool.new(size: 2, timeout: 2) { Redis.new db: 15 }
432+
@namespaced = Redis::Namespace.new(:ns, redis: connection_pool)
433+
434+
expect(connection_pool).to receive(:with).and_call_original do |arg|
435+
expect(arg).to be(an_instance_of(Redis))
436+
end.at_least(:once)
437+
438+
@namespaced.mapped_hmset "foo", {"key" => "value"}
439+
440+
@namespaced.multi
441+
@namespaced.del "foo"
442+
@namespaced.mapped_hmset "foo", {"key1" => "value1"}
443+
@namespaced.exec
444+
445+
expect(@namespaced.hgetall("foo")).to eq({"key1" => "value1"})
446+
expect(@redis.get("foo")).to eq("bar")
447+
448+
@namespaced = memo
449+
end
450+
390451
it 'should return futures without attempting to remove namespaces' do
391452
@namespaced.multi do
392453
@future = @namespaced.keys('*')
@@ -403,6 +464,26 @@
403464
expect(@namespaced.hgetall("foo")).to eq({"key1" => "value1"})
404465
end
405466

467+
it "should utilize connection_pool while adding namespace to pipelined blocks" do
468+
memo = @namespaced
469+
connection_pool = ConnectionPool.new(size: 2, timeout: 2) { Redis.new db: 15 }
470+
@namespaced = Redis::Namespace.new(:ns, redis: connection_pool)
471+
472+
expect(connection_pool).to receive(:with).and_call_original do |arg|
473+
expect(arg).to be(an_instance_of(Redis))
474+
end.at_least(:once)
475+
476+
@namespaced.mapped_hmset "foo", {"key" => "value"}
477+
@namespaced.pipelined do |r|
478+
r.del "foo"
479+
r.mapped_hmset "foo", {"key1" => "value1"}
480+
end
481+
expect(@namespaced.hgetall("foo")).to eq({"key1" => "value1"})
482+
expect(@redis.get("foo")).to eq("bar")
483+
484+
@namespaced = memo
485+
end
486+
406487
it "should returned response array from pipelined block" do
407488
@namespaced.mset "foo", "bar", "key", "value"
408489
result = @namespaced.pipelined do |r|

0 commit comments

Comments
 (0)