redis 4.8.0 → 5.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +64 -1
  3. data/README.md +101 -161
  4. data/lib/redis/client.rb +82 -625
  5. data/lib/redis/commands/bitmaps.rb +4 -1
  6. data/lib/redis/commands/cluster.rb +1 -18
  7. data/lib/redis/commands/connection.rb +5 -10
  8. data/lib/redis/commands/geo.rb +3 -3
  9. data/lib/redis/commands/hashes.rb +9 -6
  10. data/lib/redis/commands/hyper_log_log.rb +1 -1
  11. data/lib/redis/commands/keys.rb +5 -23
  12. data/lib/redis/commands/lists.rb +74 -25
  13. data/lib/redis/commands/pubsub.rb +28 -25
  14. data/lib/redis/commands/server.rb +15 -15
  15. data/lib/redis/commands/sets.rb +31 -40
  16. data/lib/redis/commands/sorted_sets.rb +84 -12
  17. data/lib/redis/commands/streams.rb +39 -19
  18. data/lib/redis/commands/strings.rb +18 -17
  19. data/lib/redis/commands/transactions.rb +7 -31
  20. data/lib/redis/commands.rb +4 -7
  21. data/lib/redis/distributed.rb +114 -64
  22. data/lib/redis/errors.rb +15 -50
  23. data/lib/redis/hash_ring.rb +26 -26
  24. data/lib/redis/pipeline.rb +43 -222
  25. data/lib/redis/subscribe.rb +50 -14
  26. data/lib/redis/version.rb +1 -1
  27. data/lib/redis.rb +76 -184
  28. metadata +10 -54
  29. data/lib/redis/cluster/command.rb +0 -79
  30. data/lib/redis/cluster/command_loader.rb +0 -33
  31. data/lib/redis/cluster/key_slot_converter.rb +0 -72
  32. data/lib/redis/cluster/node.rb +0 -120
  33. data/lib/redis/cluster/node_key.rb +0 -31
  34. data/lib/redis/cluster/node_loader.rb +0 -34
  35. data/lib/redis/cluster/option.rb +0 -100
  36. data/lib/redis/cluster/slot.rb +0 -86
  37. data/lib/redis/cluster/slot_loader.rb +0 -46
  38. data/lib/redis/cluster.rb +0 -315
  39. data/lib/redis/connection/command_helper.rb +0 -41
  40. data/lib/redis/connection/hiredis.rb +0 -68
  41. data/lib/redis/connection/registry.rb +0 -13
  42. data/lib/redis/connection/ruby.rb +0 -437
  43. data/lib/redis/connection/synchrony.rb +0 -148
  44. data/lib/redis/connection.rb +0 -11
@@ -39,7 +39,10 @@ class Redis
39
39
  # @param [String, Array<String>] keys one or more source keys to perform `operation`
40
40
  # @return [Integer] the length of the string stored in `destkey`
41
41
  def bitop(operation, destkey, *keys)
42
- send_command([:bitop, operation, destkey, *keys])
42
+ keys.flatten!(1)
43
+ command = [:bitop, operation, destkey]
44
+ command.concat(keys)
45
+ send_command(command)
43
46
  end
44
47
 
45
48
  # Return the position of the first bit set to 1 or 0 in a string.
@@ -12,24 +12,7 @@ class Redis
12
12
  #
13
13
  # @return [Object] depends on the subcommand
14
14
  def cluster(subcommand, *args)
15
- subcommand = subcommand.to_s.downcase
16
- block = case subcommand
17
- when 'slots'
18
- HashifyClusterSlots
19
- when 'nodes'
20
- HashifyClusterNodes
21
- when 'slaves'
22
- HashifyClusterSlaves
23
- when 'info'
24
- HashifyInfo
25
- else
26
- Noop
27
- end
28
-
29
- # @see https://github.com/antirez/redis/blob/unstable/src/redis-trib.rb#L127 raw reply expected
30
- block = Noop unless @cluster_mode
31
-
32
- send_command([:cluster, subcommand] + args, &block)
15
+ send_command([:cluster, subcommand] + args)
33
16
  end
34
17
 
35
18
  # Sends `ASKING` command to random node and returns its reply.
@@ -34,10 +34,7 @@ class Redis
34
34
  # @param [Integer] db zero-based index of the DB to use (0 to 15)
35
35
  # @return [String] `OK`
36
36
  def select(db)
37
- synchronize do |client|
38
- client.db = db
39
- client.call([:select, db])
40
- end
37
+ send_command([:select, db])
41
38
  end
42
39
 
43
40
  # Close the connection.
@@ -45,12 +42,10 @@ class Redis
45
42
  # @return [String] `OK`
46
43
  def quit
47
44
  synchronize do |client|
48
- begin
49
- client.call([:quit])
50
- rescue ConnectionError
51
- ensure
52
- client.disconnect
53
- end
45
+ client.call_v([:quit])
46
+ rescue ConnectionError
47
+ ensure
48
+ client.close
54
49
  end
55
50
  end
56
51
  end
@@ -74,9 +74,9 @@ class Redis
74
74
  private
75
75
 
76
76
  def _geoarguments(*args, options: nil, sort: nil, count: nil)
77
- args.push sort if sort
78
- args.push 'count', count if count
79
- args.push options if options
77
+ args << sort if sort
78
+ args << 'COUNT' << Integer(count) if count
79
+ args << options if options
80
80
  args
81
81
  end
82
82
  end
@@ -63,7 +63,7 @@ class Redis
63
63
  #
64
64
  # @see #hmset
65
65
  def mapped_hmset(key, hash)
66
- hmset(key, hash.to_a.flatten)
66
+ hmset(key, hash.flatten)
67
67
  end
68
68
 
69
69
  # Get the value of a hash field.
@@ -87,7 +87,8 @@ class Redis
87
87
  #
88
88
  # @see #mapped_hmget
89
89
  def hmget(key, *fields, &blk)
90
- send_command([:hmget, key] + fields, &blk)
90
+ fields.flatten!(1)
91
+ send_command([:hmget, key].concat(fields), &blk)
91
92
  end
92
93
 
93
94
  # Get the values of all the given hash fields.
@@ -102,7 +103,8 @@ class Redis
102
103
  #
103
104
  # @see #hmget
104
105
  def mapped_hmget(key, *fields)
105
- hmget(key, *fields) do |reply|
106
+ fields.flatten!(1)
107
+ hmget(key, fields) do |reply|
106
108
  if reply.is_a?(Array)
107
109
  Hash[fields.zip(reply)]
108
110
  else
@@ -152,7 +154,8 @@ class Redis
152
154
  # @param [String, Array<String>] field
153
155
  # @return [Integer] the number of fields that were removed from the hash
154
156
  def hdel(key, *fields)
155
- send_command([:hdel, key, *fields])
157
+ fields.flatten!(1)
158
+ send_command([:hdel, key].concat(fields))
156
159
  end
157
160
 
158
161
  # Determine if a hash field exists.
@@ -171,7 +174,7 @@ class Redis
171
174
  # @param [Integer] increment
172
175
  # @return [Integer] value of the field after incrementing it
173
176
  def hincrby(key, field, increment)
174
- send_command([:hincrby, key, field, increment])
177
+ send_command([:hincrby, key, field, Integer(increment)])
175
178
  end
176
179
 
177
180
  # Increment the numeric value of a hash field by the given float number.
@@ -181,7 +184,7 @@ class Redis
181
184
  # @param [Float] increment
182
185
  # @return [Float] value of the field after incrementing it
183
186
  def hincrbyfloat(key, field, increment)
184
- send_command([:hincrbyfloat, key, field, increment], &Floatify)
187
+ send_command([:hincrbyfloat, key, field, Float(increment)], &Floatify)
185
188
  end
186
189
 
187
190
  # Get all the fields in a hash.
@@ -20,7 +20,7 @@ class Redis
20
20
  # @param [String, Array<String>] keys
21
21
  # @return [Integer]
22
22
  def pfcount(*keys)
23
- send_command([:pfcount] + keys)
23
+ send_command([:pfcount] + keys.flatten(1))
24
24
  end
25
25
 
26
26
  # Merge multiple HyperLogLog values into an unique value that will approximate the cardinality of the union of
@@ -76,7 +76,7 @@ class Redis
76
76
  # - `:lt => true`: Set expiry only when the new expiry is less than current one.
77
77
  # @return [Boolean] whether the timeout was set or not
78
78
  def expire(key, seconds, nx: nil, xx: nil, gt: nil, lt: nil)
79
- args = [:expire, key, seconds]
79
+ args = [:expire, key, Integer(seconds)]
80
80
  args << "NX" if nx
81
81
  args << "XX" if xx
82
82
  args << "GT" if gt
@@ -96,7 +96,7 @@ class Redis
96
96
  # - `:lt => true`: Set expiry only when the new expiry is less than current one.
97
97
  # @return [Boolean] whether the timeout was set or not
98
98
  def expireat(key, unix_time, nx: nil, xx: nil, gt: nil, lt: nil)
99
- args = [:expireat, key, unix_time]
99
+ args = [:expireat, key, Integer(unix_time)]
100
100
  args << "NX" if nx
101
101
  args << "XX" if xx
102
102
  args << "GT" if gt
@@ -132,7 +132,7 @@ class Redis
132
132
  # - `:lt => true`: Set expiry only when the new expiry is less than current one.
133
133
  # @return [Boolean] whether the timeout was set or not
134
134
  def pexpire(key, milliseconds, nx: nil, xx: nil, gt: nil, lt: nil)
135
- args = [:pexpire, key, milliseconds]
135
+ args = [:pexpire, key, Integer(milliseconds)]
136
136
  args << "NX" if nx
137
137
  args << "XX" if xx
138
138
  args << "GT" if gt
@@ -152,7 +152,7 @@ class Redis
152
152
  # - `:lt => true`: Set expiry only when the new expiry is less than current one.
153
153
  # @return [Boolean] whether the timeout was set or not
154
154
  def pexpireat(key, ms_unix_time, nx: nil, xx: nil, gt: nil, lt: nil)
155
- args = [:pexpireat, key, ms_unix_time]
155
+ args = [:pexpireat, key, Integer(ms_unix_time)]
156
156
  args << "NX" if nx
157
157
  args << "XX" if xx
158
158
  args << "GT" if gt
@@ -249,24 +249,6 @@ class Redis
249
249
  # @param [String, Array<String>] keys
250
250
  # @return [Integer]
251
251
  def exists(*keys)
252
- if !Redis.exists_returns_integer && keys.size == 1
253
- if Redis.exists_returns_integer.nil?
254
- message = "`Redis#exists(key)` will return an Integer in redis-rb 4.3. `exists?` returns a boolean, you " \
255
- "should use it instead. To opt-in to the new behavior now you can set Redis.exists_returns_integer = " \
256
- "true. To disable this message and keep the current (boolean) behaviour of 'exists' you can set " \
257
- "`Redis.exists_returns_integer = false`, but this option will be removed in 5.0.0. " \
258
- "(#{::Kernel.caller(1, 1).first})\n"
259
-
260
- ::Redis.deprecate!(message)
261
- end
262
-
263
- exists?(*keys)
264
- else
265
- _exists(*keys)
266
- end
267
- end
268
-
269
- def _exists(*keys)
270
252
  send_command([:exists, *keys])
271
253
  end
272
254
 
@@ -445,7 +427,7 @@ class Redis
445
427
 
446
428
  args << cursor
447
429
  args << "MATCH" << match if match
448
- args << "COUNT" << count if count
430
+ args << "COUNT" << Integer(count) if count
449
431
  args << "TYPE" << type if type
450
432
 
451
433
  send_command([command] + args, &block)
@@ -48,7 +48,7 @@ class Redis
48
48
  # @param [String, Symbol] where_destination where to push the element to the source list
49
49
  # e.g. 'LEFT' - to head, 'RIGHT' - to tail
50
50
  # @param [Hash] options
51
- # - `:timeout => Numeric`: timeout in seconds, defaults to no timeout
51
+ # - `:timeout => [Float, Integer]`: timeout in seconds, defaults to no timeout
52
52
  #
53
53
  # @return [nil, String] the element, or nil when the source key does not exist or the timeout expired
54
54
  #
@@ -99,10 +99,10 @@ class Redis
99
99
  #
100
100
  # @param [String] key
101
101
  # @param [Integer] count number of elements to remove
102
- # @return [String, Array<String>] the values of the first elements
102
+ # @return [nil, String, Array<String>] the values of the first elements
103
103
  def lpop(key, count = nil)
104
104
  command = [:lpop, key]
105
- command << count if count
105
+ command << Integer(count) if count
106
106
  send_command(command)
107
107
  end
108
108
 
@@ -110,10 +110,10 @@ class Redis
110
110
  #
111
111
  # @param [String] key
112
112
  # @param [Integer] count number of elements to remove
113
- # @return [String, Array<String>] the values of the last elements
113
+ # @return [nil, String, Array<String>] the values of the last elements
114
114
  def rpop(key, count = nil)
115
115
  command = [:rpop, key]
116
- command << count if count
116
+ command << Integer(count) if count
117
117
  send_command(command)
118
118
  end
119
119
 
@@ -142,7 +142,7 @@ class Redis
142
142
  # @param [String, Array<String>] keys one or more keys to perform the
143
143
  # blocking pop on
144
144
  # @param [Hash] options
145
- # - `:timeout => Integer`: timeout in seconds, defaults to no timeout
145
+ # - `:timeout => [Float, Integer]`: timeout in seconds, defaults to no timeout
146
146
  #
147
147
  # @return [nil, [String, String]]
148
148
  # - `nil` when the operation timed out
@@ -156,7 +156,7 @@ class Redis
156
156
  # @param [String, Array<String>] keys one or more keys to perform the
157
157
  # blocking pop on
158
158
  # @param [Hash] options
159
- # - `:timeout => Integer`: timeout in seconds, defaults to no timeout
159
+ # - `:timeout => [Float, Integer]`: timeout in seconds, defaults to no timeout
160
160
  #
161
161
  # @return [nil, [String, String]]
162
162
  # - `nil` when the operation timed out
@@ -173,23 +173,77 @@ class Redis
173
173
  # @param [String] source source key
174
174
  # @param [String] destination destination key
175
175
  # @param [Hash] options
176
- # - `:timeout => Integer`: timeout in seconds, defaults to no timeout
176
+ # - `:timeout => [Float, Integer]`: timeout in seconds, defaults to no timeout
177
177
  #
178
178
  # @return [nil, String]
179
179
  # - `nil` when the operation timed out
180
180
  # - the element was popped and pushed otherwise
181
- def brpoplpush(source, destination, deprecated_timeout = 0, timeout: deprecated_timeout)
181
+ def brpoplpush(source, destination, timeout: 0)
182
182
  command = [:brpoplpush, source, destination, timeout]
183
183
  send_blocking_command(command, timeout)
184
184
  end
185
185
 
186
+ # Pops one or more elements from the first non-empty list key from the list
187
+ # of provided key names. If lists are empty, blocks until timeout has passed.
188
+ #
189
+ # @example Popping a element
190
+ # redis.blmpop(1.0, 'list')
191
+ # #=> ['list', ['a']]
192
+ # @example With count option
193
+ # redis.blmpop(1.0, 'list', count: 2)
194
+ # #=> ['list', ['a', 'b']]
195
+ #
196
+ # @params timeout [Float] a float value specifying the maximum number of seconds to block) elapses.
197
+ # A timeout of zero can be used to block indefinitely.
198
+ # @params key [String, Array<String>] one or more keys with lists
199
+ # @params modifier [String]
200
+ # - when `"LEFT"` - the elements popped are those from the left of the list
201
+ # - when `"RIGHT"` - the elements popped are those from the right of the list
202
+ # @params count [Integer] a number of elements to pop
203
+ #
204
+ # @return [Array<String, Array<String, Float>>] list of popped elements or nil
205
+ def blmpop(timeout, *keys, modifier: "LEFT", count: nil)
206
+ raise ArgumentError, "Pick either LEFT or RIGHT" unless modifier == "LEFT" || modifier == "RIGHT"
207
+
208
+ args = [:lmpop, keys.size, *keys, modifier]
209
+ args << "COUNT" << Integer(count) if count
210
+
211
+ send_blocking_command(args, timeout)
212
+ end
213
+
214
+ # Pops one or more elements from the first non-empty list key from the list
215
+ # of provided key names.
216
+ #
217
+ # @example Popping a element
218
+ # redis.lmpop('list')
219
+ # #=> ['list', ['a']]
220
+ # @example With count option
221
+ # redis.lmpop('list', count: 2)
222
+ # #=> ['list', ['a', 'b']]
223
+ #
224
+ # @params key [String, Array<String>] one or more keys with lists
225
+ # @params modifier [String]
226
+ # - when `"LEFT"` - the elements popped are those from the left of the list
227
+ # - when `"RIGHT"` - the elements popped are those from the right of the list
228
+ # @params count [Integer] a number of elements to pop
229
+ #
230
+ # @return [Array<String, Array<String, Float>>] list of popped elements or nil
231
+ def lmpop(*keys, modifier: "LEFT", count: nil)
232
+ raise ArgumentError, "Pick either LEFT or RIGHT" unless modifier == "LEFT" || modifier == "RIGHT"
233
+
234
+ args = [:lmpop, keys.size, *keys, modifier]
235
+ args << "COUNT" << Integer(count) if count
236
+
237
+ send_command(args)
238
+ end
239
+
186
240
  # Get an element from a list by its index.
187
241
  #
188
242
  # @param [String] key
189
243
  # @param [Integer] index
190
244
  # @return [String]
191
245
  def lindex(key, index)
192
- send_command([:lindex, key, index])
246
+ send_command([:lindex, key, Integer(index)])
193
247
  end
194
248
 
195
249
  # Insert an element before or after another element in a list.
@@ -211,7 +265,7 @@ class Redis
211
265
  # @param [Integer] stop stop index
212
266
  # @return [Array<String>]
213
267
  def lrange(key, start, stop)
214
- send_command([:lrange, key, start, stop])
268
+ send_command([:lrange, key, Integer(start), Integer(stop)])
215
269
  end
216
270
 
217
271
  # Remove elements from a list.
@@ -224,7 +278,7 @@ class Redis
224
278
  # @param [String] value
225
279
  # @return [Integer] the number of removed elements
226
280
  def lrem(key, count, value)
227
- send_command([:lrem, key, count, value])
281
+ send_command([:lrem, key, Integer(count), value])
228
282
  end
229
283
 
230
284
  # Set the value of an element in a list by its index.
@@ -234,7 +288,7 @@ class Redis
234
288
  # @param [String] value
235
289
  # @return [String] `OK`
236
290
  def lset(key, index, value)
237
- send_command([:lset, key, index, value])
291
+ send_command([:lset, key, Integer(index), value])
238
292
  end
239
293
 
240
294
  # Trim a list to the specified range.
@@ -244,7 +298,7 @@ class Redis
244
298
  # @param [Integer] stop stop index
245
299
  # @return [String] `OK`
246
300
  def ltrim(key, start, stop)
247
- send_command([:ltrim, key, start, stop])
301
+ send_command([:ltrim, key, Integer(start), Integer(stop)])
248
302
  end
249
303
 
250
304
  private
@@ -253,21 +307,16 @@ class Redis
253
307
  timeout = if args.last.is_a?(Hash)
254
308
  options = args.pop
255
309
  options[:timeout]
256
- elsif args.last.respond_to?(:to_int)
257
- last_arg = args.pop
258
- ::Redis.deprecate!(
259
- "Passing the timeout as a positional argument is deprecated, it should be passed as a keyword argument:\n" \
260
- " redis.#{cmd}(#{args.map(&:inspect).join(', ')}, timeout: #{last_arg.to_int})" \
261
- "(called from: #{caller(2, 1).first})"
262
- )
263
- last_arg.to_int
264
310
  end
265
311
 
266
312
  timeout ||= 0
313
+ unless timeout.is_a?(Integer) || timeout.is_a?(Float)
314
+ raise ArgumentError, "timeout must be an Integer or Float, got: #{timeout.class}"
315
+ end
267
316
 
268
- keys = args.flatten
269
-
270
- command = [cmd, keys, timeout]
317
+ args.flatten!(1)
318
+ command = [cmd].concat(args)
319
+ command << timeout
271
320
  send_blocking_command(command, timeout, &blk)
272
321
  end
273
322
 
@@ -9,57 +9,39 @@ class Redis
9
9
  end
10
10
 
11
11
  def subscribed?
12
- synchronize do |client|
13
- client.is_a? SubscribedClient
14
- end
12
+ !@subscription_client.nil?
15
13
  end
16
14
 
17
15
  # Listen for messages published to the given channels.
18
16
  def subscribe(*channels, &block)
19
- synchronize do |_client|
20
- _subscription(:subscribe, 0, channels, block)
21
- end
17
+ _subscription(:subscribe, 0, channels, block)
22
18
  end
23
19
 
24
20
  # Listen for messages published to the given channels. Throw a timeout error
25
21
  # if there is no messages for a timeout period.
26
22
  def subscribe_with_timeout(timeout, *channels, &block)
27
- synchronize do |_client|
28
- _subscription(:subscribe_with_timeout, timeout, channels, block)
29
- end
23
+ _subscription(:subscribe_with_timeout, timeout, channels, block)
30
24
  end
31
25
 
32
26
  # Stop listening for messages posted to the given channels.
33
27
  def unsubscribe(*channels)
34
- synchronize do |client|
35
- raise "Can't unsubscribe if not subscribed." unless subscribed?
36
-
37
- client.unsubscribe(*channels)
38
- end
28
+ _subscription(:unsubscribe, 0, channels, nil)
39
29
  end
40
30
 
41
31
  # Listen for messages published to channels matching the given patterns.
42
32
  def psubscribe(*channels, &block)
43
- synchronize do |_client|
44
- _subscription(:psubscribe, 0, channels, block)
45
- end
33
+ _subscription(:psubscribe, 0, channels, block)
46
34
  end
47
35
 
48
36
  # Listen for messages published to channels matching the given patterns.
49
37
  # Throw a timeout error if there is no messages for a timeout period.
50
38
  def psubscribe_with_timeout(timeout, *channels, &block)
51
- synchronize do |_client|
52
- _subscription(:psubscribe_with_timeout, timeout, channels, block)
53
- end
39
+ _subscription(:psubscribe_with_timeout, timeout, channels, block)
54
40
  end
55
41
 
56
42
  # Stop listening for messages posted to channels matching the given patterns.
57
43
  def punsubscribe(*channels)
58
- synchronize do |client|
59
- raise "Can't unsubscribe if not subscribed." unless subscribed?
60
-
61
- client.punsubscribe(*channels)
62
- end
44
+ _subscription(:punsubscribe, 0, channels, nil)
63
45
  end
64
46
 
65
47
  # Inspect the state of the Pub/Sub subsystem.
@@ -67,6 +49,27 @@ class Redis
67
49
  def pubsub(subcommand, *args)
68
50
  send_command([:pubsub, subcommand] + args)
69
51
  end
52
+
53
+ # Post a message to a channel in a shard.
54
+ def spublish(channel, message)
55
+ send_command([:spublish, channel, message])
56
+ end
57
+
58
+ # Listen for messages published to the given channels in a shard.
59
+ def ssubscribe(*channels, &block)
60
+ _subscription(:ssubscribe, 0, channels, block)
61
+ end
62
+
63
+ # Listen for messages published to the given channels in a shard.
64
+ # Throw a timeout error if there is no messages for a timeout period.
65
+ def ssubscribe_with_timeout(timeout, *channels, &block)
66
+ _subscription(:ssubscribe_with_timeout, timeout, channels, block)
67
+ end
68
+
69
+ # Stop listening for messages posted to the given channels in a shard.
70
+ def sunsubscribe(*channels)
71
+ _subscription(:sunsubscribe, 0, channels, nil)
72
+ end
70
73
  end
71
74
  end
72
75
  end
@@ -36,7 +36,7 @@ class Redis
36
36
  #
37
37
  # @param [String, Symbol] subcommand e.g. `kill`, `list`, `getname`, `setname`
38
38
  # @return [String, Hash] depends on subcommand
39
- def client(subcommand = nil, *args)
39
+ def client(subcommand, *args)
40
40
  send_command([:client, subcommand] + args) do |reply|
41
41
  if subcommand.to_s == "list"
42
42
  reply.lines.map do |line|
@@ -117,9 +117,13 @@ class Redis
117
117
  #
118
118
  # @yield a block to be called for every line of output
119
119
  # @yieldparam [String] line timestamp and command that was executed
120
- def monitor(&block)
120
+ def monitor
121
121
  synchronize do |client|
122
- client.call_loop([:monitor], &block)
122
+ client = client.pubsub
123
+ client.call_v([:monitor])
124
+ loop do
125
+ yield client.next_event
126
+ end
123
127
  end
124
128
  end
125
129
 
@@ -133,13 +137,11 @@ class Redis
133
137
  # Synchronously save the dataset to disk and then shut down the server.
134
138
  def shutdown
135
139
  synchronize do |client|
136
- client.with_reconnect(false) do
137
- begin
138
- client.call([:shutdown])
139
- rescue ConnectionError
140
- # This means Redis has probably exited.
141
- nil
142
- end
140
+ client.disable_reconnection do
141
+ client.call_v([:shutdown])
142
+ rescue ConnectionError
143
+ # This means Redis has probably exited.
144
+ nil
143
145
  end
144
146
  end
145
147
  end
@@ -155,11 +157,9 @@ class Redis
155
157
  # @param [Integer] length maximum number of entries to return
156
158
  # @return [Array<String>, Integer, String] depends on subcommand
157
159
  def slowlog(subcommand, length = nil)
158
- synchronize do |client|
159
- args = [:slowlog, subcommand]
160
- args << length if length
161
- client.call args
162
- end
160
+ args = [:slowlog, subcommand]
161
+ args << Integer(length) if length
162
+ send_command(args)
163
163
  end
164
164
 
165
165
  # Internal command used for replication.