ssdb 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +31 -0
- data/README.md +117 -0
- data/Rakefile +10 -0
- data/lib/ssdb.rb +431 -0
- data/lib/ssdb/batch.rb +27 -0
- data/lib/ssdb/client.rb +173 -0
- data/lib/ssdb/future.rb +30 -0
- data/lib/ssdb/version.rb +3 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/ssdb/batch_spec.rb +38 -0
- data/spec/ssdb/client_spec.rb +48 -0
- data/spec/ssdb/future_spec.rb +30 -0
- data/spec/ssdb_spec.rb +37 -0
- data/spec/types/values_spec.rb +103 -0
- data/spec/types/zsets_spec.rb +116 -0
- data/ssdb.gemspec +25 -0
- metadata +151 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
ssdb (0.1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
diff-lcs (1.2.3)
|
10
|
+
rake (10.0.4)
|
11
|
+
redcarpet (2.2.2)
|
12
|
+
rspec (2.13.0)
|
13
|
+
rspec-core (~> 2.13.0)
|
14
|
+
rspec-expectations (~> 2.13.0)
|
15
|
+
rspec-mocks (~> 2.13.0)
|
16
|
+
rspec-core (2.13.1)
|
17
|
+
rspec-expectations (2.13.0)
|
18
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
19
|
+
rspec-mocks (2.13.1)
|
20
|
+
yard (0.8.6.1)
|
21
|
+
|
22
|
+
PLATFORMS
|
23
|
+
ruby
|
24
|
+
|
25
|
+
DEPENDENCIES
|
26
|
+
bundler
|
27
|
+
rake
|
28
|
+
redcarpet
|
29
|
+
rspec
|
30
|
+
ssdb!
|
31
|
+
yard
|
data/README.md
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
# ssdb-rb
|
2
|
+
|
3
|
+
A Ruby client library for [SSDB][ssdb-home], heaviliy inspired by the great
|
4
|
+
[redis-rb][redisrb-home] library. Requires SSDB version 1.4.2 or higher.
|
5
|
+
|
6
|
+
[ssdb-home]: https://github.com/ideawu/ssdb
|
7
|
+
[redisrb-home]: https://github.com/redis/redis-rb
|
8
|
+
|
9
|
+
### Installation
|
10
|
+
|
11
|
+
Install via rubygems:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem install ssdb
|
15
|
+
```
|
16
|
+
|
17
|
+
Use it with bundler, by adding the following line to your Gemfile:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
gem "ssdb"
|
21
|
+
```
|
22
|
+
|
23
|
+
For more information please visit http://gembundler.com/.
|
24
|
+
|
25
|
+
### Basic usage
|
26
|
+
|
27
|
+
Connect to SSDB, assuming it is listening on `localhost`, port 8888.
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
require "ssdb"
|
31
|
+
|
32
|
+
ssdb = SSDB.new
|
33
|
+
```
|
34
|
+
|
35
|
+
To connect to a custom server, please provide a custom `:url` option:
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
ssdb = SSDB.new url: "ssdb://1.2.3.4:8889"
|
39
|
+
```
|
40
|
+
|
41
|
+
To execute commands:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
ssdb.set("mykey", "hello world")
|
45
|
+
# => true
|
46
|
+
|
47
|
+
ssdb.get("mykey")
|
48
|
+
# => "hello world"
|
49
|
+
```
|
50
|
+
|
51
|
+
Full documentation of all commands is available on [rdoc.info][rdoc].
|
52
|
+
|
53
|
+
[rdoc]: http://rdoc.info/github/bsm/ssdb-rb/
|
54
|
+
|
55
|
+
### Batching/pipelining
|
56
|
+
|
57
|
+
Multiple commands can be executed as a batch operations. Instead of sending
|
58
|
+
commands one-by-one the client is able to send a batch of commands and
|
59
|
+
retrieve all responses as a single socket message exchange cycle.
|
60
|
+
|
61
|
+
Example:
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
ssdb.batch do
|
65
|
+
ssdb.set "foo", "5"
|
66
|
+
ssdb.get "foo"
|
67
|
+
ssdb.incr "foo"
|
68
|
+
end
|
69
|
+
# => [true, "5", 6]
|
70
|
+
```
|
71
|
+
|
72
|
+
### Futures
|
73
|
+
|
74
|
+
Results of individual batch operations are stored as *futures*. Future values
|
75
|
+
can be retrieved via the `#value` method once the batch execution is complete.
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
ssdb.batch do
|
79
|
+
v = ssdb.set "foo", "bar"
|
80
|
+
w = ssdc.incr "baz"
|
81
|
+
end
|
82
|
+
|
83
|
+
v.value
|
84
|
+
# => true
|
85
|
+
|
86
|
+
w.value
|
87
|
+
# => 1
|
88
|
+
```
|
89
|
+
|
90
|
+
### TODO
|
91
|
+
|
92
|
+
* Implement HASH operations
|
93
|
+
|
94
|
+
### Licence (MIT)
|
95
|
+
|
96
|
+
```
|
97
|
+
Copyright (c) 2013 Black Square Media Ltd
|
98
|
+
|
99
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
100
|
+
a copy of this software and associated documentation files (the
|
101
|
+
"Software"), to deal in the Software without restriction, including
|
102
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
103
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
104
|
+
permit persons to whom the Software is furnished to do so, subject to
|
105
|
+
the following conditions:
|
106
|
+
|
107
|
+
The above copyright notice and this permission notice shall be
|
108
|
+
included in all copies or substantial portions of the Software.
|
109
|
+
|
110
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
111
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
112
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
113
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
114
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
115
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
116
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
117
|
+
```
|
data/Rakefile
ADDED
data/lib/ssdb.rb
ADDED
@@ -0,0 +1,431 @@
|
|
1
|
+
require "monitor"
|
2
|
+
|
3
|
+
class SSDB
|
4
|
+
include MonitorMixin
|
5
|
+
|
6
|
+
Error = Class.new(RuntimeError)
|
7
|
+
ConnectionError = Class.new(Error)
|
8
|
+
TimeoutError = Class.new(Error)
|
9
|
+
CommandError = Class.new(Error)
|
10
|
+
FutureNotReady = Class.new(Error)
|
11
|
+
|
12
|
+
T_BOOL = ->r { r == "1" }
|
13
|
+
T_INT = ->r { r.to_i }
|
14
|
+
T_CINT = ->r { r.to_i if r }
|
15
|
+
T_VBOOL = ->r { r.each_slice(2).map {|_, v| v == "1" }}
|
16
|
+
T_VINT = ->r { r.each_slice(2).map {|_, v| v.to_i }}
|
17
|
+
T_STRSTR = ->r { r.each_slice(2).to_a }
|
18
|
+
T_STRINT = ->r { r.each_slice(2).map {|v, s| [v, s.to_i] } }
|
19
|
+
T_MAPINT = ->r,n { h = {}; r.each_slice(2) {|k, v| h[k] = v }; n.map {|k| h[k].to_i } }
|
20
|
+
T_MAPSTR = ->r,n { h = {}; r.each_slice(2) {|k, v| h[k] = v }; n.map {|k| h[k] } }
|
21
|
+
BLANK = "".freeze
|
22
|
+
|
23
|
+
# @attr_reader [SSDB::Client] the client
|
24
|
+
attr_reader :client
|
25
|
+
|
26
|
+
# @return [SSDB] the current/global SSDB connection
|
27
|
+
def self.current
|
28
|
+
@current ||= SSDB.new
|
29
|
+
end
|
30
|
+
|
31
|
+
# @param [SSDB] ssdb the current/global SSDB connection
|
32
|
+
def self.current=(ssdb)
|
33
|
+
@current = ssdb
|
34
|
+
end
|
35
|
+
|
36
|
+
# @see SSDB::Client#initialize
|
37
|
+
def initialize(*a)
|
38
|
+
@client = Client.new(*a)
|
39
|
+
super() # Monitor#initialize
|
40
|
+
end
|
41
|
+
|
42
|
+
# Execute a batch operation
|
43
|
+
#
|
44
|
+
# @example simple batch
|
45
|
+
#
|
46
|
+
# ssdb.batch do
|
47
|
+
# ssdb.set "foo", "5"
|
48
|
+
# ssdb.get "foo"
|
49
|
+
# ssdb.incr "foo"
|
50
|
+
# end
|
51
|
+
# # => [true, "5", 6]
|
52
|
+
#
|
53
|
+
# @example batch with futures
|
54
|
+
#
|
55
|
+
# ssdb.batch do
|
56
|
+
# v = ssdb.set "foo", "5"
|
57
|
+
# w = ssdb.incr "foo"
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# v.value
|
61
|
+
# # => true
|
62
|
+
# w.value
|
63
|
+
# # => 6
|
64
|
+
#
|
65
|
+
def batch
|
66
|
+
mon_synchronize do
|
67
|
+
begin
|
68
|
+
original, @client = @client, SSDB::Batch.new
|
69
|
+
yield(self)
|
70
|
+
@client.values = original.perform(@client)
|
71
|
+
ensure
|
72
|
+
@client = original
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Returns value at `key`.
|
78
|
+
#
|
79
|
+
# @param [String] key the key
|
80
|
+
# @return [String] the value
|
81
|
+
def get(key)
|
82
|
+
mon_synchronize do
|
83
|
+
perform ["get", key]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Sets `value` at `key`.
|
88
|
+
#
|
89
|
+
# @param [String] key the key
|
90
|
+
# @param [String] value the value
|
91
|
+
def set(key, value)
|
92
|
+
mon_synchronize do
|
93
|
+
perform ["set", key, value], proc: T_BOOL
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Increments a `key` by value
|
98
|
+
#
|
99
|
+
# @param [String] key the key
|
100
|
+
# @param [Integer] value the increment
|
101
|
+
def incr(key, value = 1)
|
102
|
+
mon_synchronize do
|
103
|
+
perform ["incr", key, value], proc: T_INT
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Decrements a `key` by value
|
108
|
+
#
|
109
|
+
# @param [String] key the key
|
110
|
+
# @param [Integer] value the decrement
|
111
|
+
def decr(key, value = 1)
|
112
|
+
mon_synchronize do
|
113
|
+
perform ["decr", key, value], proc: T_INT
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Checks existence of `key`.
|
118
|
+
#
|
119
|
+
# @param [String] key the key
|
120
|
+
# @return [Boolean] true if exists
|
121
|
+
def exists(key)
|
122
|
+
mon_synchronize do
|
123
|
+
perform ["exists", key], proc: T_BOOL
|
124
|
+
end
|
125
|
+
end
|
126
|
+
alias_method :exists?, :exists
|
127
|
+
|
128
|
+
# Delete `key`.
|
129
|
+
#
|
130
|
+
# @param [String] key the key
|
131
|
+
def del(key)
|
132
|
+
mon_synchronize do
|
133
|
+
perform ["del", key]
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# Scans keys between `start` and `stop`.
|
138
|
+
#
|
139
|
+
# @param [String] start start at this key
|
140
|
+
# @param [String] stop stop at this key
|
141
|
+
# @param [Hash] opts options
|
142
|
+
# @option opts [Integer] :limit limit results
|
143
|
+
# @return [Array<String>] matching keys
|
144
|
+
def keys(start, stop, opts = {})
|
145
|
+
limit = opts[:limit] || -1
|
146
|
+
mon_synchronize do
|
147
|
+
perform ["keys", start, stop, limit], multi: true
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# Scans keys between `start` and `stop`.
|
152
|
+
#
|
153
|
+
# @param [String] start start at this key
|
154
|
+
# @param [String] stop stop at this key
|
155
|
+
# @param [Hash] opts options
|
156
|
+
# @option opts [Integer] :limit limit results
|
157
|
+
# @return [Array<Array<String,String>>] key/value pairs
|
158
|
+
def scan(start, stop, opts = {})
|
159
|
+
limit = opts[:limit] || -1
|
160
|
+
mon_synchronize do
|
161
|
+
perform ["scan", start, stop, limit], multi: true, proc: T_STRSTR
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# Reverse-scans keys between `start` and `stop`.
|
166
|
+
#
|
167
|
+
# @param [String] start start at this key
|
168
|
+
# @param [String] stop stop at this key
|
169
|
+
# @param [Hash] opts options
|
170
|
+
# @option opts [Integer] :limit limit results
|
171
|
+
# @return [Array<Array<String,String>>] key/value pairs in reverse order
|
172
|
+
def rscan(start, stop, opts = {})
|
173
|
+
limit = opts[:limit] || -1
|
174
|
+
mon_synchronize do
|
175
|
+
perform ["rscan", start, stop, limit], multi: true, proc: T_STRSTR
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
# Sets multiple keys
|
180
|
+
#
|
181
|
+
# @param [Hash] pairs key/value pairs
|
182
|
+
def multi_set(pairs)
|
183
|
+
mon_synchronize do
|
184
|
+
perform ["multi_set", *pairs.to_a].flatten, proc: T_INT
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
# Retrieves multiple keys
|
189
|
+
#
|
190
|
+
# @param [Array<String>] keys
|
191
|
+
# @return [Array<String>] values
|
192
|
+
def multi_get(keys)
|
193
|
+
keys = Array(keys) unless keys.is_a?(Array)
|
194
|
+
mon_synchronize do
|
195
|
+
perform ["multi_get", *keys], multi: true, proc: T_MAPSTR, args: [keys]
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# Deletes multiple keys
|
200
|
+
#
|
201
|
+
# @param [Array<String>] keys
|
202
|
+
def multi_del(keys)
|
203
|
+
keys = Array(keys) unless keys.is_a?(Array)
|
204
|
+
mon_synchronize do
|
205
|
+
perform ["multi_del", *keys], proc: T_INT
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
# Checks existence of multiple keys
|
210
|
+
#
|
211
|
+
# @param [Array<String>] keys
|
212
|
+
# @return [Array<Boolean>] results
|
213
|
+
def multi_exists(keys)
|
214
|
+
keys = Array(keys) unless keys.is_a?(Array)
|
215
|
+
mon_synchronize do
|
216
|
+
perform ["multi_exists", *keys], multi: true, proc: T_VBOOL
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
# Returns the score of `member` at `key`.
|
221
|
+
#
|
222
|
+
# @param [String] key the key
|
223
|
+
# @param [String] member the member
|
224
|
+
# @return [Float] the score
|
225
|
+
def zget(key, member)
|
226
|
+
mon_synchronize do
|
227
|
+
perform ["zget", key, member], proc: T_CINT
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
# Sets the `score` of `member` at `key`.
|
232
|
+
#
|
233
|
+
# @param [String] key the key
|
234
|
+
# @param [String] member the member
|
235
|
+
# @param [Numeric] score the score
|
236
|
+
def zset(key, member, score)
|
237
|
+
mon_synchronize do
|
238
|
+
perform ["zset", key, member, score], proc: T_BOOL
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
# Redis 'compatibility'.
|
243
|
+
#
|
244
|
+
# @param [String] key the key
|
245
|
+
# @param [Numeric] score the score
|
246
|
+
# @param [String] member the member
|
247
|
+
def zadd(key, score, member)
|
248
|
+
zset(key, member, score)
|
249
|
+
end
|
250
|
+
|
251
|
+
# Increments the `member` in `key` by `score`
|
252
|
+
#
|
253
|
+
# @param [String] key the key
|
254
|
+
# @param [String] member the member
|
255
|
+
# @param [Integer] score the increment
|
256
|
+
def zincr(key, member, score = 1)
|
257
|
+
mon_synchronize do
|
258
|
+
perform ["zincr", key, member, score], proc: T_INT
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
# Decrements the `member` in `key` by `score`
|
263
|
+
#
|
264
|
+
# @param [String] key the key
|
265
|
+
# @param [String] member the member
|
266
|
+
# @param [Integer] score the decrement
|
267
|
+
def zdecr(key, member, score = 1)
|
268
|
+
mon_synchronize do
|
269
|
+
perform ["zdecr", key, member, score], proc: T_INT
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
# Checks existence of a zset at `key`.
|
274
|
+
#
|
275
|
+
# @param [String] key the key
|
276
|
+
# @return [Boolean] true if exists
|
277
|
+
def zexists(key)
|
278
|
+
mon_synchronize do
|
279
|
+
perform ["zexists", key], proc: T_BOOL
|
280
|
+
end
|
281
|
+
end
|
282
|
+
alias_method :zexists?, :zexists
|
283
|
+
|
284
|
+
# Returns the cardinality of a set `key`.
|
285
|
+
#
|
286
|
+
# @param [String] key the key
|
287
|
+
def zsize(key)
|
288
|
+
mon_synchronize do
|
289
|
+
perform ["zsize", key], proc: T_INT
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
# Delete an `member` from a zset `key`.
|
294
|
+
#
|
295
|
+
# @param [String] key the key
|
296
|
+
# @param [String] member the member
|
297
|
+
def zdel(key, member)
|
298
|
+
mon_synchronize do
|
299
|
+
perform ["zdel", key, member], proc: T_BOOL
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
# List zset keys between `start` and `stop`.
|
304
|
+
#
|
305
|
+
# @param [String] start start at this key
|
306
|
+
# @param [String] stop stop at this key
|
307
|
+
# @param [Hash] opts options
|
308
|
+
# @option opts [Integer] :limit limit results
|
309
|
+
# @return [Array<String>] matching zset keys
|
310
|
+
def zlist(start, stop, opts = {})
|
311
|
+
limit = opts[:limit] || -1
|
312
|
+
mon_synchronize do
|
313
|
+
perform ["zlist", start, stop, limit], multi: true
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
# Lists members at `key` starting at `start_member`
|
318
|
+
# between `start` and `stop` scores.
|
319
|
+
#
|
320
|
+
# @param [String] key the zset
|
321
|
+
# @param [Float] start start at this score
|
322
|
+
# @param [Float] stop stop at this score
|
323
|
+
# @param [Hash] opts options
|
324
|
+
# @option opts [Integer] :limit limit results
|
325
|
+
# @return [Array<String>] matching members
|
326
|
+
def zkeys(key, start, stop, opts = {})
|
327
|
+
limit = opts[:limit] || -1
|
328
|
+
mon_synchronize do
|
329
|
+
perform ["zkeys", key, BLANK, start, stop, limit], multi: true
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
# Scans for members at `key` starting at `start_member`
|
334
|
+
# between `start` and `stop` scores.
|
335
|
+
#
|
336
|
+
# @param [String] key the zset
|
337
|
+
# @param [Float] start start at this score
|
338
|
+
# @param [Float] stop stop at this score
|
339
|
+
# @param [Hash] opts options
|
340
|
+
# @option opts [Integer] :limit limit results
|
341
|
+
# @return [Array<Array<String,Float>>] member/score pairs
|
342
|
+
def zscan(key, start, stop, opts = {})
|
343
|
+
limit = opts[:limit] || -1
|
344
|
+
mon_synchronize do
|
345
|
+
perform ["zscan", key, BLANK, start, stop, limit], multi: true, proc: T_STRINT
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
# Reverse scans for members at `key` starting at `start_member`
|
350
|
+
# between `start` and `stop` scores.
|
351
|
+
#
|
352
|
+
# @param [String] key the zset
|
353
|
+
# @param [Float] start start at this score
|
354
|
+
# @param [Float] stop stop at this score
|
355
|
+
# @param [Hash] opts options
|
356
|
+
# @option opts [Integer] :limit limit results
|
357
|
+
# @return [Array<Array<String,Float>>] member/score pairs
|
358
|
+
def zrscan(key, start, stop, opts = {})
|
359
|
+
limit = opts[:limit] || -1
|
360
|
+
mon_synchronize do
|
361
|
+
perform ["zrscan", key, BLANK, start, stop, limit], multi: true, proc: T_STRINT
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
# Checks existence of multiple sets
|
366
|
+
#
|
367
|
+
# @param [Array<String>] keys
|
368
|
+
# @return [Array<Boolean>] results
|
369
|
+
def multi_zexists(keys)
|
370
|
+
keys = Array(keys) unless keys.is_a?(Array)
|
371
|
+
mon_synchronize do
|
372
|
+
perform ["multi_zexists", *keys], multi: true, proc: T_VBOOL
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
# Returns cardinalities of multiple sets
|
377
|
+
#
|
378
|
+
# @param [Array<String>] keys
|
379
|
+
# @return [Array<Boolean>] results
|
380
|
+
def multi_zsize(keys)
|
381
|
+
keys = Array(keys) unless keys.is_a?(Array)
|
382
|
+
mon_synchronize do
|
383
|
+
perform ["multi_zsize", *keys], multi: true, proc: T_VINT
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
# Sets multiple members of `key`
|
388
|
+
#
|
389
|
+
# @param [String] key the zset
|
390
|
+
# @param [Hash] pairs key/value pairs
|
391
|
+
def multi_zset(key, pairs)
|
392
|
+
mon_synchronize do
|
393
|
+
perform ["multi_zset", key, *pairs.to_a].flatten, proc: T_INT
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
# Retrieves multiple scores from `key`
|
398
|
+
#
|
399
|
+
# @param [String] key the zset
|
400
|
+
# @param [Array<String>] members
|
401
|
+
# @return [Array<Float>] scores
|
402
|
+
def multi_zget(key, members)
|
403
|
+
members = Array(members) unless members.is_a?(Array)
|
404
|
+
mon_synchronize do
|
405
|
+
perform ["multi_zget", key, *members], multi: true, proc: T_MAPINT, args: [members]
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
# Deletes multiple members from `key`
|
410
|
+
#
|
411
|
+
# @param [String] key the zset
|
412
|
+
# @param [Array<String>] members
|
413
|
+
def multi_zdel(key, members)
|
414
|
+
members = Array(members) unless members.is_a?(Array)
|
415
|
+
mon_synchronize do
|
416
|
+
perform ["multi_zdel", key, *members], proc: T_INT
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
private
|
421
|
+
|
422
|
+
def perform(chain, opts = {})
|
423
|
+
opts[:cmd] = chain.map(&:to_s)
|
424
|
+
client.call(opts)
|
425
|
+
end
|
426
|
+
|
427
|
+
end
|
428
|
+
|
429
|
+
%w|version client batch future|.each do |name|
|
430
|
+
require "ssdb/#{name}"
|
431
|
+
end
|