ssdb 0.1.0
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 +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
|