redis 2.2.2 → 3.0.0.rc1
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.
- data/.gitignore +2 -0
- data/.yardopts +3 -0
- data/CHANGELOG.md +65 -1
- data/README.md +6 -0
- data/Rakefile +19 -27
- data/lib/redis.rb +737 -170
- data/lib/redis/client.rb +82 -67
- data/lib/redis/connection/command_helper.rb +15 -16
- data/lib/redis/connection/hiredis.rb +6 -3
- data/lib/redis/connection/ruby.rb +2 -1
- data/lib/redis/connection/synchrony.rb +3 -1
- data/lib/redis/distributed.rb +20 -18
- data/lib/redis/errors.rb +38 -0
- data/lib/redis/hash_ring.rb +2 -2
- data/lib/redis/pipeline.rb +91 -19
- data/lib/redis/subscribe.rb +1 -16
- data/lib/redis/version.rb +1 -1
- data/redis.gemspec +30 -11
- data/test/command_map_test.rb +29 -0
- data/test/commands_on_hashes_test.rb +3 -3
- data/test/commands_on_lists_test.rb +1 -1
- data/test/commands_on_sets_test.rb +0 -2
- data/test/commands_on_sorted_sets_test.rb +8 -9
- data/test/commands_on_strings_test.rb +3 -3
- data/test/commands_on_value_types_test.rb +0 -1
- data/test/connection_handling_test.rb +120 -4
- data/test/distributed_commands_on_hashes_test.rb +0 -1
- data/test/distributed_commands_on_lists_test.rb +0 -1
- data/test/distributed_commands_on_sets_test.rb +0 -1
- data/test/distributed_commands_on_sorted_sets_test.rb +19 -0
- data/test/distributed_commands_on_strings_test.rb +0 -1
- data/test/distributed_commands_on_value_types_test.rb +0 -1
- data/test/distributed_connection_handling_test.rb +0 -1
- data/test/distributed_key_tags_test.rb +0 -1
- data/test/distributed_persistence_control_commands_test.rb +0 -1
- data/test/distributed_publish_subscribe_test.rb +1 -2
- data/test/distributed_remote_server_control_commands_test.rb +2 -3
- data/test/distributed_transactions_test.rb +0 -1
- data/test/encoding_test.rb +0 -1
- data/test/helper.rb +14 -4
- data/test/helper_test.rb +8 -0
- data/test/internals_test.rb +25 -33
- data/test/lint/hashes.rb +17 -3
- data/test/lint/internals.rb +2 -3
- data/test/lint/lists.rb +17 -3
- data/test/lint/sets.rb +30 -6
- data/test/lint/sorted_sets.rb +56 -27
- data/test/lint/strings.rb +9 -13
- data/test/lint/value_types.rb +12 -15
- data/test/persistence_control_commands_test.rb +0 -1
- data/test/pipelining_commands_test.rb +69 -6
- data/test/publish_subscribe_test.rb +1 -1
- data/test/redis_mock.rb +14 -5
- data/test/remote_server_control_commands_test.rb +8 -2
- data/test/sorting_test.rb +0 -1
- data/test/test.conf +1 -0
- data/test/transactions_test.rb +88 -15
- data/test/unknown_commands_test.rb +1 -2
- data/test/url_param_test.rb +0 -1
- metadata +68 -16
- data/lib/redis/compat.rb +0 -21
data/.gitignore
CHANGED
data/.yardopts
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,68 @@
|
|
1
|
-
#
|
1
|
+
# 3.0 (unreleased)
|
2
|
+
|
3
|
+
* The `ZRANGE`, `ZREVRANGE`, `ZRANGEBYSCORE` and `ZREVRANGEBYSCORE` commands
|
4
|
+
now return an array containing `[String, Float]` pairs when
|
5
|
+
`:with_scores => true` is passed.
|
6
|
+
|
7
|
+
* The `ZINCRBY` and `ZSCORE` commands now return a `Float` score instead
|
8
|
+
of a string holding a representation of the score.
|
9
|
+
|
10
|
+
* The client now raises custom exceptions where it makes sense.
|
11
|
+
|
12
|
+
If by any chance you were rescuing low-level exceptions (`Errno::*`),
|
13
|
+
you should now rescue as follows:
|
14
|
+
|
15
|
+
Errno::ECONNRESET -> Redis::ConnectionError
|
16
|
+
Errno::EPIPE -> Redis::ConnectionError
|
17
|
+
Errno::ECONNABORTED -> Redis::ConnectionError
|
18
|
+
Errno::EBADF -> Redis::ConnectionError
|
19
|
+
Errno::EINVAL -> Redis::ConnectionError
|
20
|
+
Errno::EAGAIN -> Redis::TimeoutError
|
21
|
+
Errno::ECONNREFUSED -> Redis::CannotConnectError
|
22
|
+
|
23
|
+
* Always raise exceptions originating from erroneous command invocation
|
24
|
+
inside pipelines and MULTI/EXEC blocks.
|
25
|
+
|
26
|
+
The old behavior (swallowing exceptions) could cause application bugs
|
27
|
+
to go unnoticed.
|
28
|
+
|
29
|
+
* Implement futures for assigning values inside pipelines and MULTI/EXEC
|
30
|
+
blocks. Futures are assigned their value after the pipeline or
|
31
|
+
MULTI/EXEC block has executed.
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
$redis.pipelined do
|
35
|
+
@future = $redis.get "key"
|
36
|
+
end
|
37
|
+
|
38
|
+
puts @future.value
|
39
|
+
```
|
40
|
+
|
41
|
+
* Ruby 1.8.6 is officially not supported.
|
42
|
+
|
43
|
+
* Support `ZCOUNT` in `Redis::Distributed` (Michael Dungan).
|
44
|
+
|
45
|
+
* Pipelined commands now return the same replies as when called outside
|
46
|
+
a pipeline.
|
47
|
+
|
48
|
+
In the past, pipelined replies were returned without post-processing.
|
49
|
+
|
50
|
+
* Support `SLOWLOG` command (Michael Bernstein).
|
51
|
+
|
52
|
+
* Calling `SHUTDOWN` effectively disconnects the client (Stefan Kaes).
|
53
|
+
|
54
|
+
* Basic support for mapping commands so that they can be renamed on the
|
55
|
+
server.
|
56
|
+
|
57
|
+
* Connecting using a URL now checks that a host is given.
|
58
|
+
|
59
|
+
It's just a small sanity check, cf. #126
|
60
|
+
|
61
|
+
* Support variadic commands introduced in Redis 2.4.
|
62
|
+
|
63
|
+
# 2.2.2
|
64
|
+
|
65
|
+
* Added method `Redis::Distributed#hsetnx`.
|
2
66
|
|
3
67
|
# 2.2.1
|
4
68
|
|
data/README.md
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
A Ruby client library for the [Redis](http://redis.io) key-value store.
|
4
4
|
|
5
|
+
A simple Ruby client trying to match Redis' API one-to-one while still providing a Rubystic interface.
|
6
|
+
It features thread safety, client-side sharding, and an obsession for performance.
|
7
|
+
|
5
8
|
## A note about versions
|
6
9
|
|
7
10
|
Versions *1.0.x* target all versions of Redis. You have to use this one if you are using Redis < 1.2.
|
@@ -100,6 +103,9 @@ All users and admins:
|
|
100
103
|
|
101
104
|
Redis only stores strings as values. If you want to store an object inside a key, you can use a serialization/deseralization mechanism like JSON:
|
102
105
|
|
106
|
+
>> require 'json'
|
107
|
+
=> true
|
108
|
+
|
103
109
|
>> redis.set "foo", [1, 2, 3].to_json
|
104
110
|
=> OK
|
105
111
|
|
data/Rakefile
CHANGED
@@ -35,11 +35,6 @@ task :stop do
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
def isolated(&block)
|
39
|
-
pid = fork { yield }
|
40
|
-
Process.wait(pid)
|
41
|
-
end
|
42
|
-
|
43
38
|
desc "Run the test suite"
|
44
39
|
task :test => ["test:ruby", "test:hiredis", "test:synchrony"]
|
45
40
|
|
@@ -48,26 +43,23 @@ namespace :test do
|
|
48
43
|
task :ruby do
|
49
44
|
require "cutest"
|
50
45
|
|
51
|
-
|
52
|
-
Cutest.run(Dir["./test/**/*_test.rb"])
|
53
|
-
end
|
46
|
+
Cutest.run(Dir["./test/**/*_test.rb"])
|
54
47
|
end
|
55
48
|
|
56
49
|
desc "Run tests against the hiredis driver"
|
57
50
|
task :hiredis do
|
58
51
|
require "cutest"
|
59
52
|
|
60
|
-
|
61
|
-
|
62
|
-
require "redis/connection/hiredis"
|
53
|
+
begin
|
54
|
+
require "redis/connection/hiredis"
|
63
55
|
|
64
|
-
|
65
|
-
|
56
|
+
puts
|
57
|
+
puts "Running tests against hiredis v#{Hiredis::VERSION}"
|
66
58
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
59
|
+
ENV["REDIS_CONNECTION_DRIVER"] = "hiredis"
|
60
|
+
Cutest.run(Dir["./test/**/*_test.rb"])
|
61
|
+
rescue LoadError
|
62
|
+
puts "Skipping tests against hiredis"
|
71
63
|
end
|
72
64
|
end
|
73
65
|
|
@@ -78,18 +70,18 @@ namespace :test do
|
|
78
70
|
# Synchrony needs 1.9
|
79
71
|
next if RUBY_VERSION < "1.9"
|
80
72
|
|
81
|
-
|
82
|
-
|
83
|
-
require "redis/connection/synchrony"
|
73
|
+
begin
|
74
|
+
require "redis/connection/synchrony"
|
84
75
|
|
85
|
-
|
86
|
-
|
76
|
+
puts
|
77
|
+
puts "Running tests against em-synchrony"
|
87
78
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
79
|
+
threaded_tests = ['./test/thread_safety_test.rb']
|
80
|
+
|
81
|
+
ENV["REDIS_CONNECTION_DRIVER"] = "synchrony"
|
82
|
+
Cutest.run(Dir['./test/**/*_test.rb'] - threaded_tests)
|
83
|
+
rescue LoadError
|
84
|
+
puts "Skipping tests against em-synchrony"
|
93
85
|
end
|
94
86
|
end
|
95
87
|
end
|
data/lib/redis.rb
CHANGED
@@ -1,23 +1,7 @@
|
|
1
1
|
require "monitor"
|
2
|
+
require "redis/errors"
|
2
3
|
|
3
4
|
class Redis
|
4
|
-
class ProtocolError < RuntimeError
|
5
|
-
def initialize(reply_type)
|
6
|
-
super(<<-EOS.gsub(/(?:^|\n)\s*/, " "))
|
7
|
-
Got '#{reply_type}' as initial reply byte.
|
8
|
-
If you're running in a multi-threaded environment, make sure you
|
9
|
-
pass the :thread_safe option when initializing the connection.
|
10
|
-
If you're in a forking environment, such as Unicorn, you need to
|
11
|
-
connect to Redis after forking.
|
12
|
-
EOS
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
module DisableThreadSafety
|
17
|
-
def synchronize
|
18
|
-
yield
|
19
|
-
end
|
20
|
-
end
|
21
5
|
|
22
6
|
def self.deprecate(message, trace = caller[0])
|
23
7
|
$stderr.puts "\n#{message} (in #{trace})"
|
@@ -28,14 +12,20 @@ class Redis
|
|
28
12
|
def self.connect(options = {})
|
29
13
|
options = options.dup
|
30
14
|
|
31
|
-
|
15
|
+
url = options.delete(:url) || ENV["REDIS_URL"]
|
16
|
+
if url
|
17
|
+
require "uri"
|
18
|
+
|
19
|
+
uri = URI(url)
|
32
20
|
|
33
|
-
|
21
|
+
# Require the URL to have at least a host
|
22
|
+
raise ArgumentError, "invalid url" unless uri.host
|
34
23
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
24
|
+
options[:host] ||= uri.host
|
25
|
+
options[:port] ||= uri.port
|
26
|
+
options[:password] ||= uri.password
|
27
|
+
options[:db] ||= uri.path[1..-1].to_i
|
28
|
+
end
|
39
29
|
|
40
30
|
new(options)
|
41
31
|
end
|
@@ -54,14 +44,17 @@ class Redis
|
|
54
44
|
@client = Client.new(options)
|
55
45
|
|
56
46
|
if options[:thread_safe] == false
|
57
|
-
|
58
|
-
extend DisableThreadSafety
|
47
|
+
@synchronizer = lambda { |&block| block.call }
|
59
48
|
else
|
60
|
-
|
61
|
-
super()
|
49
|
+
@synchronizer = lambda { |&block| mon_synchronize { block.call } }
|
50
|
+
super() # Monitor#initialize
|
62
51
|
end
|
63
52
|
end
|
64
53
|
|
54
|
+
def synchronize
|
55
|
+
@synchronizer.call { yield }
|
56
|
+
end
|
57
|
+
|
65
58
|
# Run code without the client reconnecting
|
66
59
|
def without_reconnect(&block)
|
67
60
|
synchronize do
|
@@ -70,6 +63,10 @@ class Redis
|
|
70
63
|
end
|
71
64
|
|
72
65
|
# Authenticate to the server.
|
66
|
+
#
|
67
|
+
# @param [String] password must match the password specified in the
|
68
|
+
# `requirepass` directive in the configuration file
|
69
|
+
# @return [String] `OK`
|
73
70
|
def auth(password)
|
74
71
|
synchronize do
|
75
72
|
@client.call [:auth, password]
|
@@ -77,6 +74,9 @@ class Redis
|
|
77
74
|
end
|
78
75
|
|
79
76
|
# Change the selected database for the current connection.
|
77
|
+
#
|
78
|
+
# @param [Fixnum] db zero-based index of the DB to use (0 to 15)
|
79
|
+
# @return [String] `OK`
|
80
80
|
def select(db)
|
81
81
|
synchronize do
|
82
82
|
@client.db = db
|
@@ -85,38 +85,48 @@ class Redis
|
|
85
85
|
end
|
86
86
|
|
87
87
|
# Get information and statistics about the server.
|
88
|
+
#
|
89
|
+
# @param [String, Symbol] cmd e.g. "commandstats"
|
90
|
+
# @return [Hash<String, String>]
|
88
91
|
def info(cmd = nil)
|
89
92
|
synchronize do
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
reply = Hash[*reply.split(/:|\r\n/).grep(/^[^#]/)]
|
93
|
+
@client.call [:info, cmd].compact do |reply|
|
94
|
+
if reply.kind_of?(String)
|
95
|
+
reply = Hash[*reply.split(/:|\r\n/).grep(/^[^#]/)]
|
94
96
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
97
|
+
if cmd && cmd.to_s == "commandstats"
|
98
|
+
# Extract nested hashes for INFO COMMANDSTATS
|
99
|
+
reply = Hash[reply.map do |k, v|
|
100
|
+
[k[/^cmdstat_(.*)$/, 1], Hash[*v.split(/,|=/)]]
|
101
|
+
end]
|
102
|
+
end
|
100
103
|
end
|
101
|
-
end
|
102
104
|
|
103
|
-
|
105
|
+
reply
|
106
|
+
end
|
104
107
|
end
|
105
108
|
end
|
106
109
|
|
110
|
+
# Get or set server configuration parameters.
|
111
|
+
#
|
112
|
+
# @param [String] action e.g. `get`, `set`, `resetstat`
|
113
|
+
# @return [String, Hash] string reply, or hash when retrieving more than one
|
114
|
+
# property with `CONFIG GET`
|
107
115
|
def config(action, *args)
|
108
116
|
synchronize do
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
117
|
+
@client.call [:config, action, *args] do |reply|
|
118
|
+
if reply.kind_of?(Array) && action == :get
|
119
|
+
Hash[*reply]
|
120
|
+
else
|
121
|
+
reply
|
122
|
+
end
|
115
123
|
end
|
116
124
|
end
|
117
125
|
end
|
118
126
|
|
119
127
|
# Remove all keys from the current database.
|
128
|
+
#
|
129
|
+
# @return [String] `OK`
|
120
130
|
def flushdb
|
121
131
|
synchronize do
|
122
132
|
@client.call [:flushdb]
|
@@ -124,6 +134,8 @@ class Redis
|
|
124
134
|
end
|
125
135
|
|
126
136
|
# Remove all keys from all databases.
|
137
|
+
#
|
138
|
+
# @return [String] `OK`
|
127
139
|
def flushall
|
128
140
|
synchronize do
|
129
141
|
@client.call [:flushall]
|
@@ -131,6 +143,8 @@ class Redis
|
|
131
143
|
end
|
132
144
|
|
133
145
|
# Synchronously save the dataset to disk.
|
146
|
+
#
|
147
|
+
# @return [String]
|
134
148
|
def save
|
135
149
|
synchronize do
|
136
150
|
@client.call [:save]
|
@@ -138,6 +152,8 @@ class Redis
|
|
138
152
|
end
|
139
153
|
|
140
154
|
# Asynchronously save the dataset to disk.
|
155
|
+
#
|
156
|
+
# @return [String] `OK`
|
141
157
|
def bgsave
|
142
158
|
synchronize do
|
143
159
|
@client.call [:bgsave]
|
@@ -145,6 +161,8 @@ class Redis
|
|
145
161
|
end
|
146
162
|
|
147
163
|
# Asynchronously rewrite the append-only file.
|
164
|
+
#
|
165
|
+
# @return [String] `OK`
|
148
166
|
def bgrewriteaof
|
149
167
|
synchronize do
|
150
168
|
@client.call [:bgrewriteaof]
|
@@ -152,13 +170,22 @@ class Redis
|
|
152
170
|
end
|
153
171
|
|
154
172
|
# Get the value of a key.
|
173
|
+
#
|
174
|
+
# @param [String] key
|
175
|
+
# @return [String]
|
155
176
|
def get(key)
|
156
177
|
synchronize do
|
157
178
|
@client.call [:get, key]
|
158
179
|
end
|
159
180
|
end
|
160
181
|
|
182
|
+
alias :[] :get
|
183
|
+
|
161
184
|
# Returns the bit value at offset in the string value stored at key.
|
185
|
+
#
|
186
|
+
# @param [String] key
|
187
|
+
# @param [Fixnum] offset bit offset
|
188
|
+
# @return [Fixnum] `0` or `1`
|
162
189
|
def getbit(key, offset)
|
163
190
|
synchronize do
|
164
191
|
@client.call [:getbit, key, offset]
|
@@ -166,6 +193,12 @@ class Redis
|
|
166
193
|
end
|
167
194
|
|
168
195
|
# Get a substring of the string stored at a key.
|
196
|
+
#
|
197
|
+
# @param [String] key
|
198
|
+
# @param [Fixnum] start zero-based start offset
|
199
|
+
# @param [Fixnum] stop zero-based end offset. Use -1 for representing
|
200
|
+
# the end of the string
|
201
|
+
# @return [Fixnum] `0` or `1`
|
169
202
|
def getrange(key, start, stop)
|
170
203
|
synchronize do
|
171
204
|
@client.call [:getrange, key, start, stop]
|
@@ -173,6 +206,11 @@ class Redis
|
|
173
206
|
end
|
174
207
|
|
175
208
|
# Set the string value of a key and return its old value.
|
209
|
+
#
|
210
|
+
# @param [String] key
|
211
|
+
# @param [String] value value to replace the current value with
|
212
|
+
# @return [String] the old value stored in the key, or `nil` if the key
|
213
|
+
# did not exist
|
176
214
|
def getset(key, value)
|
177
215
|
synchronize do
|
178
216
|
@client.call [:getset, key, value]
|
@@ -180,26 +218,31 @@ class Redis
|
|
180
218
|
end
|
181
219
|
|
182
220
|
# Get the values of all the given keys.
|
183
|
-
|
221
|
+
#
|
222
|
+
# @param [Array<String>] keys
|
223
|
+
# @return [Array<String>]
|
224
|
+
def mget(*keys, &blk)
|
184
225
|
synchronize do
|
185
|
-
@client.call [:mget, *keys]
|
226
|
+
@client.call [:mget, *keys], &blk
|
186
227
|
end
|
187
228
|
end
|
188
229
|
|
189
230
|
# Append a value to a key.
|
231
|
+
#
|
232
|
+
# @param [String] key
|
233
|
+
# @param [String] value value to append
|
234
|
+
# @return [Fixnum] length of the string after appending
|
190
235
|
def append(key, value)
|
191
236
|
synchronize do
|
192
237
|
@client.call [:append, key, value]
|
193
238
|
end
|
194
239
|
end
|
195
240
|
|
196
|
-
def substr(key, start, stop)
|
197
|
-
synchronize do
|
198
|
-
@client.call [:substr, key, start, stop]
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
241
|
# Get the length of the value stored in a key.
|
242
|
+
#
|
243
|
+
# @param [String] key
|
244
|
+
# @return [Fixnum] the length of the value stored in the key, or 0
|
245
|
+
# if the key does not exist
|
203
246
|
def strlen(key)
|
204
247
|
synchronize do
|
205
248
|
@client.call [:strlen, key]
|
@@ -207,26 +250,41 @@ class Redis
|
|
207
250
|
end
|
208
251
|
|
209
252
|
# Get all the fields and values in a hash.
|
253
|
+
#
|
254
|
+
# @param [String] key
|
255
|
+
# @return [Hash<String, String>]
|
210
256
|
def hgetall(key)
|
211
257
|
synchronize do
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
258
|
+
@client.call [:hgetall, key] do |reply|
|
259
|
+
if reply.kind_of?(Array)
|
260
|
+
hash = Hash.new
|
261
|
+
reply.each_slice(2) do |field, value|
|
262
|
+
hash[field] = value
|
263
|
+
end
|
264
|
+
hash
|
265
|
+
else
|
266
|
+
reply
|
267
|
+
end
|
218
268
|
end
|
219
269
|
end
|
220
270
|
end
|
221
271
|
|
222
272
|
# Get the value of a hash field.
|
273
|
+
#
|
274
|
+
# @param [String] key
|
275
|
+
# @param [String] field
|
276
|
+
# @return [String]
|
223
277
|
def hget(key, field)
|
224
278
|
synchronize do
|
225
279
|
@client.call [:hget, key, field]
|
226
280
|
end
|
227
281
|
end
|
228
282
|
|
229
|
-
# Delete
|
283
|
+
# Delete one or more hash fields.
|
284
|
+
#
|
285
|
+
# @param [String] key
|
286
|
+
# @param [String, Array<String>] field
|
287
|
+
# @return [Fixnum] the number of fields that were removed from the hash
|
230
288
|
def hdel(key, field)
|
231
289
|
synchronize do
|
232
290
|
@client.call [:hdel, key, field]
|
@@ -234,6 +292,9 @@ class Redis
|
|
234
292
|
end
|
235
293
|
|
236
294
|
# Get all the fields in a hash.
|
295
|
+
#
|
296
|
+
# @param [String] key
|
297
|
+
# @return [Array<String>]
|
237
298
|
def hkeys(key)
|
238
299
|
synchronize do
|
239
300
|
@client.call [:hkeys, key]
|
@@ -241,19 +302,24 @@ class Redis
|
|
241
302
|
end
|
242
303
|
|
243
304
|
# Find all keys matching the given pattern.
|
305
|
+
#
|
306
|
+
# @param [String] pattern
|
307
|
+
# @return [Array<String>]
|
244
308
|
def keys(pattern = "*")
|
245
309
|
synchronize do
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
310
|
+
@client.call [:keys, pattern] do |reply|
|
311
|
+
if reply.kind_of?(String)
|
312
|
+
reply.split(" ")
|
313
|
+
else
|
314
|
+
reply
|
315
|
+
end
|
252
316
|
end
|
253
317
|
end
|
254
318
|
end
|
255
319
|
|
256
320
|
# Return a random key from the keyspace.
|
321
|
+
#
|
322
|
+
# @return [String]
|
257
323
|
def randomkey
|
258
324
|
synchronize do
|
259
325
|
@client.call [:randomkey]
|
@@ -261,6 +327,9 @@ class Redis
|
|
261
327
|
end
|
262
328
|
|
263
329
|
# Echo the given string.
|
330
|
+
#
|
331
|
+
# @param [String] value
|
332
|
+
# @return [String]
|
264
333
|
def echo(value)
|
265
334
|
synchronize do
|
266
335
|
@client.call [:echo, value]
|
@@ -268,6 +337,8 @@ class Redis
|
|
268
337
|
end
|
269
338
|
|
270
339
|
# Ping the server.
|
340
|
+
#
|
341
|
+
# @return [String] `PONG`
|
271
342
|
def ping
|
272
343
|
synchronize do
|
273
344
|
@client.call [:ping]
|
@@ -275,6 +346,8 @@ class Redis
|
|
275
346
|
end
|
276
347
|
|
277
348
|
# Get the UNIX time stamp of the last successful save to disk.
|
349
|
+
#
|
350
|
+
# @return [Fixnum]
|
278
351
|
def lastsave
|
279
352
|
synchronize do
|
280
353
|
@client.call [:lastsave]
|
@@ -282,6 +355,8 @@ class Redis
|
|
282
355
|
end
|
283
356
|
|
284
357
|
# Return the number of keys in the selected database.
|
358
|
+
#
|
359
|
+
# @return [Fixnum]
|
285
360
|
def dbsize
|
286
361
|
synchronize do
|
287
362
|
@client.call [:dbsize]
|
@@ -289,13 +364,19 @@ class Redis
|
|
289
364
|
end
|
290
365
|
|
291
366
|
# Determine if a key exists.
|
367
|
+
#
|
368
|
+
# @param [String] key
|
369
|
+
# @return [Boolean]
|
292
370
|
def exists(key)
|
293
371
|
synchronize do
|
294
|
-
|
372
|
+
@client.call [:exists, key], &_boolify
|
295
373
|
end
|
296
374
|
end
|
297
375
|
|
298
376
|
# Get the length of a list.
|
377
|
+
#
|
378
|
+
# @param [String] key
|
379
|
+
# @return [Fixnum]
|
299
380
|
def llen(key)
|
300
381
|
synchronize do
|
301
382
|
@client.call [:llen, key]
|
@@ -303,6 +384,11 @@ class Redis
|
|
303
384
|
end
|
304
385
|
|
305
386
|
# Get a range of elements from a list.
|
387
|
+
#
|
388
|
+
# @param [String] key
|
389
|
+
# @param [Fixnum] start start index
|
390
|
+
# @param [Fixnum] stop stop index
|
391
|
+
# @return [Array<String>]
|
306
392
|
def lrange(key, start, stop)
|
307
393
|
synchronize do
|
308
394
|
@client.call [:lrange, key, start, stop]
|
@@ -310,6 +396,11 @@ class Redis
|
|
310
396
|
end
|
311
397
|
|
312
398
|
# Trim a list to the specified range.
|
399
|
+
#
|
400
|
+
# @param [String] key
|
401
|
+
# @param [Fixnum] start start index
|
402
|
+
# @param [Fixnum] stop stop index
|
403
|
+
# @return [String] `OK`
|
313
404
|
def ltrim(key, start, stop)
|
314
405
|
synchronize do
|
315
406
|
@client.call [:ltrim, key, start, stop]
|
@@ -317,6 +408,10 @@ class Redis
|
|
317
408
|
end
|
318
409
|
|
319
410
|
# Get an element from a list by its index.
|
411
|
+
#
|
412
|
+
# @param [String] key
|
413
|
+
# @param [Fixnum] index
|
414
|
+
# @return [String]
|
320
415
|
def lindex(key, index)
|
321
416
|
synchronize do
|
322
417
|
@client.call [:lindex, key, index]
|
@@ -324,6 +419,13 @@ class Redis
|
|
324
419
|
end
|
325
420
|
|
326
421
|
# Insert an element before or after another element in a list.
|
422
|
+
#
|
423
|
+
# @param [String] key
|
424
|
+
# @param [String, Symbol] where `BEFORE` or `AFTER`
|
425
|
+
# @param [String] pivot reference element
|
426
|
+
# @param [String] value
|
427
|
+
# @return [Fixnum] length of the list after the insert operation, or `-1`
|
428
|
+
# when the element `pivot` was not found
|
327
429
|
def linsert(key, where, pivot, value)
|
328
430
|
synchronize do
|
329
431
|
@client.call [:linsert, key, where, pivot, value]
|
@@ -331,6 +433,11 @@ class Redis
|
|
331
433
|
end
|
332
434
|
|
333
435
|
# Set the value of an element in a list by its index.
|
436
|
+
#
|
437
|
+
# @param [String] key
|
438
|
+
# @param [Fixnum] index
|
439
|
+
# @param [String] value
|
440
|
+
# @return [String] `OK`
|
334
441
|
def lset(key, index, value)
|
335
442
|
synchronize do
|
336
443
|
@client.call [:lset, key, index, value]
|
@@ -338,13 +445,25 @@ class Redis
|
|
338
445
|
end
|
339
446
|
|
340
447
|
# Remove elements from a list.
|
448
|
+
#
|
449
|
+
# @param [String] key
|
450
|
+
# @param [Fixnum] count number of elements to remove. Use a positive
|
451
|
+
# value to remove the first `count` occurrences of `value`. A negative
|
452
|
+
# value to remove the last `count` occurrences of `value`. Or zero, to
|
453
|
+
# remove all occurrences of `value` from the list.
|
454
|
+
# @param [String] value
|
455
|
+
# @return [Fixnum] the number of removed elements
|
341
456
|
def lrem(key, count, value)
|
342
457
|
synchronize do
|
343
458
|
@client.call [:lrem, key, count, value]
|
344
459
|
end
|
345
460
|
end
|
346
461
|
|
347
|
-
# Append
|
462
|
+
# Append one or more values to a list, creating the list if it doesn't exist
|
463
|
+
#
|
464
|
+
# @param [String] key
|
465
|
+
# @param [String] value
|
466
|
+
# @return [Fixnum] the length of the list after the push operation
|
348
467
|
def rpush(key, value)
|
349
468
|
synchronize do
|
350
469
|
@client.call [:rpush, key, value]
|
@@ -352,13 +471,21 @@ class Redis
|
|
352
471
|
end
|
353
472
|
|
354
473
|
# Append a value to a list, only if the list exists.
|
474
|
+
#
|
475
|
+
# @param [String] key
|
476
|
+
# @param [String] value
|
477
|
+
# @return [Fixnum] the length of the list after the push operation
|
355
478
|
def rpushx(key, value)
|
356
479
|
synchronize do
|
357
480
|
@client.call [:rpushx, key, value]
|
358
481
|
end
|
359
482
|
end
|
360
483
|
|
361
|
-
# Prepend
|
484
|
+
# Prepend one or more values to a list, creating the list if it doesn't exist
|
485
|
+
#
|
486
|
+
# @param [String] key
|
487
|
+
# @param [String] value
|
488
|
+
# @return [Fixnum] the length of the list after the push operation
|
362
489
|
def lpush(key, value)
|
363
490
|
synchronize do
|
364
491
|
@client.call [:lpush, key, value]
|
@@ -366,6 +493,10 @@ class Redis
|
|
366
493
|
end
|
367
494
|
|
368
495
|
# Prepend a value to a list, only if the list exists.
|
496
|
+
#
|
497
|
+
# @param [String] key
|
498
|
+
# @param [String] value
|
499
|
+
# @return [Fixnum] the length of the list after the push operation
|
369
500
|
def lpushx(key, value)
|
370
501
|
synchronize do
|
371
502
|
@client.call [:lpushx, key, value]
|
@@ -373,6 +504,9 @@ class Redis
|
|
373
504
|
end
|
374
505
|
|
375
506
|
# Remove and get the last element in a list.
|
507
|
+
#
|
508
|
+
# @param [String] key
|
509
|
+
# @return [String]
|
376
510
|
def rpop(key)
|
377
511
|
synchronize do
|
378
512
|
@client.call [:rpop, key]
|
@@ -380,28 +514,47 @@ class Redis
|
|
380
514
|
end
|
381
515
|
|
382
516
|
# Remove and get the first element in a list, or block until one is available.
|
517
|
+
#
|
518
|
+
# @param [Array<String>] args one or more keys to perform a blocking pop on,
|
519
|
+
# followed by a `Fixnum` timeout value
|
520
|
+
# @return [nil, Array<String>] tuple of list that was popped from and element
|
521
|
+
# that was popped, or nil when the blocking operation timed out
|
383
522
|
def blpop(*args)
|
384
523
|
synchronize do
|
385
|
-
@client.call_without_timeout
|
524
|
+
@client.call_without_timeout [:blpop, *args]
|
386
525
|
end
|
387
526
|
end
|
388
527
|
|
389
528
|
# Remove and get the last element in a list, or block until one is available.
|
529
|
+
#
|
530
|
+
# @param [Array<String>] args one or more keys to perform a blocking pop on,
|
531
|
+
# followed by a `Fixnum` timeout value
|
532
|
+
# @return [nil, Array<String>] tuple of list that was popped from and element
|
533
|
+
# that was popped, or nil when the blocking operation timed out
|
390
534
|
def brpop(*args)
|
391
535
|
synchronize do
|
392
|
-
@client.call_without_timeout
|
536
|
+
@client.call_without_timeout [:brpop, *args]
|
393
537
|
end
|
394
538
|
end
|
395
539
|
|
396
540
|
# Pop a value from a list, push it to another list and return it; or block
|
397
541
|
# until one is available.
|
542
|
+
#
|
543
|
+
# @param [String] source source key
|
544
|
+
# @param [String] destination destination key
|
545
|
+
# @param [Fixnum] timeout
|
546
|
+
# @return [nil, String] the element, or nil when the blocking operation timed out
|
398
547
|
def brpoplpush(source, destination, timeout)
|
399
548
|
synchronize do
|
400
|
-
@client.call_without_timeout
|
549
|
+
@client.call_without_timeout [:brpoplpush, source, destination, timeout]
|
401
550
|
end
|
402
551
|
end
|
403
552
|
|
404
553
|
# Remove the last element in a list, append it to another list and return it.
|
554
|
+
#
|
555
|
+
# @param [String] source source key
|
556
|
+
# @param [String] destination destination key
|
557
|
+
# @return [nil, String] the element, or nil when the source key does not exist
|
405
558
|
def rpoplpush(source, destination)
|
406
559
|
synchronize do
|
407
560
|
@client.call [:rpoplpush, source, destination]
|
@@ -409,13 +562,32 @@ class Redis
|
|
409
562
|
end
|
410
563
|
|
411
564
|
# Remove and get the first element in a list.
|
565
|
+
#
|
566
|
+
# @param [String] key
|
567
|
+
# @return [String]
|
412
568
|
def lpop(key)
|
413
569
|
synchronize do
|
414
570
|
@client.call [:lpop, key]
|
415
571
|
end
|
416
572
|
end
|
417
573
|
|
574
|
+
# Interact with the slowlog (get, len, reset)
|
575
|
+
#
|
576
|
+
# @param [String] subcommand e.g. `get`, `len`, `reset`
|
577
|
+
# @param [Fixnum] length maximum number of entries to return
|
578
|
+
# @return [Array<String>, Fixnum, String] depends on subcommand
|
579
|
+
def slowlog(subcommand, length=nil)
|
580
|
+
synchronize do
|
581
|
+
args = [:slowlog, subcommand]
|
582
|
+
args << length if length
|
583
|
+
@client.call args
|
584
|
+
end
|
585
|
+
end
|
586
|
+
|
418
587
|
# Get all the members in a set.
|
588
|
+
#
|
589
|
+
# @param [String] key
|
590
|
+
# @return [Array<String>]
|
419
591
|
def smembers(key)
|
420
592
|
synchronize do
|
421
593
|
@client.call [:smembers, key]
|
@@ -423,34 +595,76 @@ class Redis
|
|
423
595
|
end
|
424
596
|
|
425
597
|
# Determine if a given value is a member of a set.
|
598
|
+
#
|
599
|
+
# @param [String] key
|
600
|
+
# @param [String] member
|
601
|
+
# @return [Boolean]
|
426
602
|
def sismember(key, member)
|
427
603
|
synchronize do
|
428
|
-
|
604
|
+
@client.call [:sismember, key, member], &_boolify
|
429
605
|
end
|
430
606
|
end
|
431
607
|
|
432
|
-
# Add
|
433
|
-
|
608
|
+
# Add one or more members to a set.
|
609
|
+
#
|
610
|
+
# @param [String] key
|
611
|
+
# @param [String, Array<String>] member one member, or array of members
|
612
|
+
# @return [Boolean, Fixnum] `Boolean` when a single member is specified,
|
613
|
+
# holding whether or not adding the member succeeded, or `Fixnum` when an
|
614
|
+
# array of members is specified, holding the number of members that were
|
615
|
+
# successfully added
|
616
|
+
def sadd(key, member)
|
434
617
|
synchronize do
|
435
|
-
|
618
|
+
@client.call [:sadd, key, member] do |reply|
|
619
|
+
if member.is_a? Array
|
620
|
+
# Variadic: return integer
|
621
|
+
reply
|
622
|
+
else
|
623
|
+
# Single argument: return boolean
|
624
|
+
_boolify.call(reply)
|
625
|
+
end
|
626
|
+
end
|
436
627
|
end
|
437
628
|
end
|
438
629
|
|
439
|
-
# Remove
|
440
|
-
|
441
|
-
|
442
|
-
|
630
|
+
# Remove one or more members from a set.
|
631
|
+
#
|
632
|
+
# @param [String] key
|
633
|
+
# @param [String, Array<String>] member one member, or array of members
|
634
|
+
# @return [Boolean, Fixnum] `Boolean` when a single member is specified,
|
635
|
+
# holding whether or not removing the member succeeded, or `Fixnum` when an
|
636
|
+
# array of members is specified, holding the number of members that were
|
637
|
+
# successfully removed
|
638
|
+
def srem(key, member)
|
639
|
+
synchronize do
|
640
|
+
@client.call [:srem, key, member] do |reply|
|
641
|
+
if member.is_a? Array
|
642
|
+
# Variadic: return integer
|
643
|
+
reply
|
644
|
+
else
|
645
|
+
# Single argument: return boolean
|
646
|
+
_boolify.call(reply)
|
647
|
+
end
|
648
|
+
end
|
443
649
|
end
|
444
650
|
end
|
445
651
|
|
446
652
|
# Move a member from one set to another.
|
653
|
+
#
|
654
|
+
# @param [String] source source key
|
655
|
+
# @param [String] destination destination key
|
656
|
+
# @param [String] member member to move from `source` to `destination`
|
657
|
+
# @return [Boolean]
|
447
658
|
def smove(source, destination, member)
|
448
659
|
synchronize do
|
449
|
-
|
660
|
+
@client.call [:smove, source, destination, member], &_boolify
|
450
661
|
end
|
451
662
|
end
|
452
663
|
|
453
664
|
# Remove and return a random member from a set.
|
665
|
+
#
|
666
|
+
# @param [String] key
|
667
|
+
# @return [String]
|
454
668
|
def spop(key)
|
455
669
|
synchronize do
|
456
670
|
@client.call [:spop, key]
|
@@ -458,6 +672,9 @@ class Redis
|
|
458
672
|
end
|
459
673
|
|
460
674
|
# Get the number of members in a set.
|
675
|
+
#
|
676
|
+
# @param [String] key
|
677
|
+
# @return [Fixnum]
|
461
678
|
def scard(key)
|
462
679
|
synchronize do
|
463
680
|
@client.call [:scard, key]
|
@@ -465,6 +682,9 @@ class Redis
|
|
465
682
|
end
|
466
683
|
|
467
684
|
# Intersect multiple sets.
|
685
|
+
#
|
686
|
+
# @param [String, Array<String>] keys keys pointing to sets to intersect
|
687
|
+
# @return [Array<String>] members in the intersection
|
468
688
|
def sinter(*keys)
|
469
689
|
synchronize do
|
470
690
|
@client.call [:sinter, *keys]
|
@@ -472,6 +692,10 @@ class Redis
|
|
472
692
|
end
|
473
693
|
|
474
694
|
# Intersect multiple sets and store the resulting set in a key.
|
695
|
+
#
|
696
|
+
# @param [String] destination destination key
|
697
|
+
# @param [String, Array<String>] keys keys pointing to sets to intersect
|
698
|
+
# @return [Fixnum] number of elements in the resulting set
|
475
699
|
def sinterstore(destination, *keys)
|
476
700
|
synchronize do
|
477
701
|
@client.call [:sinterstore, destination, *keys]
|
@@ -479,6 +703,9 @@ class Redis
|
|
479
703
|
end
|
480
704
|
|
481
705
|
# Add multiple sets.
|
706
|
+
#
|
707
|
+
# @param [String, Array<String>] keys keys pointing to sets to unify
|
708
|
+
# @return [Array<String>] members in the union
|
482
709
|
def sunion(*keys)
|
483
710
|
synchronize do
|
484
711
|
@client.call [:sunion, *keys]
|
@@ -486,6 +713,10 @@ class Redis
|
|
486
713
|
end
|
487
714
|
|
488
715
|
# Add multiple sets and store the resulting set in a key.
|
716
|
+
#
|
717
|
+
# @param [String] destination destination key
|
718
|
+
# @param [String, Array<String>] keys keys pointing to sets to unify
|
719
|
+
# @return [Fixnum] number of elements in the resulting set
|
489
720
|
def sunionstore(destination, *keys)
|
490
721
|
synchronize do
|
491
722
|
@client.call [:sunionstore, destination, *keys]
|
@@ -493,6 +724,9 @@ class Redis
|
|
493
724
|
end
|
494
725
|
|
495
726
|
# Subtract multiple sets.
|
727
|
+
#
|
728
|
+
# @param [String, Array<String>] keys keys pointing to sets to subtract
|
729
|
+
# @return [Array<String>] members in the difference
|
496
730
|
def sdiff(*keys)
|
497
731
|
synchronize do
|
498
732
|
@client.call [:sdiff, *keys]
|
@@ -500,6 +734,10 @@ class Redis
|
|
500
734
|
end
|
501
735
|
|
502
736
|
# Subtract multiple sets and store the resulting set in a key.
|
737
|
+
#
|
738
|
+
# @param [String] destination destination key
|
739
|
+
# @param [String, Array<String>] keys keys pointing to sets to subtract
|
740
|
+
# @return [Fixnum] number of elements in the resulting set
|
503
741
|
def sdiffstore(destination, *keys)
|
504
742
|
synchronize do
|
505
743
|
@client.call [:sdiffstore, destination, *keys]
|
@@ -507,20 +745,83 @@ class Redis
|
|
507
745
|
end
|
508
746
|
|
509
747
|
# Get a random member from a set.
|
748
|
+
#
|
749
|
+
# @param [String] key
|
750
|
+
# @return [String]
|
510
751
|
def srandmember(key)
|
511
752
|
synchronize do
|
512
753
|
@client.call [:srandmember, key]
|
513
754
|
end
|
514
755
|
end
|
515
756
|
|
516
|
-
# Add
|
517
|
-
|
757
|
+
# Add one or more members to a sorted set, or update the score for members
|
758
|
+
# that already exist.
|
759
|
+
#
|
760
|
+
# @example Add a single `(score, member)` pair to a sorted set
|
761
|
+
# redis.zadd("zset", 32.0, "member")
|
762
|
+
# @example Add an array of `(score, member)` pairs to a sorted set
|
763
|
+
# redis.zadd("zset", [[32.0, "a"], [64.0, "b"]])
|
764
|
+
#
|
765
|
+
# @param [String] key
|
766
|
+
# @param [(Float, String), Array<(Float,String)>] args
|
767
|
+
# - a single `(score, member)` pair
|
768
|
+
# - an array of `(score, member)` pairs
|
769
|
+
#
|
770
|
+
# @return [Boolean, Fixnum]
|
771
|
+
# - `Boolean` when a single pair is specified, holding whether or not it was
|
772
|
+
# **added** to the sorted set
|
773
|
+
# - `Fixnum` when an array of pairs is specified, holding the number of
|
774
|
+
# pairs that were **added** to the sorted set
|
775
|
+
def zadd(key, *args)
|
776
|
+
synchronize do
|
777
|
+
if args.size == 1 && args[0].is_a?(Array)
|
778
|
+
# Variadic: return integer
|
779
|
+
@client.call [:zadd, key] + args[0]
|
780
|
+
elsif args.size == 2
|
781
|
+
# Single pair: return boolean
|
782
|
+
@client.call [:zadd, key, args[0], args[1]], &_boolify
|
783
|
+
else
|
784
|
+
raise ArgumentError, "wrong number of arguments"
|
785
|
+
end
|
786
|
+
end
|
787
|
+
end
|
788
|
+
|
789
|
+
# Remove one or more members from a sorted set.
|
790
|
+
#
|
791
|
+
# @example Remove a single member from a sorted set
|
792
|
+
# redis.zrem("zset", "a")
|
793
|
+
# @example Remove an array of members from a sorted set
|
794
|
+
# redis.zrem("zset", ["a", "b"])
|
795
|
+
#
|
796
|
+
# @param [String] key
|
797
|
+
# @param [String, Array<String>] member
|
798
|
+
# - a single member
|
799
|
+
# - an array of members
|
800
|
+
#
|
801
|
+
# @return [Boolean, Fixnum]
|
802
|
+
# - `Boolean` when a single member is specified, holding whether or not it
|
803
|
+
# was removed from the sorted set
|
804
|
+
# - `Fixnum` when an array of pairs is specified, holding the number of
|
805
|
+
# members that were removed to the sorted set
|
806
|
+
def zrem(key, member)
|
518
807
|
synchronize do
|
519
|
-
|
808
|
+
@client.call [:zrem, key, member] do |reply|
|
809
|
+
if member.is_a? Array
|
810
|
+
# Variadic: return integer
|
811
|
+
reply
|
812
|
+
else
|
813
|
+
# Single argument: return boolean
|
814
|
+
_boolify.call(reply)
|
815
|
+
end
|
816
|
+
end
|
520
817
|
end
|
521
818
|
end
|
522
819
|
|
523
820
|
# Determine the index of a member in a sorted set.
|
821
|
+
#
|
822
|
+
# @param [String] key
|
823
|
+
# @param [String] member
|
824
|
+
# @return [Fixnum]
|
524
825
|
def zrank(key, member)
|
525
826
|
synchronize do
|
526
827
|
@client.call [:zrank, key, member]
|
@@ -529,6 +830,10 @@ class Redis
|
|
529
830
|
|
530
831
|
# Determine the index of a member in a sorted set, with scores ordered from
|
531
832
|
# high to low.
|
833
|
+
#
|
834
|
+
# @param [String] key
|
835
|
+
# @param [String] member
|
836
|
+
# @return [Fixnum]
|
532
837
|
def zrevrank(key, member)
|
533
838
|
synchronize do
|
534
839
|
@client.call [:zrevrank, key, member]
|
@@ -536,13 +841,31 @@ class Redis
|
|
536
841
|
end
|
537
842
|
|
538
843
|
# Increment the score of a member in a sorted set.
|
844
|
+
#
|
845
|
+
# @example
|
846
|
+
# redis.zincrby("zset", 32.0, "a")
|
847
|
+
# # => 64.0
|
848
|
+
#
|
849
|
+
# @param [String] key
|
850
|
+
# @param [Float] increment
|
851
|
+
# @param [String] member
|
852
|
+
# @return [Float] score of the member after incrementing it
|
539
853
|
def zincrby(key, increment, member)
|
540
854
|
synchronize do
|
541
|
-
@client.call [:zincrby, key, increment, member]
|
855
|
+
@client.call [:zincrby, key, increment, member] do |reply|
|
856
|
+
Float(reply) if reply
|
857
|
+
end
|
542
858
|
end
|
543
859
|
end
|
544
860
|
|
545
861
|
# Get the number of members in a sorted set.
|
862
|
+
#
|
863
|
+
# @example
|
864
|
+
# redis.zcard("zset")
|
865
|
+
# # => 4
|
866
|
+
#
|
867
|
+
# @param [String] key
|
868
|
+
# @return [Fixnum]
|
546
869
|
def zcard(key)
|
547
870
|
synchronize do
|
548
871
|
@client.call [:zcard, key]
|
@@ -550,65 +873,205 @@ class Redis
|
|
550
873
|
end
|
551
874
|
|
552
875
|
# Return a range of members in a sorted set, by index.
|
876
|
+
#
|
877
|
+
# @example Retrieve all members from a sorted set
|
878
|
+
# redis.zrange("zset", 0, -1)
|
879
|
+
# # => ["a", "b"]
|
880
|
+
# @example Retrieve all members and their scores from a sorted set
|
881
|
+
# redis.zrange("zset", 0, -1, :with_scores => true)
|
882
|
+
# # => [["a", 32.0], ["b", 64.0]]
|
883
|
+
#
|
884
|
+
# @param [String] key
|
885
|
+
# @param [Fixnum] start start index
|
886
|
+
# @param [Fixnum] stop stop index
|
887
|
+
# @param [Hash] options
|
888
|
+
# - `:with_scores => true`: include scores in output
|
889
|
+
#
|
890
|
+
# @return [Array<String>, Array<(String, Float)>]
|
891
|
+
# - when `:with_scores` is not specified, an array of members
|
892
|
+
# - when `:with_scores` is specified, an array with `(member, score)` pairs
|
553
893
|
def zrange(key, start, stop, options = {})
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
894
|
+
args = []
|
895
|
+
|
896
|
+
with_scores = options[:with_scores] || options[:withscores]
|
897
|
+
args << "WITHSCORES" if with_scores
|
558
898
|
|
559
899
|
synchronize do
|
560
|
-
@client.call [:zrange, key, start, stop, *
|
900
|
+
@client.call [:zrange, key, start, stop, *args] do |reply|
|
901
|
+
if with_scores
|
902
|
+
if reply
|
903
|
+
reply.each_slice(2).map do |member, score|
|
904
|
+
[member, Float(score)]
|
905
|
+
end
|
906
|
+
end
|
907
|
+
else
|
908
|
+
reply
|
909
|
+
end
|
910
|
+
end
|
561
911
|
end
|
562
912
|
end
|
563
913
|
|
564
|
-
# Return a range of members in a sorted set, by
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
914
|
+
# Return a range of members in a sorted set, by index, with scores ordered
|
915
|
+
# from high to low.
|
916
|
+
#
|
917
|
+
# @example Retrieve all members from a sorted set
|
918
|
+
# redis.zrevrange("zset", 0, -1)
|
919
|
+
# # => ["b", "a"]
|
920
|
+
# @example Retrieve all members and their scores from a sorted set
|
921
|
+
# redis.zrevrange("zset", 0, -1, :with_scores => true)
|
922
|
+
# # => [["b", 64.0], ["a", 32.0]]
|
923
|
+
#
|
924
|
+
# @see #zrange
|
925
|
+
def zrevrange(key, start, stop, options = {})
|
926
|
+
args = []
|
571
927
|
|
572
|
-
|
573
|
-
|
574
|
-
end
|
575
|
-
end
|
928
|
+
with_scores = options[:with_scores] || options[:withscores]
|
929
|
+
args << "WITHSCORES" if with_scores
|
576
930
|
|
577
|
-
# Count the members in a sorted set with scores within the given values.
|
578
|
-
def zcount(key, start, stop)
|
579
931
|
synchronize do
|
580
|
-
@client.call [:
|
932
|
+
@client.call [:zrevrange, key, start, stop, *args] do |reply|
|
933
|
+
if with_scores
|
934
|
+
if reply
|
935
|
+
reply.each_slice(2).map do |member, score|
|
936
|
+
[member, Float(score)]
|
937
|
+
end
|
938
|
+
end
|
939
|
+
else
|
940
|
+
reply
|
941
|
+
end
|
942
|
+
end
|
581
943
|
end
|
582
944
|
end
|
583
945
|
|
584
|
-
# Return a range of members in a sorted set, by
|
585
|
-
#
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
946
|
+
# Return a range of members in a sorted set, by score.
|
947
|
+
#
|
948
|
+
# @example Retrieve members with score `>= 5` and `< 100`
|
949
|
+
# redis.zrangebyscore("zset", "5", "(100")
|
950
|
+
# # => ["a", "b"]
|
951
|
+
# @example Retrieve the first 2 members with score `>= 0`
|
952
|
+
# redis.zrangebyscore("zset", "0", "+inf", :limit => [0, 2])
|
953
|
+
# # => ["a", "b"]
|
954
|
+
# @example Retrieve members and their scores with scores `> 5`
|
955
|
+
# redis.zrangebyscore("zset", "(5", "+inf", :with_scores => true)
|
956
|
+
# # => [["a", 32.0], ["b", 64.0]]
|
957
|
+
#
|
958
|
+
# @param [String] key
|
959
|
+
# @param [String] min
|
960
|
+
# - inclusive minimum score is specified verbatim
|
961
|
+
# - exclusive minimum score is specified by prefixing `(`
|
962
|
+
# @param [String] max
|
963
|
+
# - inclusive maximum score is specified verbatim
|
964
|
+
# - exclusive maximum score is specified by prefixing `(`
|
965
|
+
# @param [Hash] options
|
966
|
+
# - `:with_scores => true`: include scores in output
|
967
|
+
# - `:limit => [offset, count]`: skip `offset` members, return a maximum of
|
968
|
+
# `count` members
|
969
|
+
#
|
970
|
+
# @return [Array<String>, Array<(String, Float)>]
|
971
|
+
# - when `:with_scores` is not specified, an array of members
|
972
|
+
# - when `:with_scores` is specified, an array with `(member, score)` pairs
|
973
|
+
def zrangebyscore(key, min, max, options = {})
|
974
|
+
args = []
|
975
|
+
|
976
|
+
with_scores = options[:with_scores] || options[:withscores]
|
977
|
+
args.concat ["WITHSCORES"] if with_scores
|
978
|
+
|
979
|
+
limit = options[:limit]
|
980
|
+
args.concat ["LIMIT", *limit] if limit
|
591
981
|
|
592
982
|
synchronize do
|
593
|
-
@client.call [:
|
983
|
+
@client.call [:zrangebyscore, key, min, max, *args] do |reply|
|
984
|
+
if with_scores
|
985
|
+
if reply
|
986
|
+
reply.each_slice(2).map do |member, score|
|
987
|
+
[member, Float(score)]
|
988
|
+
end
|
989
|
+
end
|
990
|
+
else
|
991
|
+
reply
|
992
|
+
end
|
993
|
+
end
|
594
994
|
end
|
595
995
|
end
|
596
996
|
|
597
997
|
# Return a range of members in a sorted set, by score, with scores ordered
|
598
998
|
# from high to low.
|
999
|
+
#
|
1000
|
+
# @example Retrieve members with score `< 100` and `>= 5`
|
1001
|
+
# redis.zrevrangebyscore("zset", "(100", "5")
|
1002
|
+
# # => ["b", "a"]
|
1003
|
+
# @example Retrieve the first 2 members with score `<= 0`
|
1004
|
+
# redis.zrevrangebyscore("zset", "0", "-inf", :limit => [0, 2])
|
1005
|
+
# # => ["b", "a"]
|
1006
|
+
# @example Retrieve members and their scores with scores `> 5`
|
1007
|
+
# redis.zrevrangebyscore("zset", "+inf", "(5", :with_scores => true)
|
1008
|
+
# # => [["b", 64.0], ["a", 32.0]]
|
1009
|
+
#
|
1010
|
+
# @see #zrangebyscore
|
599
1011
|
def zrevrangebyscore(key, max, min, options = {})
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
1012
|
+
args = []
|
1013
|
+
|
1014
|
+
with_scores = options[:with_scores] || options[:withscores]
|
1015
|
+
args.concat ["WITHSCORES"] if with_scores
|
1016
|
+
|
1017
|
+
limit = options[:limit]
|
1018
|
+
args.concat ["LIMIT", *limit] if limit
|
1019
|
+
|
1020
|
+
synchronize do
|
1021
|
+
@client.call [:zrevrangebyscore, key, max, min, *args] do |reply|
|
1022
|
+
if with_scores
|
1023
|
+
if reply
|
1024
|
+
reply.each_slice(2).map do |member, score|
|
1025
|
+
[member, Float(score)]
|
1026
|
+
end
|
1027
|
+
end
|
1028
|
+
else
|
1029
|
+
reply
|
1030
|
+
end
|
1031
|
+
end
|
604
1032
|
end
|
1033
|
+
end
|
605
1034
|
|
1035
|
+
# Count the members in a sorted set with scores within the given values.
|
1036
|
+
#
|
1037
|
+
# @example Count members with score `>= 5` and `< 100`
|
1038
|
+
# redis.zcount("zset", "5", "(100")
|
1039
|
+
# # => 2
|
1040
|
+
# @example Count members with scores `> 5`
|
1041
|
+
# redis.zcount("zset", "(5", "+inf")
|
1042
|
+
# # => 2
|
1043
|
+
#
|
1044
|
+
# @param [String] key
|
1045
|
+
# @param [String] min
|
1046
|
+
# - inclusive minimum score is specified verbatim
|
1047
|
+
# - exclusive minimum score is specified by prefixing `(`
|
1048
|
+
# @param [String] max
|
1049
|
+
# - inclusive maximum score is specified verbatim
|
1050
|
+
# - exclusive maximum score is specified by prefixing `(`
|
1051
|
+
# @return [Fixnum] number of members in within the specified range
|
1052
|
+
def zcount(key, start, stop)
|
606
1053
|
synchronize do
|
607
|
-
@client.call [:
|
1054
|
+
@client.call [:zcount, key, start, stop]
|
608
1055
|
end
|
609
1056
|
end
|
610
1057
|
|
611
1058
|
# Remove all members in a sorted set within the given scores.
|
1059
|
+
#
|
1060
|
+
# @example Remove members with score `>= 5` and `< 100`
|
1061
|
+
# redis.zremrangebyscore("zset", "5", "(100")
|
1062
|
+
# # => 2
|
1063
|
+
# @example Remove members with scores `> 5`
|
1064
|
+
# redis.zremrangebyscore("zset", "(5", "+inf")
|
1065
|
+
# # => 2
|
1066
|
+
#
|
1067
|
+
# @param [String] key
|
1068
|
+
# @param [String] min
|
1069
|
+
# - inclusive minimum score is specified verbatim
|
1070
|
+
# - exclusive minimum score is specified by prefixing `(`
|
1071
|
+
# @param [String] max
|
1072
|
+
# - inclusive maximum score is specified verbatim
|
1073
|
+
# - exclusive maximum score is specified by prefixing `(`
|
1074
|
+
# @return [Fixnum] number of members that were removed
|
612
1075
|
def zremrangebyscore(key, min, max)
|
613
1076
|
synchronize do
|
614
1077
|
@client.call [:zremrangebyscore, key, min, max]
|
@@ -616,6 +1079,18 @@ class Redis
|
|
616
1079
|
end
|
617
1080
|
|
618
1081
|
# Remove all members in a sorted set within the given indexes.
|
1082
|
+
#
|
1083
|
+
# @example Remove first 5 members
|
1084
|
+
# redis.zremrangebyrank("zset", 0, 4)
|
1085
|
+
# # => 5
|
1086
|
+
# @example Remove last 5 members
|
1087
|
+
# redis.zremrangebyrank("zset", -5, -1)
|
1088
|
+
# # => 5
|
1089
|
+
#
|
1090
|
+
# @param [String] key
|
1091
|
+
# @param [Fixnum] start start index
|
1092
|
+
# @param [Fixnum] stop stop index
|
1093
|
+
# @return [Fixnum] number of members that were removed
|
619
1094
|
def zremrangebyrank(key, start, stop)
|
620
1095
|
synchronize do
|
621
1096
|
@client.call [:zremrangebyrank, key, start, stop]
|
@@ -623,21 +1098,36 @@ class Redis
|
|
623
1098
|
end
|
624
1099
|
|
625
1100
|
# Get the score associated with the given member in a sorted set.
|
1101
|
+
#
|
1102
|
+
# @example Get the score for member "a"
|
1103
|
+
# redis.zscore("zset", "a")
|
1104
|
+
# # => 32.0
|
1105
|
+
#
|
1106
|
+
# @param [String] key
|
1107
|
+
# @param [String] member
|
1108
|
+
# @return [Float] score of the member
|
626
1109
|
def zscore(key, member)
|
627
1110
|
synchronize do
|
628
|
-
@client.call [:zscore, key, member]
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
# Remove a member from a sorted set.
|
633
|
-
def zrem(key, member)
|
634
|
-
synchronize do
|
635
|
-
_bool @client.call [:zrem, key, member]
|
1111
|
+
@client.call [:zscore, key, member] do |reply|
|
1112
|
+
Float(reply) if reply
|
1113
|
+
end
|
636
1114
|
end
|
637
1115
|
end
|
638
1116
|
|
639
1117
|
# Intersect multiple sorted sets and store the resulting sorted set in a new
|
640
1118
|
# key.
|
1119
|
+
#
|
1120
|
+
# @example Compute the intersection of `2*zsetA` with `1*zsetB`, summing their scores
|
1121
|
+
# redis.zinterstore("zsetC", ["zsetA", "zsetB"], :weights => [2.0, 1.0], :aggregate => "sum")
|
1122
|
+
# # => 4
|
1123
|
+
#
|
1124
|
+
# @param [String] destination destination key
|
1125
|
+
# @param [Array<String>] keys source keys
|
1126
|
+
# @param [Hash] options
|
1127
|
+
# - `:weights => [Float, Float, ...]`: weights to associate with source
|
1128
|
+
# sorted sets
|
1129
|
+
# - `:aggregate => String`: aggregate function to use (sum, min, max, ...)
|
1130
|
+
# @return [Fixnum] number of elements in the resulting sorted set
|
641
1131
|
def zinterstore(destination, keys, options = {})
|
642
1132
|
command = CommandOptions.new(options) do |c|
|
643
1133
|
c.splat :weights
|
@@ -650,6 +1140,18 @@ class Redis
|
|
650
1140
|
end
|
651
1141
|
|
652
1142
|
# Add multiple sorted sets and store the resulting sorted set in a new key.
|
1143
|
+
#
|
1144
|
+
# @example Compute the union of `2*zsetA` with `1*zsetB`, summing their scores
|
1145
|
+
# redis.zunionstore("zsetC", ["zsetA", "zsetB"], :weights => [2.0, 1.0], :aggregate => "sum")
|
1146
|
+
# # => 8
|
1147
|
+
#
|
1148
|
+
# @param [String] destination destination key
|
1149
|
+
# @param [Array<String>] keys source keys
|
1150
|
+
# @param [Hash] options
|
1151
|
+
# - `:weights => [Float, Float, ...]`: weights to associate with source
|
1152
|
+
# sorted sets
|
1153
|
+
# - `:aggregate => String`: aggregate function to use (sum, min, max, ...)
|
1154
|
+
# @return [Fixnum] number of elements in the resulting sorted set
|
653
1155
|
def zunionstore(destination, keys, options = {})
|
654
1156
|
command = CommandOptions.new(options) do |c|
|
655
1157
|
c.splat :weights
|
@@ -662,27 +1164,56 @@ class Redis
|
|
662
1164
|
end
|
663
1165
|
|
664
1166
|
# Move a key to another database.
|
1167
|
+
#
|
1168
|
+
# @example Move a key to another database
|
1169
|
+
# redis.set "foo", "bar"
|
1170
|
+
# # => "OK"
|
1171
|
+
# redis.move "foo", 2
|
1172
|
+
# # => true
|
1173
|
+
# redis.exists "foo"
|
1174
|
+
# # => false
|
1175
|
+
# redis.select 2
|
1176
|
+
# # => "OK"
|
1177
|
+
# redis.exists "foo"
|
1178
|
+
# # => true
|
1179
|
+
# resis.get "foo"
|
1180
|
+
# # => "bar"
|
1181
|
+
#
|
1182
|
+
# @param [String] key
|
1183
|
+
# @param [Fixnum] db
|
1184
|
+
# @return [Boolean] whether the key was moved or not
|
665
1185
|
def move(key, db)
|
666
1186
|
synchronize do
|
667
|
-
|
1187
|
+
@client.call [:move, key, db], &_boolify
|
668
1188
|
end
|
669
1189
|
end
|
670
1190
|
|
671
1191
|
# Set the value of a key, only if the key does not exist.
|
1192
|
+
#
|
1193
|
+
# @param [String] key
|
1194
|
+
# @param [String] value
|
1195
|
+
# @return [Boolean] whether the key was set or not
|
672
1196
|
def setnx(key, value)
|
673
1197
|
synchronize do
|
674
|
-
|
1198
|
+
@client.call [:setnx, key, value], &_boolify
|
675
1199
|
end
|
676
1200
|
end
|
677
1201
|
|
678
|
-
# Delete
|
1202
|
+
# Delete one or more keys.
|
1203
|
+
#
|
1204
|
+
# @param [String, Array<String>] keys
|
1205
|
+
# @return [Fixnum] number of keys that were removed
|
679
1206
|
def del(*keys)
|
680
1207
|
synchronize do
|
681
1208
|
@client.call [:del, *keys]
|
682
1209
|
end
|
683
1210
|
end
|
684
1211
|
|
685
|
-
# Rename a key.
|
1212
|
+
# Rename a key. If the new key already exists it is overwritten.
|
1213
|
+
#
|
1214
|
+
# @param [String] old_name
|
1215
|
+
# @param [String] new_name
|
1216
|
+
# @return [String] `OK`
|
686
1217
|
def rename(old_name, new_name)
|
687
1218
|
synchronize do
|
688
1219
|
@client.call [:rename, old_name, new_name]
|
@@ -690,27 +1221,43 @@ class Redis
|
|
690
1221
|
end
|
691
1222
|
|
692
1223
|
# Rename a key, only if the new key does not exist.
|
1224
|
+
#
|
1225
|
+
# @param [String] old_name
|
1226
|
+
# @param [String] new_name
|
1227
|
+
# @return [Boolean] whether the key was renamed or not
|
693
1228
|
def renamenx(old_name, new_name)
|
694
1229
|
synchronize do
|
695
|
-
|
1230
|
+
@client.call [:renamenx, old_name, new_name], &_boolify
|
696
1231
|
end
|
697
1232
|
end
|
698
1233
|
|
699
1234
|
# Set a key's time to live in seconds.
|
1235
|
+
#
|
1236
|
+
# @param [String] key
|
1237
|
+
# @param [Fixnum] seconds time to live. After this timeout has expired,
|
1238
|
+
# the key will automatically be deleted
|
1239
|
+
# @return [Boolean] whether the timeout was set or not
|
700
1240
|
def expire(key, seconds)
|
701
1241
|
synchronize do
|
702
|
-
|
1242
|
+
@client.call [:expire, key, seconds], &_boolify
|
703
1243
|
end
|
704
1244
|
end
|
705
1245
|
|
706
1246
|
# Remove the expiration from a key.
|
1247
|
+
#
|
1248
|
+
# @param [String] key
|
1249
|
+
# @return [Boolean] whether the timeout was removed or not
|
707
1250
|
def persist(key)
|
708
1251
|
synchronize do
|
709
|
-
|
1252
|
+
@client.call [:persist, key], &_boolify
|
710
1253
|
end
|
711
1254
|
end
|
712
1255
|
|
713
1256
|
# Get the time to live for a key.
|
1257
|
+
#
|
1258
|
+
# @param [String] key
|
1259
|
+
# @return [Fixnum] remaining time to live in seconds, or -1 if the
|
1260
|
+
# key does not exist or does not have a timeout
|
714
1261
|
def ttl(key)
|
715
1262
|
synchronize do
|
716
1263
|
@client.call [:ttl, key]
|
@@ -718,23 +1265,29 @@ class Redis
|
|
718
1265
|
end
|
719
1266
|
|
720
1267
|
# Set the expiration for a key as a UNIX timestamp.
|
1268
|
+
#
|
1269
|
+
# @param [String] key
|
1270
|
+
# @param [Fixnum] unix_time expiry time specified as a UNIX timestamp
|
1271
|
+
# (seconds since January 1, 1970). After this timeout has expired,
|
1272
|
+
# the key will automatically be deleted
|
1273
|
+
# @return [Boolean] whether the timeout was set or not
|
721
1274
|
def expireat(key, unix_time)
|
722
1275
|
synchronize do
|
723
|
-
|
1276
|
+
@client.call [:expireat, key, unix_time], &_boolify
|
724
1277
|
end
|
725
1278
|
end
|
726
1279
|
|
727
1280
|
# Set the string value of a hash field.
|
728
1281
|
def hset(key, field, value)
|
729
1282
|
synchronize do
|
730
|
-
|
1283
|
+
@client.call [:hset, key, field, value], &_boolify
|
731
1284
|
end
|
732
1285
|
end
|
733
1286
|
|
734
1287
|
# Set the value of a hash field, only if the field does not exist.
|
735
1288
|
def hsetnx(key, field, value)
|
736
1289
|
synchronize do
|
737
|
-
|
1290
|
+
@client.call [:hsetnx, key, field, value], &_boolify
|
738
1291
|
end
|
739
1292
|
end
|
740
1293
|
|
@@ -750,19 +1303,23 @@ class Redis
|
|
750
1303
|
end
|
751
1304
|
|
752
1305
|
# Get the values of all the given hash fields.
|
753
|
-
def hmget(key, *fields)
|
1306
|
+
def hmget(key, *fields, &blk)
|
754
1307
|
synchronize do
|
755
|
-
@client.call [:hmget, key, *fields]
|
1308
|
+
@client.call [:hmget, key, *fields], &blk
|
756
1309
|
end
|
757
1310
|
end
|
758
1311
|
|
759
1312
|
def mapped_hmget(key, *fields)
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
1313
|
+
hmget(key, *fields) do |reply|
|
1314
|
+
if reply.kind_of?(Array)
|
1315
|
+
hash = Hash.new
|
1316
|
+
fields.zip(reply).each do |field, value|
|
1317
|
+
hash[field] = value
|
1318
|
+
end
|
1319
|
+
hash
|
1320
|
+
else
|
1321
|
+
reply
|
1322
|
+
end
|
766
1323
|
end
|
767
1324
|
end
|
768
1325
|
|
@@ -797,7 +1354,7 @@ class Redis
|
|
797
1354
|
# Determine if a hash field exists.
|
798
1355
|
def hexists(key, field)
|
799
1356
|
synchronize do
|
800
|
-
|
1357
|
+
@client.call [:hexists, key, field], &_boolify
|
801
1358
|
end
|
802
1359
|
end
|
803
1360
|
|
@@ -827,14 +1384,6 @@ class Redis
|
|
827
1384
|
end
|
828
1385
|
end
|
829
1386
|
|
830
|
-
def [](key)
|
831
|
-
get(key)
|
832
|
-
end
|
833
|
-
|
834
|
-
def []=(key,value)
|
835
|
-
set(key, value)
|
836
|
-
end
|
837
|
-
|
838
1387
|
# Set the string value of a key.
|
839
1388
|
def set(key, value)
|
840
1389
|
synchronize do
|
@@ -842,6 +1391,8 @@ class Redis
|
|
842
1391
|
end
|
843
1392
|
end
|
844
1393
|
|
1394
|
+
alias :[]= :set
|
1395
|
+
|
845
1396
|
# Sets or clears the bit at offset in the string value stored at key.
|
846
1397
|
def setbit(key, offset, value)
|
847
1398
|
synchronize do
|
@@ -886,12 +1437,16 @@ class Redis
|
|
886
1437
|
end
|
887
1438
|
|
888
1439
|
def mapped_mget(*keys)
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
1440
|
+
mget(*keys) do |reply|
|
1441
|
+
if reply.kind_of?(Array)
|
1442
|
+
hash = Hash.new
|
1443
|
+
keys.zip(reply).each do |field, value|
|
1444
|
+
hash[field] = value
|
1445
|
+
end
|
1446
|
+
hash
|
1447
|
+
else
|
1448
|
+
reply
|
1449
|
+
end
|
895
1450
|
end
|
896
1451
|
end
|
897
1452
|
|
@@ -939,6 +1494,9 @@ class Redis
|
|
939
1494
|
end
|
940
1495
|
|
941
1496
|
# Determine the type stored at key.
|
1497
|
+
#
|
1498
|
+
# @param [String] key
|
1499
|
+
# @return [String] `string`, `list`, `set`, `zset`, `hash` or `none`
|
942
1500
|
def type(key)
|
943
1501
|
synchronize do
|
944
1502
|
@client.call [:type, key]
|
@@ -950,7 +1508,7 @@ class Redis
|
|
950
1508
|
synchronize do
|
951
1509
|
begin
|
952
1510
|
@client.call [:quit]
|
953
|
-
rescue
|
1511
|
+
rescue ConnectionError
|
954
1512
|
ensure
|
955
1513
|
@client.disconnect
|
956
1514
|
end
|
@@ -960,7 +1518,14 @@ class Redis
|
|
960
1518
|
# Synchronously save the dataset to disk and then shut down the server.
|
961
1519
|
def shutdown
|
962
1520
|
synchronize do
|
963
|
-
@client.
|
1521
|
+
@client.without_reconnect do
|
1522
|
+
begin
|
1523
|
+
@client.call [:shutdown]
|
1524
|
+
rescue ConnectionError
|
1525
|
+
# This means Redis has probably exited.
|
1526
|
+
nil
|
1527
|
+
end
|
1528
|
+
end
|
964
1529
|
end
|
965
1530
|
end
|
966
1531
|
|
@@ -971,12 +1536,12 @@ class Redis
|
|
971
1536
|
end
|
972
1537
|
end
|
973
1538
|
|
974
|
-
def pipelined
|
1539
|
+
def pipelined
|
975
1540
|
synchronize do
|
976
1541
|
begin
|
977
1542
|
original, @client = @client, Pipeline.new
|
978
1543
|
yield
|
979
|
-
original.
|
1544
|
+
original.call_pipeline(@client)
|
980
1545
|
ensure
|
981
1546
|
@client = original
|
982
1547
|
end
|
@@ -1008,15 +1573,16 @@ class Redis
|
|
1008
1573
|
def multi
|
1009
1574
|
synchronize do
|
1010
1575
|
if !block_given?
|
1011
|
-
@client.call :multi
|
1576
|
+
@client.call [:multi]
|
1012
1577
|
else
|
1013
|
-
|
1014
|
-
|
1578
|
+
begin
|
1579
|
+
pipeline = Pipeline::Multi.new
|
1580
|
+
original, @client = @client, pipeline
|
1015
1581
|
yield(self)
|
1016
|
-
|
1582
|
+
original.call_pipeline(pipeline)
|
1583
|
+
ensure
|
1584
|
+
@client = original
|
1017
1585
|
end
|
1018
|
-
|
1019
|
-
result.last
|
1020
1586
|
end
|
1021
1587
|
end
|
1022
1588
|
end
|
@@ -1123,8 +1689,10 @@ private
|
|
1123
1689
|
# Commands returning 1 for true and 0 for false may be executed in a pipeline
|
1124
1690
|
# where the method call will return nil. Propagate the nil instead of falsely
|
1125
1691
|
# returning false.
|
1126
|
-
def
|
1127
|
-
|
1692
|
+
def _boolify
|
1693
|
+
lambda { |value|
|
1694
|
+
value == 1 if value
|
1695
|
+
}
|
1128
1696
|
end
|
1129
1697
|
|
1130
1698
|
def subscription(method, channels, block)
|
@@ -1145,4 +1713,3 @@ require "redis/connection"
|
|
1145
1713
|
require "redis/client"
|
1146
1714
|
require "redis/pipeline"
|
1147
1715
|
require "redis/subscribe"
|
1148
|
-
require "redis/compat"
|