redic-rb 1.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1e6a500c5ac8d333481dcc65b4c7f9eb9dddc322f80fdc691d73aa0d426fadee
4
+ data.tar.gz: '09da31f87e4089f3100256ad018ec6f0e687c9ed0e46c316b8e404831c3045d4'
5
+ SHA512:
6
+ metadata.gz: a080ef7608225c3587c66f4f6115af50710686218b26e2a95dff8cb67d6baba9a3f8f8566c30872a41a6d014a04afd003650f21f4ef7920c4231e4f78df07e75
7
+ data.tar.gz: 894767f8f0a73c5440ef5dffc237ce4190b92237eb485803d8de9acbb682de65ee04dccd03046abeec6b2bcb3d40e701425d9bcc697f16a0a9ce7bff7bf1404e
data/.gems ADDED
@@ -0,0 +1,2 @@
1
+ cutest -v 1.2.3
2
+ hiredis -v 0.6.3
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ /.gs
data/CHANGELOG ADDED
@@ -0,0 +1,35 @@
1
+ 1.5.1
2
+
3
+ - Allow timeout to be changed.
4
+
5
+ 1.5.0
6
+
7
+ - Raise runtime errors when using `call!`.
8
+
9
+ 1.4.1
10
+
11
+ - Reconnect only if URLs differ.
12
+
13
+ 1.4.0
14
+
15
+ - Close connections with Redic#quit.
16
+
17
+ 1.3.0
18
+
19
+ - Improve support for multithreaded environments.
20
+
21
+ 1.2.0
22
+
23
+ - Add Redic#configure.
24
+
25
+ 1.1.1
26
+
27
+ - Redic can now connect to sentinels.
28
+
29
+ 1.1.0
30
+
31
+ - Redic is now compatible with all rubies.
32
+
33
+ 1.0.0
34
+
35
+ - Add a configurable timeout.
data/CONTRIBUTING ADDED
@@ -0,0 +1,19 @@
1
+ This code tries to solve a particular problem with a very simple
2
+ implementation. We try to keep the code to a minimum while making
3
+ it as clear as possible. The design is very likely finished, and
4
+ if some feature is missing it is possible that it was left out on
5
+ purpose. That said, new usage patterns may arise, and when that
6
+ happens we are ready to adapt if necessary.
7
+
8
+ A good first step for contributing is to meet us on IRC and discuss
9
+ ideas. We spend a lot of time on #lesscode at freenode, always ready
10
+ to talk about code and simplicity. If connecting to IRC is not an
11
+ option, you can create an issue explaining the proposed change and
12
+ a use case. We pay a lot of attention to use cases, because our
13
+ goal is to keep the code base simple. Usually the result of a
14
+ conversation is the creation of a different tool.
15
+
16
+ Please don't start the conversation with a pull request. The code
17
+ should come at last, and even though it may help to convey an idea,
18
+ more often than not it draws the attention to a particular
19
+ implementation.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,59 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ redic-rb (1.6)
5
+ redis (~> 4.1)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ awesome_print (1.8.0)
11
+ byebug (11.0.0)
12
+ clap (1.0.0)
13
+ coderay (1.1.2)
14
+ coolline (0.5.0)
15
+ unicode_utils (~> 1.4)
16
+ cutest (1.2.3)
17
+ clap
18
+ hirb (0.7.3)
19
+ hirb-unicode-steakknife (0.0.8)
20
+ hirb (~> 0.5)
21
+ unicode-display_width (~> 1.1)
22
+ method_source (0.9.2)
23
+ pry (0.12.2)
24
+ coderay (~> 1.1.0)
25
+ method_source (~> 0.9.0)
26
+ pry-byebug (3.7.0)
27
+ byebug (~> 11.0)
28
+ pry (~> 0.10)
29
+ pry-coolline (0.2.5)
30
+ coolline (~> 0.5)
31
+ pry-doc (0.13.5)
32
+ pry (~> 0.11)
33
+ yard (~> 0.9.11)
34
+ pry-rails (0.3.9)
35
+ pry (>= 0.10.4)
36
+ redis (4.1.0)
37
+ spirit_hands (2.1.5)
38
+ awesome_print (~> 1.6)
39
+ hirb (~> 0.7)
40
+ hirb-unicode-steakknife (~> 0.0)
41
+ pry (~> 0.10)
42
+ pry-byebug (~> 3.4)
43
+ pry-coolline (~> 0.2)
44
+ pry-doc (~> 0.8)
45
+ pry-rails (~> 0.3)
46
+ unicode-display_width (1.5.0)
47
+ unicode_utils (1.4.0)
48
+ yard (0.9.18)
49
+
50
+ PLATFORMS
51
+ ruby
52
+
53
+ DEPENDENCIES
54
+ cutest (~> 1.2)
55
+ redic-rb!
56
+ spirit_hands (~> 2.1)
57
+
58
+ BUNDLED WITH
59
+ 1.16.1
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2013-2014 Michel Martens, Cyril David
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,142 @@
1
+ Redic
2
+ =====
3
+
4
+ Lightweight Redis Client
5
+
6
+ Description
7
+ -----------
8
+
9
+ Lightweight Redis Client inspired by [redigo][redigo], a Redis
10
+ client library for golang.
11
+
12
+ ## Usage
13
+
14
+ ```ruby
15
+ # Accepts a Redis URL and defaults to "redis://127.0.0.1:6379".
16
+ redis = Redic.new
17
+
18
+ # Processes the command and returns the response.
19
+ redis.call("SET", "foo", "bar")
20
+
21
+ assert_equal "bar", redis.call("GET", "foo")
22
+
23
+ # Pipelining is implemented by buffering commands,
24
+ # then calling Redic#commit
25
+ redis.queue("SET", "foo", "bar")
26
+ redis.queue("GET", "foo")
27
+
28
+ assert_equal ["OK", "bar"], redis.commit
29
+ ```
30
+
31
+ You can provide the password and the database to be selected. The
32
+ format for Redis URLs is `redis://user:pass@host:port/db`. As
33
+ Redis only needs a password for authentication, the user can be
34
+ omitted:
35
+
36
+ ```ruby
37
+ # Connect to localhost:6380 using "bar" as password and use the
38
+ # database 2. Both AUTH and SELECT commands are issued after
39
+ # connecting. The user part of the URL is not provided.
40
+ redis = Redic.new("redis://:bar@localhost:6380/2")
41
+ ```
42
+
43
+ It is also possible to configure a timeout for the connection. The
44
+ default timeout is 10 seconds.
45
+
46
+ ```ruby
47
+ # Timeout expressed in microseconds.
48
+ redis = Redic.new(REDIS_URL, 2_000_000)
49
+ redis.timeout == 2_000_000 #=> true
50
+ ```
51
+ A client can be re-configured, forcing the next connection to
52
+ be established with the new details:
53
+
54
+ ```ruby
55
+ redis = Redic.new("redis://localhost:6379")
56
+ redis.configure("redis://localhost:6380")
57
+ ```
58
+
59
+ Here's one final example using both a Redis URL and a timeout:
60
+
61
+ ```ruby
62
+ # It's recommended to store the REDIS_URL as an environment
63
+ # variable. Use `fetch` to retrieve values that must be present,
64
+ # as it raises an error if the value is not found.
65
+ REDIS_URL = ENV.fetch("REDIS_URL")
66
+ REDIS_TIMEOUT = ENV.fetch("REDIS_TIMEOUT")
67
+
68
+ redis = Redic.new(REDIS_URL, REDIS_TIMEOUT)
69
+ ```
70
+
71
+ Both the initializer and the `configure` method accept a `URL` and
72
+ a `timeout`.
73
+
74
+ In order to close the connection, call `quit`:
75
+
76
+ ```ruby
77
+ redis = Redic.new("redis://localhost:6379")
78
+ redis.quit
79
+ ```
80
+
81
+ With that command, `"QUIT"` is sent to Redis and the socket is closed.
82
+
83
+ ## Differences with redis-rb
84
+
85
+ Redic uses [hiredis][hiredis] for the connection and for parsing
86
+ the replies. There are no alternative connection drivers. Unlike
87
+ [redis-rb][redis-rb] it doesn't define all the Redis commands, and
88
+ instead it acts as a transport layer. The lock provided is smaller
89
+ than that of redis-rb, as it only wraps the writing and reading from
90
+ the connection. So even if both clients are thread-safe by default,
91
+ the peformance of a smaller lock is marginally better.
92
+
93
+ [redigo]: https://github.com/garyburd/redigo
94
+ [hiredis]: https://github.com/pietern/hiredis-rb
95
+ [redis-rb]: https://github.com/redis/redis-rb
96
+
97
+ ## Limitations
98
+
99
+ When a client enters a subscribed mode, further reads to retrieve the
100
+ messages are not thread safe. It is very important to take this into
101
+ account and to create a different client if you need to send different
102
+ operations while a client is subscribed to a channel.
103
+
104
+ ```ruby
105
+ # Example of pub/sub usage.
106
+ c1 = Redic.new
107
+ c2 = Redic.new
108
+
109
+ # After this command, the client is no longer thread safe.
110
+ c1.call("SUBSCRIBE", "foo")
111
+
112
+ # That's why we need to publish from a different connection.
113
+ c2.call("PUBLISH", "foo")
114
+
115
+ # Note that this operation is not thread safe.
116
+ assert_equal ["message", "foo", "value1"], c1.client.read
117
+ ```
118
+
119
+ You can wrap thread unsafe operations in a mutex:
120
+
121
+ ```ruby
122
+ redis = Redic.new
123
+
124
+ mutex = Mutex.new
125
+
126
+ mutex.synchronize do
127
+ redis.call("MONITOR")
128
+
129
+ # Display every command sent to Redis.
130
+ loop do
131
+ puts redis.client.read
132
+ end
133
+ end
134
+ ```
135
+
136
+ ## Installation
137
+
138
+ You can install it using rubygems.
139
+
140
+ ```
141
+ $ gem install redic
142
+ ```
data/bin/console ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "redic"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ require "pry"
11
+ Pry.start
12
+
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,116 @@
1
+ require_relative "connection"
2
+ require "uri"
3
+ require "redis"
4
+
5
+ class Redic
6
+ class Client
7
+ EMPTY = "".freeze
8
+ SLASH = "/".freeze
9
+
10
+ attr_accessor :timeout
11
+
12
+ def initialize(url, timeout)
13
+ @semaphore = Mutex.new
14
+ @connection = false
15
+
16
+ configure(url, timeout)
17
+ end
18
+
19
+ def configure(url, timeout)
20
+ disconnect!
21
+
22
+ @uri = URI.parse(url)
23
+ @timeout = timeout
24
+ end
25
+
26
+ def read
27
+ #@connection.read
28
+ @response
29
+ end
30
+
31
+ def write(command)
32
+ #@connection.write(command)
33
+ cmd_name = command.shift.to_s.downcase
34
+ block = command.find{ |cmd| cmd.is_a? Proc }
35
+ #binding.pry if cmd_name == "subscribe"
36
+ @response = if command.empty?
37
+ @connection.send(cmd_name)
38
+ else
39
+ @connection.send(cmd_name, *command, &block)
40
+ end
41
+ rescue => e
42
+ return raise e if e.message =~ /ERR invalid DB index/
43
+ return raise e if e.message =~ /ERR invalid password/
44
+ @response = RuntimeError.new(e.message)
45
+ end
46
+
47
+ def connect
48
+ establish_connection unless connected?
49
+
50
+ @semaphore.synchronize do
51
+ yield
52
+ end
53
+ rescue Errno::ECONNRESET
54
+ @connection = false
55
+ retry
56
+ end
57
+
58
+ def connected?
59
+ @connection && @connection.connected?
60
+ end
61
+
62
+ def disconnect!
63
+ if connected?
64
+ @connection.disconnect!
65
+ @connection = false
66
+ end
67
+ end
68
+
69
+ def quit
70
+ if connected?
71
+ assert_ok(call("QUIT"))
72
+ disconnect!
73
+
74
+ true
75
+ else
76
+ false
77
+ end
78
+ end
79
+
80
+ private
81
+ def establish_connection
82
+ begin
83
+ #Redic::Connection.new(@uri, @timeout)
84
+ @connection = Redis.new(url: @uri)
85
+ raise StandardError if @connection.ping != "PONG"
86
+ rescue StandardError => err
87
+ raise err, "Can't connect to: #{@uri} because: #{err.message}"
88
+ end
89
+
90
+ if @uri.scheme != "unix"
91
+ if @uri.password
92
+ assert_ok(call("AUTH", @uri.password))
93
+ end
94
+
95
+ if @uri.path != EMPTY && @uri.path != SLASH
96
+ assert_ok(call("SELECT", @uri.path[1..-1]))
97
+ end
98
+ end
99
+ end
100
+
101
+ def call(*args)
102
+ @semaphore.synchronize do
103
+ write(args)
104
+ read
105
+ end
106
+ end
107
+
108
+ def assert(value, error)
109
+ raise error unless value
110
+ end
111
+
112
+ def assert_ok(reply)
113
+ assert(reply == "OK", reply)
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,17 @@
1
+ #require "hiredis/connection"
2
+ #
3
+ #class Redic
4
+ # module Connection
5
+ # def self.new(uri, timeout)
6
+ # connection = Hiredis::Connection.new
7
+ #
8
+ # if uri.scheme == "unix"
9
+ # connection.connect_unix(uri.path, timeout)
10
+ # else
11
+ # connection.connect(uri.host, uri.port, timeout)
12
+ # end
13
+ #
14
+ # connection
15
+ # end
16
+ # end
17
+ #end
data/lib/redic.rb ADDED
@@ -0,0 +1,75 @@
1
+ require 'redis'
2
+ require_relative "redic/client"
3
+
4
+ class Redic
5
+ attr :url
6
+ attr :client
7
+
8
+ def initialize(url = "redis://127.0.0.1:6379", timeout = 10_000_000)
9
+ @url = url
10
+ @client = Redic::Client.new(url, timeout)
11
+ @buffer = Hash.new { |h, k| h[k] = [] }
12
+ end
13
+
14
+ def buffer
15
+ @buffer[Thread.current.object_id]
16
+ end
17
+
18
+ def reset
19
+ @buffer.delete(Thread.current.object_id)
20
+ end
21
+
22
+ def clear
23
+ @buffer.clear
24
+ end
25
+
26
+ def configure(url, timeout = 10_000_000)
27
+ if @url != url
28
+ @url = url
29
+ @client.configure(url, timeout)
30
+ end
31
+ end
32
+
33
+ def call(*args)
34
+ @client.connect do
35
+ @client.write(args)
36
+ @client.read
37
+ end
38
+ end
39
+
40
+ def call!(*args)
41
+ reply = call(*args)
42
+
43
+ if RuntimeError === reply
44
+ raise reply
45
+ end
46
+
47
+ return reply
48
+ end
49
+
50
+ def queue(*args)
51
+ buffer << args
52
+ end
53
+
54
+ def commit
55
+ @client.connect do
56
+ buffer.map do |args|
57
+ @client.write(args)
58
+ end
59
+ end
60
+ ensure
61
+ reset
62
+ end
63
+
64
+ def timeout
65
+ @client.timeout
66
+ end
67
+
68
+ def timeout=(timeout)
69
+ @client.timeout = timeout
70
+ end
71
+
72
+ def quit
73
+ @client.quit
74
+ end
75
+ end
data/makefile ADDED
@@ -0,0 +1,2 @@
1
+ test:
2
+ RUBYLIB=./lib cutest tests/*.rb
data/redic-rb.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "redic-rb"
5
+ s.version = "1.6"
6
+ s.summary = "Lightweight Redis Client"
7
+ s.description = "Lightweight Redis Client"
8
+ s.authors = ["Michel Martens", "Cyril David", "Diego Gomez"]
9
+ s.email = ["michel@soveran.com", "cyx@cyx.is", "diego.f.gomez.pardo@gmail.com"]
10
+ s.homepage = "https://github.com/degz/redic-rb"
11
+ s.files = `git ls-files`.split("\n")
12
+ s.license = "MIT"
13
+
14
+ s.add_dependency "redis", "~> 4.1"
15
+
16
+ s.add_development_dependency "spirit_hands", "~> 2.1"
17
+ s.add_development_dependency "cutest", "~> 1.2"
18
+
19
+ end
@@ -0,0 +1,54 @@
1
+ require "cutest"
2
+ require_relative "../lib/redic"
3
+
4
+ REDIS_URL = "redis://localhost:6379/"
5
+
6
+ prepare do
7
+ c = Redic.new(REDIS_URL)
8
+
9
+ begin
10
+ c.call("FLUSHDB")
11
+ rescue
12
+ c.call("AUTH", "foo")
13
+ c.call("FLUSHDB")
14
+ c.call("CONFIG", "SET", "requirepass", "")
15
+ end
16
+ end
17
+
18
+ test "multiple threads" do
19
+
20
+ cs = Array.new
21
+
22
+ c = Redic.new(REDIS_URL)
23
+
24
+ c.queue("SET", "foo", "1")
25
+
26
+ t1 = Thread.new do
27
+ c.queue("SET", "bar", "2")
28
+ end
29
+
30
+ t2 = Thread.new do
31
+ c.queue("SET", "baz", "3")
32
+ c.commit
33
+ end
34
+
35
+ t1.join
36
+ t2.join
37
+
38
+ assert_equal nil, c.call("GET", "foo")
39
+ assert_equal nil, c.call("GET", "bar")
40
+ assert_equal "3", c.call("GET", "baz")
41
+
42
+ c.commit
43
+
44
+ # The buffer for `c` still exists
45
+ assert_equal "1", c.call("GET", "foo")
46
+
47
+ # Buffer for the thread that didn't commit is the only one left
48
+ assert_equal 1, c.instance_variable_get("@buffer").keys.size
49
+
50
+ c.clear
51
+
52
+ # All buffers are cleared
53
+ assert_equal 0, c.instance_variable_get("@buffer").keys.size
54
+ end
@@ -0,0 +1,232 @@
1
+ require "cutest"
2
+ require_relative "../lib/redic"
3
+ require 'pry'
4
+
5
+ REDIS_URL = "redis://localhost:6379/0"
6
+
7
+ prepare do
8
+ c = Redic.new(REDIS_URL)
9
+
10
+ begin
11
+ c.call!("FLUSHDB").inspect
12
+ rescue
13
+ c.call!("AUTH", "foo")
14
+ c.call!("SELECT", "0")
15
+ c.call!("FLUSHDB")
16
+ c.call!("CONFIG", "SET", "requirepass", "")
17
+ end
18
+ end
19
+
20
+ setup do
21
+ Redic.new(REDIS_URL)
22
+ end
23
+
24
+ test "url" do |c|
25
+ assert_equal "redis://localhost:6379/0", c.url
26
+ end
27
+
28
+ test "select db from url" do |c1|
29
+
30
+ # Connect to db 1
31
+ c2 = Redic.new("redis://localhost:6379/2")
32
+
33
+ c2.call("FLUSHDB")
34
+
35
+ # Set a value in db 0
36
+ c1.call("SET", "foo", "bar")
37
+
38
+ assert_equal(1, c1.call("DBSIZE"))
39
+ assert_equal(0, c2.call("DBSIZE"))
40
+ end
41
+
42
+ test "error when selecting db from url" do
43
+ c2 = Redic.new("redis://localhost:6379/foo")
44
+
45
+ assert_raise(RuntimeError) do
46
+
47
+ # Connection is lazy, send a command
48
+ c2.call("PING")
49
+ end
50
+ end
51
+
52
+ test "error when authenticating from url" do |c1|
53
+
54
+ # Configure password as "foo"
55
+ c1.call("CONFIG", "SET", "requirepass", "foo")
56
+
57
+ # The password provided is wrong
58
+ c2 = Redic.new("redis://:bar@localhost:6379/")
59
+
60
+ assert_raise(RuntimeError) do
61
+
62
+ # Connection is lazy, send a command
63
+ c2.call("PING")
64
+ end
65
+
66
+ c3 = Redic.new("redis://:foo@localhost:6379/")
67
+ assert_equal "PONG", c3.call("PING")
68
+
69
+ # Remove password
70
+ c3.call("CONFIG", "SET", "requirepass", "")
71
+ end
72
+
73
+ #test "Can connect to sentinel" do
74
+ # c2 = Redic.new "redis://localhost:26379"
75
+ # c2.call "SENTINEL", "masters"
76
+ #end
77
+
78
+ test "timeout" do |c1|
79
+
80
+ # Default timeout is 10 seconds
81
+ assert_equal 10_000_000, c1.timeout
82
+
83
+ # Timeout configured to 200_000 microseconds
84
+ c2 = Redic.new(REDIS_URL, 200_000)
85
+
86
+ assert_equal 200_000, c2.timeout
87
+
88
+ # Change timeout to 5 seconds
89
+ c2.timeout = 5_000_000
90
+
91
+ assert_equal 5_000_000, c2.timeout
92
+ end
93
+
94
+ test "normal commands" do |c|
95
+ c.call("SET", "foo", "bar")
96
+
97
+ assert_equal "bar", c.call("GET", "foo")
98
+ end
99
+
100
+ test "pipelining" do |c|
101
+ c.queue("SET", "foo", "perro")
102
+ c.queue("GET", "foo")
103
+
104
+ assert_equal ["OK", "perro"], c.commit
105
+ end
106
+
107
+ test "multi/exec" do |c|
108
+ c.queue("MULTI")
109
+ c.queue("SET", "foo", "bar")
110
+ c.queue("EXEC")
111
+
112
+ assert_equal ["OK", "QUEUED", ["OK"]], c.commit
113
+ end
114
+
115
+ test "runtime errors" do |c|
116
+ res = c.call("KABLAMMO")
117
+
118
+ assert res.is_a?(RuntimeError)
119
+ end
120
+
121
+ test "encoding" do |c|
122
+ Encoding.default_external = "UTF-8"
123
+
124
+ c.call("SET", "foo", "שלום")
125
+
126
+ assert_equal "Shalom שלום", "Shalom " + c.call("GET", "foo")
127
+
128
+ end if defined?(Encoding)
129
+
130
+ test "errors in pipeline" do |c|
131
+ c.queue("SET", "foo", "bar")
132
+ c.queue("INCR", "foo")
133
+ c.queue("GET", "foo")
134
+
135
+ res = c.commit
136
+
137
+ assert "OK" == res[0]
138
+ assert RuntimeError === res[1]
139
+ assert "bar" == res[2]
140
+ end
141
+
142
+ test "thread safety" do |c|
143
+ c.call("SET", "foo", 1)
144
+ c.call("SET", "bar", 2)
145
+
146
+ foos, bars = nil, nil
147
+
148
+ t1 = Thread.new do
149
+ foos = Array.new(100) { c.call("GET", "foo") }
150
+ end
151
+
152
+ t2 = Thread.new do
153
+ bars = Array.new(100) { c.call("GET", "bar") }
154
+ end
155
+
156
+ t1.join
157
+ t2.join
158
+
159
+ assert_equal ["1"], foos.uniq
160
+ assert_equal ["2"], bars.uniq
161
+ end
162
+
163
+ test "blocking commands" do |c1|
164
+ c2 = Redic.new
165
+ r = nil
166
+
167
+ t1 = Thread.new do
168
+ r = c1.call("BLPOP", "foo", 5)
169
+ end
170
+
171
+ t2 = Thread.new do
172
+ c2.call("RPUSH", "foo", "value")
173
+ end
174
+
175
+ t1.join
176
+ t2.join
177
+
178
+ assert_equal ["foo", "value"], r
179
+ end
180
+
181
+ #test "pub/sub" do |c1|
182
+ # c2 = Redic.new
183
+ #
184
+ # binding.pry
185
+ # res = c1.call("SUBSCRIBE", "foo", Proc.new{})
186
+ # assert_equal ["subscribe", "foo", 1], res
187
+ #
188
+ # c2.call("PUBLISH", "foo", "value1")
189
+ # c2.call("PUBLISH", "foo", "value2")
190
+ #
191
+ # assert_equal ["message", "foo", "value1"], c1.client.read
192
+ # assert_equal ["message", "foo", "value2"], c1.client.read
193
+ #
194
+ # c1.call("UNSUBSCRIBE", "foo")
195
+ #
196
+ # assert_equal "PONG", c1.call("PING")
197
+ #end
198
+
199
+ test "reconnect" do |c1|
200
+ url = "redis://:foo@localhost:6379/"
201
+
202
+ assert url != c1.url
203
+
204
+ c1.call("CONFIG", "SET", "requirepass", "foo")
205
+
206
+ c1.configure(url)
207
+
208
+ assert url == c1.url
209
+ assert url.object_id == c1.url.object_id
210
+
211
+ # Reconfigure only if URLs differ
212
+ c1.configure(url.dup)
213
+
214
+ # No reconnection ocurred
215
+ assert url.object_id == c1.url.object_id
216
+
217
+ assert_equal "PONG", c1.call("PING")
218
+ end
219
+
220
+ test "disconnect" do |c1|
221
+
222
+ # Connection is lazy
223
+ assert_equal false, c1.client.connected?
224
+ assert_equal false, c1.quit
225
+
226
+ c1.call("PING")
227
+
228
+ assert_equal true, c1.client.connected?
229
+ assert_equal true, c1.quit
230
+
231
+ assert_equal false, c1.client.connected?
232
+ end
@@ -0,0 +1,27 @@
1
+ require "cutest"
2
+ require_relative "../lib/redic"
3
+
4
+ setup do
5
+ Redic.new("unix:///tmp/redis.6379.sock")
6
+ end
7
+
8
+ test "normal commands" do |c|
9
+ c.call("SET", "foo", "bar")
10
+
11
+ assert_equal "bar", c.call("GET", "foo")
12
+ end
13
+
14
+ test "pipelining" do |c|
15
+ c.queue("SET", "foo", "bar")
16
+ c.queue("GET", "foo")
17
+
18
+ assert_equal ["OK", "bar"], c.commit
19
+ end
20
+
21
+ test "multi/exec" do |c|
22
+ c.queue("MULTI")
23
+ c.queue("SET", "foo", "bar")
24
+ c.queue("EXEC")
25
+
26
+ assert_equal ["OK", "QUEUED", ["OK"]], c.commit
27
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: redic-rb
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.6'
5
+ platform: ruby
6
+ authors:
7
+ - Michel Martens
8
+ - Cyril David
9
+ - Diego Gomez
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2019-03-11 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: redis
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - "~>"
20
+ - !ruby/object:Gem::Version
21
+ version: '4.1'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - "~>"
27
+ - !ruby/object:Gem::Version
28
+ version: '4.1'
29
+ - !ruby/object:Gem::Dependency
30
+ name: spirit_hands
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - "~>"
34
+ - !ruby/object:Gem::Version
35
+ version: '2.1'
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - "~>"
41
+ - !ruby/object:Gem::Version
42
+ version: '2.1'
43
+ - !ruby/object:Gem::Dependency
44
+ name: cutest
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '1.2'
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - "~>"
55
+ - !ruby/object:Gem::Version
56
+ version: '1.2'
57
+ description: Lightweight Redis Client
58
+ email:
59
+ - michel@soveran.com
60
+ - cyx@cyx.is
61
+ - diego.f.gomez.pardo@gmail.com
62
+ executables: []
63
+ extensions: []
64
+ extra_rdoc_files: []
65
+ files:
66
+ - ".gems"
67
+ - ".gitignore"
68
+ - CHANGELOG
69
+ - CONTRIBUTING
70
+ - Gemfile
71
+ - Gemfile.lock
72
+ - LICENSE
73
+ - README.md
74
+ - bin/console
75
+ - bin/setup
76
+ - lib/redic.rb
77
+ - lib/redic/client.rb
78
+ - lib/redic/connection.rb
79
+ - makefile
80
+ - redic-rb.gemspec
81
+ - tests/multithreaded_test.rb
82
+ - tests/redic_test.rb
83
+ - tests/unix_test.rb
84
+ homepage: https://github.com/degz/redic-rb
85
+ licenses:
86
+ - MIT
87
+ metadata: {}
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 2.7.3
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: Lightweight Redis Client
108
+ test_files: []