Skip to content

Commit 91a880e

Browse files
committed
Redis::Client still private. Redis exposes call, queue, commit.
1 parent b2a8529 commit 91a880e

File tree

4 files changed

+88
-46
lines changed

4 files changed

+88
-46
lines changed

lib/redis.rb

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,44 @@ def disconnect!
5959
@original_client.disconnect
6060
end
6161

62+
# Sends a command to Redis and returns its reply.
63+
#
64+
# Replies are converted to Ruby objects according to the RESP protocol, so
65+
# you can expect a Ruby array, integer or nil when Redis sends one. Higher
66+
# level transformations, such as converting an array of pairs into a Ruby
67+
# hash, are up to consumers.
68+
#
69+
# Redis error replies are raised as Ruby exceptions.
70+
def call(*command)
71+
synchronize do |client|
72+
client.call(command)
73+
end
74+
end
75+
76+
# Queues a command for pipelining.
77+
#
78+
# Commands in the queue are executed with the Redis::Client#commit method.
79+
#
80+
# See http://redis.io/topics/pipelining for more details.
81+
#
82+
def queue(*command)
83+
_queue << command
84+
end
85+
86+
# Sends all commands in the queue.
87+
#
88+
# See http://redis.io/topics/pipelining for more details.
89+
#
90+
def commit
91+
synchronize do |client|
92+
begin
93+
client.call_pipelined(_queue)
94+
ensure
95+
_queue.clear
96+
end
97+
end
98+
end
99+
62100
# Authenticate to the server.
63101
#
64102
# @param [String] password must match the password specified in the
@@ -2625,6 +2663,10 @@ def _subscription(method, channels, block)
26252663
end
26262664
end
26272665

2666+
def _queue
2667+
Thread.current[:redis_queue] ||= []
2668+
end
2669+
26282670
end
26292671

26302672
require "redis/version"

lib/redis/client.rb

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -106,18 +106,8 @@ def initialize(options = {})
106106
else
107107
@connector = Connector.new(@options)
108108
end
109-
110-
@queue = []
111109
end
112110

113-
# Sends a command to Redis and returns its reply.
114-
#
115-
# Replies are converted to Ruby objects according to the RESP protocol, so
116-
# you can expect a Ruby array, integer or nil when Redis sends one. Higher
117-
# level transformations, such as converting an array of pairs into a Ruby
118-
# hash, are up to consumers.
119-
#
120-
# Redis error replies are raised as Ruby exceptions.
121111
def call(command, &block)
122112
reply = process([command]) { read }
123113
raise reply if reply.is_a?(CommandError)
@@ -129,26 +119,6 @@ def call(command, &block)
129119
end
130120
end
131121

132-
# Queues a command for pipelining.
133-
#
134-
# Commands in the queue are executed with the Redis::Client#commit method.
135-
#
136-
# See http://redis.io/topics/pipelining for more details.
137-
#
138-
def queue(command)
139-
@queue << command
140-
end
141-
142-
# Sends all commands in the queue.
143-
#
144-
# See http://redis.io/topics/pipelining for more details.
145-
#
146-
def commit
147-
call_pipelined(@queue)
148-
ensure
149-
@queue.clear
150-
end
151-
152122
def connect
153123
@pid = Process.pid
154124

test/client_test.rb

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,54 +5,54 @@ class TestClient < Test::Unit::TestCase
55
include Helper::Client
66

77
def test_call
8-
result = r.client.call(["PING"])
8+
result = r.call("PING")
99
assert_equal result, "PONG"
1010
end
1111

1212
def test_call_with_arguments
13-
result = r.client.call(["SET", "foo", "bar"])
13+
result = r.call("SET", "foo", "bar")
1414
assert_equal result, "OK"
1515
end
1616

1717
def test_call_integers
18-
result = r.client.call(["INCR", "foo"])
18+
result = r.call("INCR", "foo")
1919
assert_equal result, 1
2020
end
2121

2222
def test_call_raise
2323
assert_raises(Redis::CommandError) do
24-
r.client.call(["INCR"])
24+
r.call("INCR")
2525
end
2626
end
2727

2828
def test_queue_commit
29-
r.client.queue(["SET", "foo", "bar"])
30-
r.client.queue(["GET", "foo"])
31-
result = r.client.commit
29+
r.queue("SET", "foo", "bar")
30+
r.queue("GET", "foo")
31+
result = r.commit
3232

3333
assert_equal result, ["OK", "bar"]
3434
end
3535

3636
def test_commit_raise
37-
r.client.queue(["SET", "foo", "bar"])
38-
r.client.queue(["INCR"])
37+
r.queue("SET", "foo", "bar")
38+
r.queue("INCR")
3939

4040
assert_raise(Redis::CommandError) do
41-
r.client.commit
41+
r.commit
4242
end
4343
end
4444

4545
def test_queue_after_error
46-
r.client.queue(["SET", "foo", "bar"])
47-
r.client.queue(["INCR"])
46+
r.queue("SET", "foo", "bar")
47+
r.queue("INCR")
4848

4949
assert_raise(Redis::CommandError) do
50-
r.client.commit
50+
r.commit
5151
end
5252

53-
r.client.queue(["SET", "foo", "bar"])
54-
r.client.queue(["INCR", "baz"])
55-
result = r.client.commit
53+
r.queue("SET", "foo", "bar")
54+
r.queue("INCR", "baz")
55+
result = r.commit
5656

5757
assert_equal result, ["OK", 1]
5858
end

test/thread_safety_test.rb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,35 @@ def test_thread_safety
2828
assert_equal ["1"], $foos.uniq
2929
assert_equal ["2"], $bars.uniq
3030
end
31+
32+
def test_thread_safety_queue_commit
33+
redis = Redis.new(OPTIONS)
34+
redis.set "foo", 1
35+
redis.set "bar", 2
36+
37+
sample = 100
38+
39+
t1 = Thread.new do
40+
sample.times do
41+
r.queue("get", "foo")
42+
end
43+
44+
$foos = r.commit
45+
end
46+
47+
t2 = Thread.new do
48+
sample.times do
49+
r.queue("get", "bar")
50+
end
51+
52+
$bars = r.commit
53+
end
54+
55+
t1.join
56+
t2.join
57+
58+
assert_equal ["1"], $foos.uniq
59+
assert_equal ["2"], $bars.uniq
60+
end
3161
end
3262
end

0 commit comments

Comments
 (0)