redic 0.0.4 → 0.0.5
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/README.md +52 -3
- data/lib/redic.rb +8 -7
- data/makefile +2 -2
- data/redic.gemspec +1 -1
- data/tests/redic_test.rb +118 -0
- data/{test → tests}/unix_test.rb +7 -7
- metadata +4 -4
- data/test/redic_test.rb +0 -78
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c3cb18b1fbaf7287872bb80f00dcf56ea80c876
|
4
|
+
data.tar.gz: f73a0f93ee0b747238614d6eefca1272b1df6e94
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5e1b59a35e39d75d09443205e334d55d18c00093de1902a807eb85989dd17ca898c8e6e6964dc25d688c522503739dc250ad5ff1a3c8a706d2df784dbf236cb7
|
7
|
+
data.tar.gz: c0f0d5cc628053da0b59b434168141a3789b642a6098ddc88dd067acfa35662f824a4f7001538141eea69c750a1679f2ff31df0c0099c53fa21e57f4202eb091
|
data/README.md
CHANGED
@@ -13,7 +13,7 @@ library for golang.
|
|
13
13
|
## Usage
|
14
14
|
|
15
15
|
```ruby
|
16
|
-
# Accepts
|
16
|
+
# Accepts a Redis URL and defaults to "redis://127.0.0.1:6379".
|
17
17
|
redis = Redic.new
|
18
18
|
|
19
19
|
# Processes the command and returns the response.
|
@@ -23,12 +23,61 @@ assert_equal "bar", redis.call("GET", "foo")
|
|
23
23
|
|
24
24
|
# Pipelining is implemented by buffering commands,
|
25
25
|
# then calling Redic#run
|
26
|
-
redis.
|
27
|
-
redis.
|
26
|
+
redis.pipe("SET", "foo", "bar")
|
27
|
+
redis.pipe("GET", "foo")
|
28
28
|
|
29
29
|
assert_equal ["OK", "bar"], redis.run
|
30
30
|
```
|
31
31
|
|
32
|
+
## Differences with redis-rb
|
33
|
+
|
34
|
+
Redic uses [hiredis][hiredis] for the connection and for parsing
|
35
|
+
the replies. There are no alternative connection drivers. Unlike
|
36
|
+
[redis-rb][redis-rb] it doesn't define all the Redis commands, and
|
37
|
+
instead it acts as a transport layer. The lock provided is smaller
|
38
|
+
than that of redis-rb, as it only wraps the writing and reading from
|
39
|
+
the connection. So even if both clients are thread-safe by default,
|
40
|
+
the peformance of a smaller lock is marginally better.
|
41
|
+
|
42
|
+
## Limitations
|
43
|
+
|
44
|
+
When a client enters a subscribed mode, further reads to retrieve the
|
45
|
+
messages are not thread safe. It is very important to take this into
|
46
|
+
account and to create a different client if you need to send different
|
47
|
+
operations while a client is subscribed to a channel.
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
# Example of pub/sub usage.
|
51
|
+
c1 = Redic.new
|
52
|
+
c2 = Redic.new
|
53
|
+
|
54
|
+
# After this command, the client is no longer thread safe.
|
55
|
+
c1.call("SUBSCRIBE", "foo")
|
56
|
+
|
57
|
+
# That's why we need to publish from a different connection.
|
58
|
+
c2.call("PUBLISH", "foo")
|
59
|
+
|
60
|
+
# Note that this operation is not thread safe.
|
61
|
+
assert_equal ["message", "foo", "value1"], c1.client.read
|
62
|
+
```
|
63
|
+
|
64
|
+
You can wrap thread unsafe operations in a mutex:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
redis = Redic.new
|
68
|
+
|
69
|
+
mutex = Mutex.new
|
70
|
+
|
71
|
+
mutex.synchronize do
|
72
|
+
redis.call("MONITOR")
|
73
|
+
|
74
|
+
# Display every command sent to Redis.
|
75
|
+
loop do
|
76
|
+
puts redis.client.read
|
77
|
+
end
|
78
|
+
end
|
79
|
+
```
|
80
|
+
|
32
81
|
## Installation
|
33
82
|
|
34
83
|
You can install it using rubygems.
|
data/lib/redic.rb
CHANGED
@@ -2,11 +2,12 @@ require "redic/client"
|
|
2
2
|
|
3
3
|
class Redic
|
4
4
|
attr :url
|
5
|
+
attr :client
|
5
6
|
|
6
7
|
def initialize(url = "redis://127.0.0.1:6379")
|
7
8
|
@url = url
|
8
9
|
@client = Redic::Client.new(url)
|
9
|
-
@
|
10
|
+
@queue = []
|
10
11
|
end
|
11
12
|
|
12
13
|
def call(*args)
|
@@ -16,21 +17,21 @@ class Redic
|
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
19
|
-
def
|
20
|
-
@
|
20
|
+
def queue(*args)
|
21
|
+
@queue << args
|
21
22
|
end
|
22
23
|
|
23
|
-
def
|
24
|
+
def commit
|
24
25
|
@client.connect do
|
25
|
-
@
|
26
|
+
@queue.each do |args|
|
26
27
|
@client.write(args)
|
27
28
|
end
|
28
29
|
|
29
|
-
@
|
30
|
+
@queue.map do
|
30
31
|
@client.read
|
31
32
|
end
|
32
33
|
end
|
33
34
|
ensure
|
34
|
-
@
|
35
|
+
@queue.clear
|
35
36
|
end
|
36
37
|
end
|
data/makefile
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
|
2
|
-
RUBYLIB=./lib cutest
|
1
|
+
test:
|
2
|
+
RUBYLIB=./lib cutest tests/*.rb
|
data/redic.gemspec
CHANGED
data/tests/redic_test.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
require File.expand_path("../lib/redic", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
REDIS_URL = "redis://localhost:6379/3"
|
4
|
+
|
5
|
+
prepare do
|
6
|
+
Redic.new(REDIS_URL).call("FLUSHDB")
|
7
|
+
end
|
8
|
+
|
9
|
+
setup do
|
10
|
+
Redic.new(REDIS_URL)
|
11
|
+
end
|
12
|
+
|
13
|
+
test "url" do |c|
|
14
|
+
assert_equal "redis://localhost:6379/3", c.url
|
15
|
+
end
|
16
|
+
|
17
|
+
test "normal commands" do |c|
|
18
|
+
c.call("SET", "foo", "bar")
|
19
|
+
|
20
|
+
assert_equal "bar", c.call("GET", "foo")
|
21
|
+
end
|
22
|
+
|
23
|
+
test "pipelining" do |c|
|
24
|
+
c.queue("SET", "foo", "bar")
|
25
|
+
c.queue("GET", "foo")
|
26
|
+
|
27
|
+
assert_equal ["OK", "bar"], c.commit
|
28
|
+
end
|
29
|
+
|
30
|
+
test "multi/exec" do |c|
|
31
|
+
c.queue("MULTI")
|
32
|
+
c.queue("SET", "foo", "bar")
|
33
|
+
c.queue("EXEC")
|
34
|
+
|
35
|
+
assert_equal ["OK", "QUEUED", ["OK"]], c.commit
|
36
|
+
end
|
37
|
+
|
38
|
+
test "runtime errors" do |c|
|
39
|
+
res = c.call("KABLAMMO")
|
40
|
+
|
41
|
+
assert res.is_a?(RuntimeError)
|
42
|
+
end
|
43
|
+
|
44
|
+
test "encoding" do |c|
|
45
|
+
Encoding.default_external = "UTF-8"
|
46
|
+
|
47
|
+
c.call("SET", "foo", "שלום")
|
48
|
+
|
49
|
+
assert_equal "Shalom שלום", "Shalom " + c.call("GET", "foo")
|
50
|
+
|
51
|
+
end if defined?(Encoding)
|
52
|
+
|
53
|
+
test "errors in pipeline" do |c|
|
54
|
+
c.queue("SET", "foo", "bar")
|
55
|
+
c.queue("INCR", "foo")
|
56
|
+
c.queue("GET", "foo")
|
57
|
+
|
58
|
+
res = c.commit
|
59
|
+
|
60
|
+
assert "OK" == res[0]
|
61
|
+
assert RuntimeError === res[1]
|
62
|
+
assert "bar" == res[2]
|
63
|
+
end
|
64
|
+
|
65
|
+
test "thread safety" do |c|
|
66
|
+
c.call("SET", "foo", 1)
|
67
|
+
c.call("SET", "bar", 2)
|
68
|
+
|
69
|
+
foos, bars = nil, nil
|
70
|
+
|
71
|
+
t1 = Thread.new do
|
72
|
+
foos = Array.new(100) { c.call("GET", "foo") }
|
73
|
+
end
|
74
|
+
|
75
|
+
t2 = Thread.new do
|
76
|
+
bars = Array.new(100) { c.call("GET", "bar") }
|
77
|
+
end
|
78
|
+
|
79
|
+
t1.join
|
80
|
+
t2.join
|
81
|
+
|
82
|
+
assert_equal ["1"], foos.uniq
|
83
|
+
assert_equal ["2"], bars.uniq
|
84
|
+
end
|
85
|
+
|
86
|
+
test "blocking commands" do |c1|
|
87
|
+
c2 = Redic.new
|
88
|
+
r = nil
|
89
|
+
|
90
|
+
t1 = Thread.new do
|
91
|
+
r = c1.call("BLPOP", "foo", 5)
|
92
|
+
end
|
93
|
+
|
94
|
+
t2 = Thread.new do
|
95
|
+
c2.call("RPUSH", "foo", "value")
|
96
|
+
end
|
97
|
+
|
98
|
+
t1.join
|
99
|
+
t2.join
|
100
|
+
|
101
|
+
assert_equal ["foo", "value"], r
|
102
|
+
end
|
103
|
+
|
104
|
+
test "pub/sub" do |c1|
|
105
|
+
c2 = Redic.new
|
106
|
+
|
107
|
+
assert_equal ["subscribe", "foo", 1], c1.call("SUBSCRIBE", "foo")
|
108
|
+
|
109
|
+
c2.call("PUBLISH", "foo", "value1")
|
110
|
+
c2.call("PUBLISH", "foo", "value2")
|
111
|
+
|
112
|
+
assert_equal ["message", "foo", "value1"], c1.client.read
|
113
|
+
assert_equal ["message", "foo", "value2"], c1.client.read
|
114
|
+
|
115
|
+
c1.call("UNSUBSCRIBE", "foo")
|
116
|
+
|
117
|
+
assert_equal "PONG", c1.call("PING")
|
118
|
+
end
|
data/{test → tests}/unix_test.rb
RENAMED
@@ -11,16 +11,16 @@ test "normal commands" do |c|
|
|
11
11
|
end
|
12
12
|
|
13
13
|
test "pipelining" do |c|
|
14
|
-
c.
|
15
|
-
c.
|
14
|
+
c.queue("SET", "foo", "bar")
|
15
|
+
c.queue("GET", "foo")
|
16
16
|
|
17
|
-
assert_equal ["OK", "bar"], c.
|
17
|
+
assert_equal ["OK", "bar"], c.commit
|
18
18
|
end
|
19
19
|
|
20
20
|
test "multi/exec" do |c|
|
21
|
-
c.
|
22
|
-
c.
|
23
|
-
c.
|
21
|
+
c.queue("MULTI")
|
22
|
+
c.queue("SET", "foo", "bar")
|
23
|
+
c.queue("EXEC")
|
24
24
|
|
25
|
-
assert_equal ["OK", "QUEUED", ["OK"]], c.
|
25
|
+
assert_equal ["OK", "QUEUED", ["OK"]], c.commit
|
26
26
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michel Martens
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-04-
|
12
|
+
date: 2013-04-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: hiredis
|
@@ -42,8 +42,8 @@ files:
|
|
42
42
|
- lib/redic/connection.rb
|
43
43
|
- makefile
|
44
44
|
- redic.gemspec
|
45
|
-
-
|
46
|
-
-
|
45
|
+
- tests/redic_test.rb
|
46
|
+
- tests/unix_test.rb
|
47
47
|
homepage: https://github.com/amakawa/redic
|
48
48
|
licenses:
|
49
49
|
- MIT
|
data/test/redic_test.rb
DELETED
@@ -1,78 +0,0 @@
|
|
1
|
-
require File.expand_path("../lib/redic", File.dirname(__FILE__))
|
2
|
-
|
3
|
-
setup do
|
4
|
-
Redic.new
|
5
|
-
end
|
6
|
-
|
7
|
-
test "url" do |c|
|
8
|
-
assert_equal "redis://127.0.0.1:6379", c.url
|
9
|
-
end
|
10
|
-
|
11
|
-
test "normal commands" do |c|
|
12
|
-
c.call("SET", "foo", "bar")
|
13
|
-
|
14
|
-
assert_equal "bar", c.call("GET", "foo")
|
15
|
-
end
|
16
|
-
|
17
|
-
test "pipelining" do |c|
|
18
|
-
c.write("SET", "foo", "bar")
|
19
|
-
c.write("GET", "foo")
|
20
|
-
|
21
|
-
assert_equal ["OK", "bar"], c.run
|
22
|
-
end
|
23
|
-
|
24
|
-
test "multi/exec" do |c|
|
25
|
-
c.write("MULTI")
|
26
|
-
c.write("SET", "foo", "bar")
|
27
|
-
c.write("EXEC")
|
28
|
-
|
29
|
-
assert_equal ["OK", "QUEUED", ["OK"]], c.run
|
30
|
-
end
|
31
|
-
|
32
|
-
test "runtime errors" do |c|
|
33
|
-
res = c.call("KABLAMMO")
|
34
|
-
|
35
|
-
assert res.is_a?(RuntimeError)
|
36
|
-
end
|
37
|
-
|
38
|
-
test "encoding" do |c|
|
39
|
-
Encoding.default_external = "UTF-8"
|
40
|
-
|
41
|
-
c.call("SET", "foo", "שלום")
|
42
|
-
|
43
|
-
assert_equal "Shalom שלום", "Shalom " + c.call("GET", "foo")
|
44
|
-
|
45
|
-
end if defined?(Encoding)
|
46
|
-
|
47
|
-
test "errors in pipeline" do |c|
|
48
|
-
c.write("SET", "foo", "bar")
|
49
|
-
c.write("INCR", "foo")
|
50
|
-
c.write("GET", "foo")
|
51
|
-
|
52
|
-
res = c.run
|
53
|
-
|
54
|
-
assert "OK" == res[0]
|
55
|
-
assert RuntimeError === res[1]
|
56
|
-
assert "bar" == res[2]
|
57
|
-
end
|
58
|
-
|
59
|
-
test "thread safety" do |c|
|
60
|
-
c.call("SET", "foo", 1)
|
61
|
-
c.call("SET", "bar", 2)
|
62
|
-
|
63
|
-
foos, bars = nil, nil
|
64
|
-
|
65
|
-
t1 = Thread.new do
|
66
|
-
foos = Array.new(100) { c.call("GET", "foo") }
|
67
|
-
end
|
68
|
-
|
69
|
-
t2 = Thread.new do
|
70
|
-
bars = Array.new(100) { c.call("GET", "bar") }
|
71
|
-
end
|
72
|
-
|
73
|
-
t1.join
|
74
|
-
t2.join
|
75
|
-
|
76
|
-
assert_equal ["1"], foos.uniq
|
77
|
-
assert_equal ["2"], bars.uniq
|
78
|
-
end
|