redis 4.1.1 → 4.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: fba6921160b00d34cc11548defceaaee4fc9c181
4
- data.tar.gz: e5eac2ace205355e4890084cc96fe98c651e8d30
2
+ SHA256:
3
+ metadata.gz: 1e49d4c950b40f5d702b9b49bfc16b6af12dba334f5866dfd44f1ff69af55ecc
4
+ data.tar.gz: bf025908a9697cb0308aa3cbce20ecd292a5d9d801c53ad89f739ca5e5beb74f
5
5
  SHA512:
6
- metadata.gz: 5e88bba869f876bc046935479283f108b46107ab00e7ab60487ca524977635dbdc9b0dcfd037a9b057e43765975c26cdc3a0ceea95aefacf608041a18b50f14e
7
- data.tar.gz: 91360e891b269c8ecb962414f29d023ace19af98e929d7f7680590dcb8520a87deb6c2a47ba27da0ea16eb47ee90d4c8bdf2be894a40c00820f9c07479188cc2
6
+ metadata.gz: b27b0178a9120d2843017f5b153dfd48f668ad6b56058bc1058cc318034f1715491cbc9557d71459588b4d3c17970f2572efffd1e79523069ebc4bc208b1c193
7
+ data.tar.gz: e6ec5a2f2d49bebdef37531d0292f1076bde4ec81adc190eae122d972bb8b9d46354c78c1fc2d1340d392d5805b42a63409bf6fe4cd020c1176a31ed249bc450
@@ -1,5 +1,54 @@
1
1
  # Unreleased
2
2
 
3
+ # 4.2.1
4
+
5
+ * Fix `exists?` returning an actual boolean when called with multiple keys. See #918.
6
+ * Setting `Redis.exists_returns_integer = false` disables warning message about new behaviour. See #920.
7
+
8
+ # 4.2.0
9
+
10
+ * Convert commands to accept keyword arguments rather than option hashes. This both help catching typos, and reduce needless allocations.
11
+ * Deprecate the synchrony driver. It will be removed in 5.0 and hopefully maintained as a separate gem. See #915.
12
+ * Make `Redis#exists` variadic, will return an Integer if called with multiple keys.
13
+ * Add `Redis#exists?` to get a Boolean if any of the keys exists.
14
+ * `Redis#exists` when called with a single key will warn that future versions will return an Integer.
15
+ Set `Redis.exists_returns_integer = true` to opt-in to the new behavior.
16
+ * Support `keepttl` ooption in `set`. See #913.
17
+ * Optimized initialization of Redis::Cluster. See #912.
18
+ * Accept sentinel options even with string key. See #599.
19
+ * Verify TLS connections by default. See #900.
20
+
21
+ # 4.1.4
22
+
23
+ * Alias `Redis#disconnect` as `#close`. See #901.
24
+ * Handle clusters with multiple slot ranges. See #894.
25
+ * Fix password authentication to a redis cluster. See #889.
26
+ * Handle recursive MOVED responses. See #882.
27
+ * Increase buffer size in the ruby connector. See #880.
28
+ * Fix thread safety of `Redis.queue`. See #878.
29
+ * Deprecate `Redis::Future#==` as it's likely to be a mistake. See #876.
30
+ * Support `KEEPTTL` option for SET command. See #913.
31
+
32
+ # 4.1.3
33
+
34
+ * Fix the client hanging forever when connecting with SSL to a non-SSL server. See #835.
35
+
36
+ # 4.1.2
37
+
38
+ * Fix several authentication problems with sentinel. See #850 and #856.
39
+ * Explicitly drop Ruby 2.2 support.
40
+
41
+
42
+ # 4.1.1
43
+
44
+ * Fix error handling in multi blocks. See #754.
45
+ * Fix geoadd to accept arrays like georadius and georadiusbymember. See #841.
46
+ * Fix georadius command failing when long == lat. See #841.
47
+ * Fix timeout error in xread block: 0. See #837.
48
+ * Fix incompatibility issue with redis-objects. See #834.
49
+ * Properly handle Errno::EADDRNOTAVAIL on connect.
50
+ * Fix password authentication to sentinel instances. See #813.
51
+
3
52
  # 4.1.0
4
53
 
5
54
  * Add Redis Cluster support. See #716.
data/README.md CHANGED
@@ -1,8 +1,9 @@
1
- # redis-rb [![Build Status][travis-image]][travis-link] [![Inline docs][inchpages-image]][inchpages-link]
1
+ # redis-rb [![Build Status][travis-image]][travis-link] [![Inline docs][inchpages-image]][inchpages-link] ![](https://github.com/redis/redis-rb/workflows/Test/badge.svg?branch=master)
2
2
 
3
3
  A Ruby client that tries to match [Redis][redis-home]' API one-to-one, while still
4
4
  providing an idiomatic interface.
5
5
 
6
+ See [RubyDoc.info][rubydoc] for the API docs of the latest published gem.
6
7
 
7
8
  ## Getting started
8
9
 
@@ -34,6 +35,9 @@ You can also specify connection options as a [`redis://` URL][redis-url]:
34
35
  redis = Redis.new(url: "redis://:p4ssw0rd@10.0.1.1:6380/15")
35
36
  ```
36
37
 
38
+ The client expects passwords with special chracters to be URL-encoded (i.e.
39
+ `CGI.escape(password)`).
40
+
37
41
  By default, the client will try to read the `REDIS_URL` environment variable
38
42
  and use that as URL to connect to. The above statement is therefore equivalent
39
43
  to setting this environment variable and calling `Redis.new` without arguments.
@@ -95,6 +99,15 @@ but a few so that if one is down the client will try the next one. The client
95
99
  is able to remember the last Sentinel that was able to reply correctly and will
96
100
  use it for the next requests.
97
101
 
102
+ If you want to [authenticate](https://redis.io/topics/sentinel#configuring-sentinel-instances-with-authentication) Sentinel itself, you must specify the `password` option per instance.
103
+
104
+ ```ruby
105
+ SENTINELS = [{ host: '127.0.0.1', port: 26380, password: 'mysecret' },
106
+ { host: '127.0.0.1', port: 26381, password: 'mysecret' }]
107
+
108
+ redis = Redis.new(host: 'mymaster', sentinels: SENTINELS, role: :master)
109
+ ```
110
+
98
111
  ## Cluster support
99
112
 
100
113
  `redis-rb` supports [clustering](https://redis.io/topics/cluster-spec).
@@ -133,12 +146,13 @@ redis.mget('{key}1', '{key}2')
133
146
  ```
134
147
 
135
148
  * The client automatically reconnects after a failover occurred, but the caller is responsible for handling errors while it is happening.
149
+ * The client support permanent node failures, and will reroute requests to promoted slaves.
136
150
  * The client supports `MOVED` and `ASK` redirections transparently.
137
151
 
138
152
  ## Storing objects
139
153
 
140
- Redis only stores strings as values. If you want to store an object, you
141
- can use a serialization mechanism such as JSON:
154
+ Redis "string" types can be used to store serialized Ruby objects, for
155
+ example with JSON:
142
156
 
143
157
  ```ruby
144
158
  require "json"
@@ -312,7 +326,7 @@ This library supports natively terminating client side SSL/TLS connections
312
326
  when talking to Redis via a server-side proxy such as [stunnel], [hitch],
313
327
  or [ghostunnel].
314
328
 
315
- To enable SSL support, pass the `:ssl => :true` option when configuring the
329
+ To enable SSL support, pass the `:ssl => true` option when configuring the
316
330
  Redis client, or pass in `:url => "rediss://..."` (like HTTPS for Redis).
317
331
  You will also need to pass in an `:ssl_params => { ... }` hash used to
318
332
  configure the `OpenSSL::SSL::SSLContext` object used for the connection:
@@ -427,6 +441,10 @@ redis = Redis.new(:driver => :synchrony)
427
441
  This library is tested against recent Ruby and Redis versions.
428
442
  Check [Travis][travis-link] for the exact versions supported.
429
443
 
444
+ ## See Also
445
+
446
+ - [async-redis](https://github.com/socketry/async-redis) — An [async](https://github.com/socketry/async) compatible Redis client.
447
+
430
448
  ## Contributors
431
449
 
432
450
  Several people contributed to redis-rb, but we would like to especially
@@ -437,7 +455,7 @@ client and evangelized Redis in Rubyland. Thank you, Ezra.
437
455
  ## Contributing
438
456
 
439
457
  [Fork the project](https://github.com/redis/redis-rb) and send pull
440
- requests. You can also ask for help at `#redis-rb` on Freenode.
458
+ requests.
441
459
 
442
460
 
443
461
  [inchpages-image]: https://inch-ci.org/github/redis/redis-rb.svg
@@ -4,13 +4,26 @@ require "monitor"
4
4
  require_relative "redis/errors"
5
5
 
6
6
  class Redis
7
+ class << self
8
+ attr_reader :exists_returns_integer
7
9
 
8
- def self.current
9
- @current ||= Redis.new
10
+ def exists_returns_integer=(value)
11
+ unless value
12
+ message = "`Redis#exists(key)` will return an Integer by default in redis-rb 4.3. The option to explicitly " \
13
+ "disable this behaviour via `Redis.exists_returns_integer` will be removed in 5.0. You should use " \
14
+ "`exists?` instead."
15
+
16
+ ::Kernel.warn(message)
17
+ end
18
+
19
+ @exists_returns_integer = value
20
+ end
21
+
22
+ attr_writer :current
10
23
  end
11
24
 
12
- def self.current=(redis)
13
- @current = redis
25
+ def self.current
26
+ @current ||= Redis.new
14
27
  end
15
28
 
16
29
  include MonitorMixin
@@ -18,18 +31,22 @@ class Redis
18
31
  # Create a new client instance
19
32
  #
20
33
  # @param [Hash] options
21
- # @option options [String] :url (value of the environment variable REDIS_URL) a Redis URL, for a TCP connection: `redis://:[password]@[hostname]:[port]/[db]` (password, port and database are optional), for a unix socket connection: `unix://[path to Redis socket]`. This overrides all other options.
34
+ # @option options [String] :url (value of the environment variable REDIS_URL) a Redis URL, for a TCP connection:
35
+ # `redis://:[password]@[hostname]:[port]/[db]` (password, port and database are optional), for a unix socket
36
+ # connection: `unix://[path to Redis socket]`. This overrides all other options.
22
37
  # @option options [String] :host ("127.0.0.1") server hostname
23
- # @option options [Fixnum] :port (6379) server port
38
+ # @option options [Integer] :port (6379) server port
24
39
  # @option options [String] :path path to server socket (overrides host and port)
25
40
  # @option options [Float] :timeout (5.0) timeout in seconds
26
41
  # @option options [Float] :connect_timeout (same as timeout) timeout for initial connect in seconds
27
42
  # @option options [String] :password Password to authenticate against server
28
- # @option options [Fixnum] :db (0) Database to select after initial connect
43
+ # @option options [Integer] :db (0) Database to select after initial connect
29
44
  # @option options [Symbol] :driver Driver to use, currently supported: `:ruby`, `:hiredis`, `:synchrony`
30
- # @option options [String] :id ID for the client connection, assigns name to current connection by sending `CLIENT SETNAME`
31
- # @option options [Hash, Fixnum] :tcp_keepalive Keepalive values, if Fixnum `intvl` and `probe` are calculated based on the value, if Hash `time`, `intvl` and `probes` can be specified as a Fixnum
32
- # @option options [Fixnum] :reconnect_attempts Number of attempts trying to connect
45
+ # @option options [String] :id ID for the client connection, assigns name to current connection by sending
46
+ # `CLIENT SETNAME`
47
+ # @option options [Hash, Integer] :tcp_keepalive Keepalive values, if Integer `intvl` and `probe` are calculated
48
+ # based on the value, if Hash `time`, `intvl` and `probes` can be specified as a Integer
49
+ # @option options [Integer] :reconnect_attempts Number of attempts trying to connect
33
50
  # @option options [Boolean] :inherit_socket (false) Whether to use socket in forked process or not
34
51
  # @option options [Array] :sentinels List of sentinels to contact
35
52
  # @option options [Symbol] :role (:master) Role to fetch via Sentinel, either `:master` or `:slave`
@@ -53,7 +70,7 @@ class Redis
53
70
  end
54
71
 
55
72
  # Run code with the client reconnecting
56
- def with_reconnect(val=true, &blk)
73
+ def with_reconnect(val = true, &blk)
57
74
  synchronize do |client|
58
75
  client.with_reconnect(val, &blk)
59
76
  end
@@ -96,7 +113,9 @@ class Redis
96
113
  # See http://redis.io/topics/pipelining for more details.
97
114
  #
98
115
  def queue(*command)
99
- @queue[Thread.current.object_id] << command
116
+ synchronize do
117
+ @queue[Thread.current.object_id] << command
118
+ end
100
119
  end
101
120
 
102
121
  # Sends all commands in the queue.
@@ -135,7 +154,7 @@ class Redis
135
154
 
136
155
  # Change the selected database for the current connection.
137
156
  #
138
- # @param [Fixnum] db zero-based index of the DB to use (0 to 15)
157
+ # @param [Integer] db zero-based index of the DB to use (0 to 15)
139
158
  # @return [String] `OK`
140
159
  def select(db)
141
160
  synchronize do |client|
@@ -204,7 +223,7 @@ class Redis
204
223
  def config(action, *args)
205
224
  synchronize do |client|
206
225
  client.call([:config, action] + args) do |reply|
207
- if reply.kind_of?(Array) && action == :get
226
+ if reply.is_a?(Array) && action == :get
208
227
  Hashify.call(reply)
209
228
  else
210
229
  reply
@@ -234,7 +253,7 @@ class Redis
234
253
 
235
254
  # Return the number of keys in the selected database.
236
255
  #
237
- # @return [Fixnum]
256
+ # @return [Integer]
238
257
  def dbsize
239
258
  synchronize do |client|
240
259
  client.call([:dbsize])
@@ -255,7 +274,7 @@ class Redis
255
274
  def flushall(options = nil)
256
275
  synchronize do |client|
257
276
  if options && options[:async]
258
- client.call([:flushall, :async])
277
+ client.call(%i[flushall async])
259
278
  else
260
279
  client.call([:flushall])
261
280
  end
@@ -270,7 +289,7 @@ class Redis
270
289
  def flushdb(options = nil)
271
290
  synchronize do |client|
272
291
  if options && options[:async]
273
- client.call([:flushdb, :async])
292
+ client.call(%i[flushdb async])
274
293
  else
275
294
  client.call([:flushdb])
276
295
  end
@@ -284,7 +303,7 @@ class Redis
284
303
  def info(cmd = nil)
285
304
  synchronize do |client|
286
305
  client.call([:info, cmd].compact) do |reply|
287
- if reply.kind_of?(String)
306
+ if reply.is_a?(String)
288
307
  reply = HashifyInfo.call(reply)
289
308
 
290
309
  if cmd && cmd.to_s == "commandstats"
@@ -303,7 +322,7 @@ class Redis
303
322
 
304
323
  # Get the UNIX time stamp of the last successful save to disk.
305
324
  #
306
- # @return [Fixnum]
325
+ # @return [Integer]
307
326
  def lastsave
308
327
  synchronize do |client|
309
328
  client.call([:lastsave])
@@ -355,9 +374,9 @@ class Redis
355
374
  # Interact with the slowlog (get, len, reset)
356
375
  #
357
376
  # @param [String] subcommand e.g. `get`, `len`, `reset`
358
- # @param [Fixnum] length maximum number of entries to return
359
- # @return [Array<String>, Fixnum, String] depends on subcommand
360
- def slowlog(subcommand, length=nil)
377
+ # @param [Integer] length maximum number of entries to return
378
+ # @return [Array<String>, Integer, String] depends on subcommand
379
+ def slowlog(subcommand, length = nil)
361
380
  synchronize do |client|
362
381
  args = [:slowlog, subcommand]
363
382
  args << length if length
@@ -377,12 +396,12 @@ class Redis
377
396
  # @example
378
397
  # r.time # => [ 1333093196, 606806 ]
379
398
  #
380
- # @return [Array<Fixnum>] tuple of seconds since UNIX epoch and
399
+ # @return [Array<Integer>] tuple of seconds since UNIX epoch and
381
400
  # microseconds in the current second
382
401
  def time
383
402
  synchronize do |client|
384
403
  client.call([:time]) do |reply|
385
- reply.map(&:to_i) if reply
404
+ reply&.map(&:to_i)
386
405
  end
387
406
  end
388
407
  end
@@ -400,7 +419,7 @@ class Redis
400
419
  # Set a key's time to live in seconds.
401
420
  #
402
421
  # @param [String] key
403
- # @param [Fixnum] seconds time to live
422
+ # @param [Integer] seconds time to live
404
423
  # @return [Boolean] whether the timeout was set or not
405
424
  def expire(key, seconds)
406
425
  synchronize do |client|
@@ -411,7 +430,7 @@ class Redis
411
430
  # Set the expiration for a key as a UNIX timestamp.
412
431
  #
413
432
  # @param [String] key
414
- # @param [Fixnum] unix_time expiry time specified as a UNIX timestamp
433
+ # @param [Integer] unix_time expiry time specified as a UNIX timestamp
415
434
  # @return [Boolean] whether the timeout was set or not
416
435
  def expireat(key, unix_time)
417
436
  synchronize do |client|
@@ -422,7 +441,7 @@ class Redis
422
441
  # Get the time to live (in seconds) for a key.
423
442
  #
424
443
  # @param [String] key
425
- # @return [Fixnum] remaining time to live in seconds.
444
+ # @return [Integer] remaining time to live in seconds.
426
445
  #
427
446
  # In Redis 2.6 or older the command returns -1 if the key does not exist or if
428
447
  # the key exist but has no associated expire.
@@ -440,7 +459,7 @@ class Redis
440
459
  # Set a key's time to live in milliseconds.
441
460
  #
442
461
  # @param [String] key
443
- # @param [Fixnum] milliseconds time to live
462
+ # @param [Integer] milliseconds time to live
444
463
  # @return [Boolean] whether the timeout was set or not
445
464
  def pexpire(key, milliseconds)
446
465
  synchronize do |client|
@@ -451,7 +470,7 @@ class Redis
451
470
  # Set the expiration for a key as number of milliseconds from UNIX Epoch.
452
471
  #
453
472
  # @param [String] key
454
- # @param [Fixnum] ms_unix_time expiry time specified as number of milliseconds from UNIX Epoch.
473
+ # @param [Integer] ms_unix_time expiry time specified as number of milliseconds from UNIX Epoch.
455
474
  # @return [Boolean] whether the timeout was set or not
456
475
  def pexpireat(key, ms_unix_time)
457
476
  synchronize do |client|
@@ -462,7 +481,7 @@ class Redis
462
481
  # Get the time to live (in milliseconds) for a key.
463
482
  #
464
483
  # @param [String] key
465
- # @return [Fixnum] remaining time to live in milliseconds
484
+ # @return [Integer] remaining time to live in milliseconds
466
485
  # In Redis 2.6 or older the command returns -1 if the key does not exist or if
467
486
  # the key exist but has no associated expire.
468
487
  #
@@ -495,9 +514,9 @@ class Redis
495
514
  # - `:replace => Boolean`: if false, raises an error if key already exists
496
515
  # @raise [Redis::CommandError]
497
516
  # @return [String] `"OK"`
498
- def restore(key, ttl, serialized_value, options = {})
517
+ def restore(key, ttl, serialized_value, replace: nil)
499
518
  args = [:restore, key, ttl, serialized_value]
500
- args << 'REPLACE' if options[:replace]
519
+ args << 'REPLACE' if replace
501
520
 
502
521
  synchronize do |client|
503
522
  client.call(args)
@@ -532,7 +551,7 @@ class Redis
532
551
  # Delete one or more keys.
533
552
  #
534
553
  # @param [String, Array<String>] keys
535
- # @return [Fixnum] number of keys that were deleted
554
+ # @return [Integer] number of keys that were deleted
536
555
  def del(*keys)
537
556
  synchronize do |client|
538
557
  client.call([:del] + keys)
@@ -542,20 +561,50 @@ class Redis
542
561
  # Unlink one or more keys.
543
562
  #
544
563
  # @param [String, Array<String>] keys
545
- # @return [Fixnum] number of keys that were unlinked
564
+ # @return [Integer] number of keys that were unlinked
546
565
  def unlink(*keys)
547
566
  synchronize do |client|
548
567
  client.call([:unlink] + keys)
549
568
  end
550
569
  end
551
570
 
552
- # Determine if a key exists.
571
+ # Determine how many of the keys exists.
553
572
  #
554
- # @param [String] key
573
+ # @param [String, Array<String>] keys
574
+ # @return [Integer]
575
+ def exists(*keys)
576
+ if !Redis.exists_returns_integer && keys.size == 1
577
+ if Redis.exists_returns_integer.nil?
578
+ message = "`Redis#exists(key)` will return an Integer in redis-rb 4.3. `exists?` returns a boolean, you " \
579
+ "should use it instead. To opt-in to the new behavior now you can set Redis.exists_returns_integer = " \
580
+ "true. To disable this message and keep the current (boolean) behaviour of 'exists' you can set " \
581
+ "`Redis.exists_returns_integer = false`, but this option will be removed in 5.0. " \
582
+ "(#{::Kernel.caller(1, 1).first})\n"
583
+
584
+ ::Kernel.warn(message)
585
+ end
586
+
587
+ exists?(*keys)
588
+ else
589
+ _exists(*keys)
590
+ end
591
+ end
592
+
593
+ def _exists(*keys)
594
+ synchronize do |client|
595
+ client.call([:exists, *keys])
596
+ end
597
+ end
598
+
599
+ # Determine if any of the keys exists.
600
+ #
601
+ # @param [String, Array<String>] keys
555
602
  # @return [Boolean]
556
- def exists(key)
603
+ def exists?(*keys)
557
604
  synchronize do |client|
558
- client.call([:exists, key], &Boolify)
605
+ client.call([:exists, *keys]) do |value|
606
+ value > 0
607
+ end
559
608
  end
560
609
  end
561
610
 
@@ -566,7 +615,7 @@ class Redis
566
615
  def keys(pattern = "*")
567
616
  synchronize do |client|
568
617
  client.call([:keys, pattern]) do |reply|
569
- if reply.kind_of?(String)
618
+ if reply.is_a?(String)
570
619
  reply.split(" ")
571
620
  else
572
621
  reply
@@ -592,7 +641,7 @@ class Redis
592
641
  # # => "bar"
593
642
  #
594
643
  # @param [String] key
595
- # @param [Fixnum] db
644
+ # @param [Integer] db
596
645
  # @return [Boolean] whether the key was moved or not
597
646
  def move(key, db)
598
647
  synchronize do |client|
@@ -656,36 +705,33 @@ class Redis
656
705
  # - `:order => String`: combination of `ASC`, `DESC` and optionally `ALPHA`
657
706
  # - `:store => String`: key to store the result at
658
707
  #
659
- # @return [Array<String>, Array<Array<String>>, Fixnum]
708
+ # @return [Array<String>, Array<Array<String>>, Integer]
660
709
  # - when `:get` is not specified, or holds a single element, an array of elements
661
710
  # - when `:get` is specified, and holds more than one element, an array of
662
711
  # elements where every element is an array with the result for every
663
712
  # element specified in `:get`
664
713
  # - when `:store` is specified, the number of elements in the stored result
665
- def sort(key, options = {})
666
- args = []
667
-
668
- by = options[:by]
669
- args.concat(["BY", by]) if by
714
+ def sort(key, by: nil, limit: nil, get: nil, order: nil, store: nil)
715
+ args = [:sort, key]
716
+ args << "BY" << by if by
670
717
 
671
- limit = options[:limit]
672
- args.concat(["LIMIT"] + limit) if limit
718
+ if limit
719
+ args << "LIMIT"
720
+ args.concat(limit)
721
+ end
673
722
 
674
- get = Array(options[:get])
675
- args.concat(["GET"].product(get).flatten) unless get.empty?
723
+ get = Array(get)
724
+ get.each do |item|
725
+ args << "GET" << item
726
+ end
676
727
 
677
- order = options[:order]
678
728
  args.concat(order.split(" ")) if order
679
-
680
- store = options[:store]
681
- args.concat(["STORE", store]) if store
729
+ args << "STORE" << store if store
682
730
 
683
731
  synchronize do |client|
684
- client.call([:sort, key] + args) do |reply|
732
+ client.call(args) do |reply|
685
733
  if get.size > 1 && !store
686
- if reply
687
- reply.each_slice(get.size).to_a
688
- end
734
+ reply.each_slice(get.size).to_a if reply
689
735
  else
690
736
  reply
691
737
  end
@@ -710,7 +756,7 @@ class Redis
710
756
  # # => 4
711
757
  #
712
758
  # @param [String] key
713
- # @return [Fixnum] value after decrementing it
759
+ # @return [Integer] value after decrementing it
714
760
  def decr(key)
715
761
  synchronize do |client|
716
762
  client.call([:decr, key])
@@ -724,8 +770,8 @@ class Redis
724
770
  # # => 0
725
771
  #
726
772
  # @param [String] key
727
- # @param [Fixnum] decrement
728
- # @return [Fixnum] value after decrementing it
773
+ # @param [Integer] decrement
774
+ # @return [Integer] value after decrementing it
729
775
  def decrby(key, decrement)
730
776
  synchronize do |client|
731
777
  client.call([:decrby, key, decrement])
@@ -739,7 +785,7 @@ class Redis
739
785
  # # => 6
740
786
  #
741
787
  # @param [String] key
742
- # @return [Fixnum] value after incrementing it
788
+ # @return [Integer] value after incrementing it
743
789
  def incr(key)
744
790
  synchronize do |client|
745
791
  client.call([:incr, key])
@@ -753,8 +799,8 @@ class Redis
753
799
  # # => 10
754
800
  #
755
801
  # @param [String] key
756
- # @param [Fixnum] increment
757
- # @return [Fixnum] value after incrementing it
802
+ # @param [Integer] increment
803
+ # @return [Integer] value after incrementing it
758
804
  def incrby(key, increment)
759
805
  synchronize do |client|
760
806
  client.call([:incrby, key, increment])
@@ -781,31 +827,25 @@ class Redis
781
827
  # @param [String] key
782
828
  # @param [String] value
783
829
  # @param [Hash] options
784
- # - `:ex => Fixnum`: Set the specified expire time, in seconds.
785
- # - `:px => Fixnum`: Set the specified expire time, in milliseconds.
830
+ # - `:ex => Integer`: Set the specified expire time, in seconds.
831
+ # - `:px => Integer`: Set the specified expire time, in milliseconds.
786
832
  # - `:nx => true`: Only set the key if it does not already exist.
787
833
  # - `:xx => true`: Only set the key if it already exist.
834
+ # - `:keepttl => true`: Retain the time to live associated with the key.
788
835
  # @return [String, Boolean] `"OK"` or true, false if `:nx => true` or `:xx => true`
789
- def set(key, value, options = {})
790
- args = []
791
-
792
- ex = options[:ex]
793
- args.concat(["EX", ex]) if ex
794
-
795
- px = options[:px]
796
- args.concat(["PX", px]) if px
797
-
798
- nx = options[:nx]
799
- args.concat(["NX"]) if nx
800
-
801
- xx = options[:xx]
802
- args.concat(["XX"]) if xx
836
+ def set(key, value, ex: nil, px: nil, nx: nil, xx: nil, keepttl: nil)
837
+ args = [:set, key, value.to_s]
838
+ args << "EX" << ex if ex
839
+ args << "PX" << px if px
840
+ args << "NX" if nx
841
+ args << "XX" if xx
842
+ args << "KEEPTTL" if keepttl
803
843
 
804
844
  synchronize do |client|
805
845
  if nx || xx
806
- client.call([:set, key, value.to_s] + args, &BoolifySet)
846
+ client.call(args, &BoolifySet)
807
847
  else
808
- client.call([:set, key, value.to_s] + args)
848
+ client.call(args)
809
849
  end
810
850
  end
811
851
  end
@@ -813,7 +853,7 @@ class Redis
813
853
  # Set the time to live in seconds of a key.
814
854
  #
815
855
  # @param [String] key
816
- # @param [Fixnum] ttl
856
+ # @param [Integer] ttl
817
857
  # @param [String] value
818
858
  # @return [String] `"OK"`
819
859
  def setex(key, ttl, value)
@@ -825,7 +865,7 @@ class Redis
825
865
  # Set the time to live in milliseconds of a key.
826
866
  #
827
867
  # @param [String] key
828
- # @param [Fixnum] ttl
868
+ # @param [Integer] ttl
829
869
  # @param [String] value
830
870
  # @return [String] `"OK"`
831
871
  def psetex(key, ttl, value)
@@ -887,7 +927,7 @@ class Redis
887
927
  # @see #mapped_msetnx
888
928
  def msetnx(*args)
889
929
  synchronize do |client|
890
- client.call([:msetnx] + args, &Boolify)
930
+ client.call([:msetnx, *args], &Boolify)
891
931
  end
892
932
  end
893
933
 
@@ -918,7 +958,7 @@ class Redis
918
958
  # Get the values of all the given keys.
919
959
  #
920
960
  # @example
921
- # redis.mget("key1", "key1")
961
+ # redis.mget("key1", "key2")
922
962
  # # => ["v1", "v2"]
923
963
  #
924
964
  # @param [Array<String>] keys
@@ -927,7 +967,7 @@ class Redis
927
967
  # @see #mapped_mget
928
968
  def mget(*keys, &blk)
929
969
  synchronize do |client|
930
- client.call([:mget] + keys, &blk)
970
+ client.call([:mget, *keys], &blk)
931
971
  end
932
972
  end
933
973
 
@@ -943,7 +983,7 @@ class Redis
943
983
  # @see #mget
944
984
  def mapped_mget(*keys)
945
985
  mget(*keys) do |reply|
946
- if reply.kind_of?(Array)
986
+ if reply.is_a?(Array)
947
987
  Hash[keys.zip(reply)]
948
988
  else
949
989
  reply
@@ -954,9 +994,9 @@ class Redis
954
994
  # Overwrite part of a string at key starting at the specified offset.
955
995
  #
956
996
  # @param [String] key
957
- # @param [Fixnum] offset byte offset
997
+ # @param [Integer] offset byte offset
958
998
  # @param [String] value
959
- # @return [Fixnum] length of the string after it was modified
999
+ # @return [Integer] length of the string after it was modified
960
1000
  def setrange(key, offset, value)
961
1001
  synchronize do |client|
962
1002
  client.call([:setrange, key, offset, value.to_s])
@@ -966,10 +1006,10 @@ class Redis
966
1006
  # Get a substring of the string stored at a key.
967
1007
  #
968
1008
  # @param [String] key
969
- # @param [Fixnum] start zero-based start offset
970
- # @param [Fixnum] stop zero-based end offset. Use -1 for representing
1009
+ # @param [Integer] start zero-based start offset
1010
+ # @param [Integer] stop zero-based end offset. Use -1 for representing
971
1011
  # the end of the string
972
- # @return [Fixnum] `0` or `1`
1012
+ # @return [Integer] `0` or `1`
973
1013
  def getrange(key, start, stop)
974
1014
  synchronize do |client|
975
1015
  client.call([:getrange, key, start, stop])
@@ -979,9 +1019,9 @@ class Redis
979
1019
  # Sets or clears the bit at offset in the string value stored at key.
980
1020
  #
981
1021
  # @param [String] key
982
- # @param [Fixnum] offset bit offset
983
- # @param [Fixnum] value bit value `0` or `1`
984
- # @return [Fixnum] the original bit value stored at `offset`
1022
+ # @param [Integer] offset bit offset
1023
+ # @param [Integer] value bit value `0` or `1`
1024
+ # @return [Integer] the original bit value stored at `offset`
985
1025
  def setbit(key, offset, value)
986
1026
  synchronize do |client|
987
1027
  client.call([:setbit, key, offset, value])
@@ -991,8 +1031,8 @@ class Redis
991
1031
  # Returns the bit value at offset in the string value stored at key.
992
1032
  #
993
1033
  # @param [String] key
994
- # @param [Fixnum] offset bit offset
995
- # @return [Fixnum] `0` or `1`
1034
+ # @param [Integer] offset bit offset
1035
+ # @return [Integer] `0` or `1`
996
1036
  def getbit(key, offset)
997
1037
  synchronize do |client|
998
1038
  client.call([:getbit, key, offset])
@@ -1003,7 +1043,7 @@ class Redis
1003
1043
  #
1004
1044
  # @param [String] key
1005
1045
  # @param [String] value value to append
1006
- # @return [Fixnum] length of the string after appending
1046
+ # @return [Integer] length of the string after appending
1007
1047
  def append(key, value)
1008
1048
  synchronize do |client|
1009
1049
  client.call([:append, key, value])
@@ -1013,9 +1053,9 @@ class Redis
1013
1053
  # Count the number of set bits in a range of the string value stored at key.
1014
1054
  #
1015
1055
  # @param [String] key
1016
- # @param [Fixnum] start start index
1017
- # @param [Fixnum] stop stop index
1018
- # @return [Fixnum] the number of bits set to 1
1056
+ # @param [Integer] start start index
1057
+ # @param [Integer] stop stop index
1058
+ # @return [Integer] the number of bits set to 1
1019
1059
  def bitcount(key, start = 0, stop = -1)
1020
1060
  synchronize do |client|
1021
1061
  client.call([:bitcount, key, start, stop])
@@ -1027,25 +1067,23 @@ class Redis
1027
1067
  # @param [String] operation e.g. `and`, `or`, `xor`, `not`
1028
1068
  # @param [String] destkey destination key
1029
1069
  # @param [String, Array<String>] keys one or more source keys to perform `operation`
1030
- # @return [Fixnum] the length of the string stored in `destkey`
1070
+ # @return [Integer] the length of the string stored in `destkey`
1031
1071
  def bitop(operation, destkey, *keys)
1032
1072
  synchronize do |client|
1033
- client.call([:bitop, operation, destkey] + keys)
1073
+ client.call([:bitop, operation, destkey, *keys])
1034
1074
  end
1035
1075
  end
1036
1076
 
1037
1077
  # Return the position of the first bit set to 1 or 0 in a string.
1038
1078
  #
1039
1079
  # @param [String] key
1040
- # @param [Fixnum] bit whether to look for the first 1 or 0 bit
1041
- # @param [Fixnum] start start index
1042
- # @param [Fixnum] stop stop index
1043
- # @return [Fixnum] the position of the first 1/0 bit.
1080
+ # @param [Integer] bit whether to look for the first 1 or 0 bit
1081
+ # @param [Integer] start start index
1082
+ # @param [Integer] stop stop index
1083
+ # @return [Integer] the position of the first 1/0 bit.
1044
1084
  # -1 if looking for 1 and it is not found or start and stop are given.
1045
- def bitpos(key, bit, start=nil, stop=nil)
1046
- if stop and not start
1047
- raise(ArgumentError, 'stop parameter specified without start parameter')
1048
- end
1085
+ def bitpos(key, bit, start = nil, stop = nil)
1086
+ raise(ArgumentError, 'stop parameter specified without start parameter') if stop && !start
1049
1087
 
1050
1088
  synchronize do |client|
1051
1089
  command = [:bitpos, key, bit]
@@ -1070,7 +1108,7 @@ class Redis
1070
1108
  # Get the length of the value stored in a key.
1071
1109
  #
1072
1110
  # @param [String] key
1073
- # @return [Fixnum] the length of the value stored in the key, or 0
1111
+ # @return [Integer] the length of the value stored in the key, or 0
1074
1112
  # if the key does not exist
1075
1113
  def strlen(key)
1076
1114
  synchronize do |client|
@@ -1081,7 +1119,7 @@ class Redis
1081
1119
  # Get the length of a list.
1082
1120
  #
1083
1121
  # @param [String] key
1084
- # @return [Fixnum]
1122
+ # @return [Integer]
1085
1123
  def llen(key)
1086
1124
  synchronize do |client|
1087
1125
  client.call([:llen, key])
@@ -1092,7 +1130,7 @@ class Redis
1092
1130
  #
1093
1131
  # @param [String] key
1094
1132
  # @param [String, Array<String>] value string value, or array of string values to push
1095
- # @return [Fixnum] the length of the list after the push operation
1133
+ # @return [Integer] the length of the list after the push operation
1096
1134
  def lpush(key, value)
1097
1135
  synchronize do |client|
1098
1136
  client.call([:lpush, key, value])
@@ -1103,7 +1141,7 @@ class Redis
1103
1141
  #
1104
1142
  # @param [String] key
1105
1143
  # @param [String] value
1106
- # @return [Fixnum] the length of the list after the push operation
1144
+ # @return [Integer] the length of the list after the push operation
1107
1145
  def lpushx(key, value)
1108
1146
  synchronize do |client|
1109
1147
  client.call([:lpushx, key, value])
@@ -1114,7 +1152,7 @@ class Redis
1114
1152
  #
1115
1153
  # @param [String] key
1116
1154
  # @param [String, Array<String>] value string value, or array of string values to push
1117
- # @return [Fixnum] the length of the list after the push operation
1155
+ # @return [Integer] the length of the list after the push operation
1118
1156
  def rpush(key, value)
1119
1157
  synchronize do |client|
1120
1158
  client.call([:rpush, key, value])
@@ -1125,7 +1163,7 @@ class Redis
1125
1163
  #
1126
1164
  # @param [String] key
1127
1165
  # @param [String] value
1128
- # @return [Fixnum] the length of the list after the push operation
1166
+ # @return [Integer] the length of the list after the push operation
1129
1167
  def rpushx(key, value)
1130
1168
  synchronize do |client|
1131
1169
  client.call([:rpushx, key, value])
@@ -1164,21 +1202,21 @@ class Redis
1164
1202
  end
1165
1203
 
1166
1204
  def _bpop(cmd, args, &blk)
1167
- options = {}
1168
-
1169
- if args.last.is_a?(Hash)
1205
+ timeout = if args.last.is_a?(Hash)
1170
1206
  options = args.pop
1207
+ options[:timeout]
1171
1208
  elsif args.last.respond_to?(:to_int)
1172
1209
  # Issue deprecation notice in obnoxious mode...
1173
- options[:timeout] = args.pop.to_int
1210
+ args.pop.to_int
1174
1211
  end
1175
1212
 
1213
+ timeout ||= 0
1214
+
1176
1215
  if args.size > 1
1177
1216
  # Issue deprecation notice in obnoxious mode...
1178
1217
  end
1179
1218
 
1180
1219
  keys = args.flatten
1181
- timeout = options[:timeout] || 0
1182
1220
 
1183
1221
  synchronize do |client|
1184
1222
  command = [cmd, keys, timeout]
@@ -1203,7 +1241,7 @@ class Redis
1203
1241
  # @param [String, Array<String>] keys one or more keys to perform the
1204
1242
  # blocking pop on
1205
1243
  # @param [Hash] options
1206
- # - `:timeout => Fixnum`: timeout in seconds, defaults to no timeout
1244
+ # - `:timeout => Integer`: timeout in seconds, defaults to no timeout
1207
1245
  #
1208
1246
  # @return [nil, [String, String]]
1209
1247
  # - `nil` when the operation timed out
@@ -1217,7 +1255,7 @@ class Redis
1217
1255
  # @param [String, Array<String>] keys one or more keys to perform the
1218
1256
  # blocking pop on
1219
1257
  # @param [Hash] options
1220
- # - `:timeout => Fixnum`: timeout in seconds, defaults to no timeout
1258
+ # - `:timeout => Integer`: timeout in seconds, defaults to no timeout
1221
1259
  #
1222
1260
  # @return [nil, [String, String]]
1223
1261
  # - `nil` when the operation timed out
@@ -1234,20 +1272,12 @@ class Redis
1234
1272
  # @param [String] source source key
1235
1273
  # @param [String] destination destination key
1236
1274
  # @param [Hash] options
1237
- # - `:timeout => Fixnum`: timeout in seconds, defaults to no timeout
1275
+ # - `:timeout => Integer`: timeout in seconds, defaults to no timeout
1238
1276
  #
1239
1277
  # @return [nil, String]
1240
1278
  # - `nil` when the operation timed out
1241
1279
  # - the element was popped and pushed otherwise
1242
- def brpoplpush(source, destination, options = {})
1243
- case options
1244
- when Integer
1245
- # Issue deprecation notice in obnoxious mode...
1246
- options = { :timeout => options }
1247
- end
1248
-
1249
- timeout = options[:timeout] || 0
1250
-
1280
+ def brpoplpush(source, destination, deprecated_timeout = 0, timeout: deprecated_timeout)
1251
1281
  synchronize do |client|
1252
1282
  command = [:brpoplpush, source, destination, timeout]
1253
1283
  timeout += client.timeout if timeout > 0
@@ -1258,7 +1288,7 @@ class Redis
1258
1288
  # Get an element from a list by its index.
1259
1289
  #
1260
1290
  # @param [String] key
1261
- # @param [Fixnum] index
1291
+ # @param [Integer] index
1262
1292
  # @return [String]
1263
1293
  def lindex(key, index)
1264
1294
  synchronize do |client|
@@ -1272,7 +1302,7 @@ class Redis
1272
1302
  # @param [String, Symbol] where `BEFORE` or `AFTER`
1273
1303
  # @param [String] pivot reference element
1274
1304
  # @param [String] value
1275
- # @return [Fixnum] length of the list after the insert operation, or `-1`
1305
+ # @return [Integer] length of the list after the insert operation, or `-1`
1276
1306
  # when the element `pivot` was not found
1277
1307
  def linsert(key, where, pivot, value)
1278
1308
  synchronize do |client|
@@ -1283,8 +1313,8 @@ class Redis
1283
1313
  # Get a range of elements from a list.
1284
1314
  #
1285
1315
  # @param [String] key
1286
- # @param [Fixnum] start start index
1287
- # @param [Fixnum] stop stop index
1316
+ # @param [Integer] start start index
1317
+ # @param [Integer] stop stop index
1288
1318
  # @return [Array<String>]
1289
1319
  def lrange(key, start, stop)
1290
1320
  synchronize do |client|
@@ -1295,12 +1325,12 @@ class Redis
1295
1325
  # Remove elements from a list.
1296
1326
  #
1297
1327
  # @param [String] key
1298
- # @param [Fixnum] count number of elements to remove. Use a positive
1328
+ # @param [Integer] count number of elements to remove. Use a positive
1299
1329
  # value to remove the first `count` occurrences of `value`. A negative
1300
1330
  # value to remove the last `count` occurrences of `value`. Or zero, to
1301
1331
  # remove all occurrences of `value` from the list.
1302
1332
  # @param [String] value
1303
- # @return [Fixnum] the number of removed elements
1333
+ # @return [Integer] the number of removed elements
1304
1334
  def lrem(key, count, value)
1305
1335
  synchronize do |client|
1306
1336
  client.call([:lrem, key, count, value])
@@ -1310,7 +1340,7 @@ class Redis
1310
1340
  # Set the value of an element in a list by its index.
1311
1341
  #
1312
1342
  # @param [String] key
1313
- # @param [Fixnum] index
1343
+ # @param [Integer] index
1314
1344
  # @param [String] value
1315
1345
  # @return [String] `OK`
1316
1346
  def lset(key, index, value)
@@ -1322,8 +1352,8 @@ class Redis
1322
1352
  # Trim a list to the specified range.
1323
1353
  #
1324
1354
  # @param [String] key
1325
- # @param [Fixnum] start start index
1326
- # @param [Fixnum] stop stop index
1355
+ # @param [Integer] start start index
1356
+ # @param [Integer] stop stop index
1327
1357
  # @return [String] `OK`
1328
1358
  def ltrim(key, start, stop)
1329
1359
  synchronize do |client|
@@ -1334,7 +1364,7 @@ class Redis
1334
1364
  # Get the number of members in a set.
1335
1365
  #
1336
1366
  # @param [String] key
1337
- # @return [Fixnum]
1367
+ # @return [Integer]
1338
1368
  def scard(key)
1339
1369
  synchronize do |client|
1340
1370
  client.call([:scard, key])
@@ -1345,8 +1375,8 @@ class Redis
1345
1375
  #
1346
1376
  # @param [String] key
1347
1377
  # @param [String, Array<String>] member one member, or array of members
1348
- # @return [Boolean, Fixnum] `Boolean` when a single member is specified,
1349
- # holding whether or not adding the member succeeded, or `Fixnum` when an
1378
+ # @return [Boolean, Integer] `Boolean` when a single member is specified,
1379
+ # holding whether or not adding the member succeeded, or `Integer` when an
1350
1380
  # array of members is specified, holding the number of members that were
1351
1381
  # successfully added
1352
1382
  def sadd(key, member)
@@ -1367,8 +1397,8 @@ class Redis
1367
1397
  #
1368
1398
  # @param [String] key
1369
1399
  # @param [String, Array<String>] member one member, or array of members
1370
- # @return [Boolean, Fixnum] `Boolean` when a single member is specified,
1371
- # holding whether or not removing the member succeeded, or `Fixnum` when an
1400
+ # @return [Boolean, Integer] `Boolean` when a single member is specified,
1401
+ # holding whether or not removing the member succeeded, or `Integer` when an
1372
1402
  # array of members is specified, holding the number of members that were
1373
1403
  # successfully removed
1374
1404
  def srem(key, member)
@@ -1389,7 +1419,7 @@ class Redis
1389
1419
  #
1390
1420
  # @param [String] key
1391
1421
  # @return [String]
1392
- # @param [Fixnum] count
1422
+ # @param [Integer] count
1393
1423
  def spop(key, count = nil)
1394
1424
  synchronize do |client|
1395
1425
  if count.nil?
@@ -1403,7 +1433,7 @@ class Redis
1403
1433
  # Get one or more random members from a set.
1404
1434
  #
1405
1435
  # @param [String] key
1406
- # @param [Fixnum] count
1436
+ # @param [Integer] count
1407
1437
  # @return [String]
1408
1438
  def srandmember(key, count = nil)
1409
1439
  synchronize do |client|
@@ -1454,7 +1484,7 @@ class Redis
1454
1484
  # @return [Array<String>] members in the difference
1455
1485
  def sdiff(*keys)
1456
1486
  synchronize do |client|
1457
- client.call([:sdiff] + keys)
1487
+ client.call([:sdiff, *keys])
1458
1488
  end
1459
1489
  end
1460
1490
 
@@ -1462,10 +1492,10 @@ class Redis
1462
1492
  #
1463
1493
  # @param [String] destination destination key
1464
1494
  # @param [String, Array<String>] keys keys pointing to sets to subtract
1465
- # @return [Fixnum] number of elements in the resulting set
1495
+ # @return [Integer] number of elements in the resulting set
1466
1496
  def sdiffstore(destination, *keys)
1467
1497
  synchronize do |client|
1468
- client.call([:sdiffstore, destination] + keys)
1498
+ client.call([:sdiffstore, destination, *keys])
1469
1499
  end
1470
1500
  end
1471
1501
 
@@ -1475,7 +1505,7 @@ class Redis
1475
1505
  # @return [Array<String>] members in the intersection
1476
1506
  def sinter(*keys)
1477
1507
  synchronize do |client|
1478
- client.call([:sinter] + keys)
1508
+ client.call([:sinter, *keys])
1479
1509
  end
1480
1510
  end
1481
1511
 
@@ -1483,10 +1513,10 @@ class Redis
1483
1513
  #
1484
1514
  # @param [String] destination destination key
1485
1515
  # @param [String, Array<String>] keys keys pointing to sets to intersect
1486
- # @return [Fixnum] number of elements in the resulting set
1516
+ # @return [Integer] number of elements in the resulting set
1487
1517
  def sinterstore(destination, *keys)
1488
1518
  synchronize do |client|
1489
- client.call([:sinterstore, destination] + keys)
1519
+ client.call([:sinterstore, destination, *keys])
1490
1520
  end
1491
1521
  end
1492
1522
 
@@ -1496,7 +1526,7 @@ class Redis
1496
1526
  # @return [Array<String>] members in the union
1497
1527
  def sunion(*keys)
1498
1528
  synchronize do |client|
1499
- client.call([:sunion] + keys)
1529
+ client.call([:sunion, *keys])
1500
1530
  end
1501
1531
  end
1502
1532
 
@@ -1504,10 +1534,10 @@ class Redis
1504
1534
  #
1505
1535
  # @param [String] destination destination key
1506
1536
  # @param [String, Array<String>] keys keys pointing to sets to unify
1507
- # @return [Fixnum] number of elements in the resulting set
1537
+ # @return [Integer] number of elements in the resulting set
1508
1538
  def sunionstore(destination, *keys)
1509
1539
  synchronize do |client|
1510
- client.call([:sunionstore, destination] + keys)
1540
+ client.call([:sunionstore, destination, *keys])
1511
1541
  end
1512
1542
  end
1513
1543
 
@@ -1518,7 +1548,7 @@ class Redis
1518
1548
  # # => 4
1519
1549
  #
1520
1550
  # @param [String] key
1521
- # @return [Fixnum]
1551
+ # @return [Integer]
1522
1552
  def zcard(key)
1523
1553
  synchronize do |client|
1524
1554
  client.call([:zcard, key])
@@ -1549,38 +1579,27 @@ class Redis
1549
1579
  # - `:incr => true`: When this option is specified ZADD acts like
1550
1580
  # ZINCRBY; only one score-element pair can be specified in this mode
1551
1581
  #
1552
- # @return [Boolean, Fixnum, Float]
1582
+ # @return [Boolean, Integer, Float]
1553
1583
  # - `Boolean` when a single pair is specified, holding whether or not it was
1554
1584
  # **added** to the sorted set.
1555
- # - `Fixnum` when an array of pairs is specified, holding the number of
1585
+ # - `Integer` when an array of pairs is specified, holding the number of
1556
1586
  # pairs that were **added** to the sorted set.
1557
1587
  # - `Float` when option :incr is specified, holding the score of the member
1558
1588
  # after incrementing it.
1559
- def zadd(key, *args) #, options
1560
- zadd_options = []
1561
- if args.last.is_a?(Hash)
1562
- options = args.pop
1563
-
1564
- nx = options[:nx]
1565
- zadd_options << "NX" if nx
1566
-
1567
- xx = options[:xx]
1568
- zadd_options << "XX" if xx
1569
-
1570
- ch = options[:ch]
1571
- zadd_options << "CH" if ch
1572
-
1573
- incr = options[:incr]
1574
- zadd_options << "INCR" if incr
1575
- end
1589
+ def zadd(key, *args, nx: nil, xx: nil, ch: nil, incr: nil)
1590
+ command = [:zadd, key]
1591
+ command << "NX" if nx
1592
+ command << "XX" if xx
1593
+ command << "CH" if ch
1594
+ command << "INCR" if incr
1576
1595
 
1577
1596
  synchronize do |client|
1578
1597
  if args.size == 1 && args[0].is_a?(Array)
1579
1598
  # Variadic: return float if INCR, integer if !INCR
1580
- client.call([:zadd, key] + zadd_options + args[0], &(incr ? Floatify : nil))
1599
+ client.call(command + args[0], &(incr ? Floatify : nil))
1581
1600
  elsif args.size == 2
1582
1601
  # Single pair: return float if INCR, boolean if !INCR
1583
- client.call([:zadd, key] + zadd_options + args, &(incr ? Floatify : Boolify))
1602
+ client.call(command + args, &(incr ? Floatify : Boolify))
1584
1603
  else
1585
1604
  raise ArgumentError, "wrong number of arguments"
1586
1605
  end
@@ -1615,10 +1634,10 @@ class Redis
1615
1634
  # - a single member
1616
1635
  # - an array of members
1617
1636
  #
1618
- # @return [Boolean, Fixnum]
1637
+ # @return [Boolean, Integer]
1619
1638
  # - `Boolean` when a single member is specified, holding whether or not it
1620
1639
  # was removed from the sorted set
1621
- # - `Fixnum` when an array of pairs is specified, holding the number of
1640
+ # - `Integer` when an array of pairs is specified, holding the number of
1622
1641
  # members that were removed to the sorted set
1623
1642
  def zrem(key, member)
1624
1643
  synchronize do |client|
@@ -1743,18 +1762,16 @@ class Redis
1743
1762
  # # => [["a", 32.0], ["b", 64.0]]
1744
1763
  #
1745
1764
  # @param [String] key
1746
- # @param [Fixnum] start start index
1747
- # @param [Fixnum] stop stop index
1765
+ # @param [Integer] start start index
1766
+ # @param [Integer] stop stop index
1748
1767
  # @param [Hash] options
1749
1768
  # - `:with_scores => true`: include scores in output
1750
1769
  #
1751
1770
  # @return [Array<String>, Array<[String, Float]>]
1752
1771
  # - when `:with_scores` is not specified, an array of members
1753
1772
  # - when `:with_scores` is specified, an array with `[member, score]` pairs
1754
- def zrange(key, start, stop, options = {})
1755
- args = []
1756
-
1757
- with_scores = options[:with_scores] || options[:withscores]
1773
+ def zrange(key, start, stop, withscores: false, with_scores: withscores)
1774
+ args = [:zrange, key, start, stop]
1758
1775
 
1759
1776
  if with_scores
1760
1777
  args << "WITHSCORES"
@@ -1762,7 +1779,7 @@ class Redis
1762
1779
  end
1763
1780
 
1764
1781
  synchronize do |client|
1765
- client.call([:zrange, key, start, stop] + args, &block)
1782
+ client.call(args, &block)
1766
1783
  end
1767
1784
  end
1768
1785
 
@@ -1777,10 +1794,8 @@ class Redis
1777
1794
  # # => [["b", 64.0], ["a", 32.0]]
1778
1795
  #
1779
1796
  # @see #zrange
1780
- def zrevrange(key, start, stop, options = {})
1781
- args = []
1782
-
1783
- with_scores = options[:with_scores] || options[:withscores]
1797
+ def zrevrange(key, start, stop, withscores: false, with_scores: withscores)
1798
+ args = [:zrevrange, key, start, stop]
1784
1799
 
1785
1800
  if with_scores
1786
1801
  args << "WITHSCORES"
@@ -1788,7 +1803,7 @@ class Redis
1788
1803
  end
1789
1804
 
1790
1805
  synchronize do |client|
1791
- client.call([:zrevrange, key, start, stop] + args, &block)
1806
+ client.call(args, &block)
1792
1807
  end
1793
1808
  end
1794
1809
 
@@ -1796,7 +1811,7 @@ class Redis
1796
1811
  #
1797
1812
  # @param [String] key
1798
1813
  # @param [String] member
1799
- # @return [Fixnum]
1814
+ # @return [Integer]
1800
1815
  def zrank(key, member)
1801
1816
  synchronize do |client|
1802
1817
  client.call([:zrank, key, member])
@@ -1808,7 +1823,7 @@ class Redis
1808
1823
  #
1809
1824
  # @param [String] key
1810
1825
  # @param [String] member
1811
- # @return [Fixnum]
1826
+ # @return [Integer]
1812
1827
  def zrevrank(key, member)
1813
1828
  synchronize do |client|
1814
1829
  client.call([:zrevrank, key, member])
@@ -1825,9 +1840,9 @@ class Redis
1825
1840
  # # => 5
1826
1841
  #
1827
1842
  # @param [String] key
1828
- # @param [Fixnum] start start index
1829
- # @param [Fixnum] stop stop index
1830
- # @return [Fixnum] number of members that were removed
1843
+ # @param [Integer] start start index
1844
+ # @param [Integer] stop stop index
1845
+ # @return [Integer] number of members that were removed
1831
1846
  def zremrangebyrank(key, start, stop)
1832
1847
  synchronize do |client|
1833
1848
  client.call([:zremrangebyrank, key, start, stop])
@@ -1851,7 +1866,7 @@ class Redis
1851
1866
  # - inclusive maximum is specified by prefixing `(`
1852
1867
  # - exclusive maximum is specified by prefixing `[`
1853
1868
  #
1854
- # @return [Fixnum] number of members within the specified lexicographical range
1869
+ # @return [Integer] number of members within the specified lexicographical range
1855
1870
  def zlexcount(key, min, max)
1856
1871
  synchronize do |client|
1857
1872
  client.call([:zlexcount, key, min, max])
@@ -1879,14 +1894,16 @@ class Redis
1879
1894
  # `count` members
1880
1895
  #
1881
1896
  # @return [Array<String>, Array<[String, Float]>]
1882
- def zrangebylex(key, min, max, options = {})
1883
- args = []
1897
+ def zrangebylex(key, min, max, limit: nil)
1898
+ args = [:zrangebylex, key, min, max]
1884
1899
 
1885
- limit = options[:limit]
1886
- args.concat(["LIMIT"] + limit) if limit
1900
+ if limit
1901
+ args << "LIMIT"
1902
+ args.concat(limit)
1903
+ end
1887
1904
 
1888
1905
  synchronize do |client|
1889
- client.call([:zrangebylex, key, min, max] + args)
1906
+ client.call(args)
1890
1907
  end
1891
1908
  end
1892
1909
 
@@ -1901,14 +1918,16 @@ class Redis
1901
1918
  # # => ["abbygail", "abby"]
1902
1919
  #
1903
1920
  # @see #zrangebylex
1904
- def zrevrangebylex(key, max, min, options = {})
1905
- args = []
1921
+ def zrevrangebylex(key, max, min, limit: nil)
1922
+ args = [:zrevrangebylex, key, max, min]
1906
1923
 
1907
- limit = options[:limit]
1908
- args.concat(["LIMIT"] + limit) if limit
1924
+ if limit
1925
+ args << "LIMIT"
1926
+ args.concat(limit)
1927
+ end
1909
1928
 
1910
1929
  synchronize do |client|
1911
- client.call([:zrevrangebylex, key, max, min] + args)
1930
+ client.call(args)
1912
1931
  end
1913
1932
  end
1914
1933
 
@@ -1939,21 +1958,21 @@ class Redis
1939
1958
  # @return [Array<String>, Array<[String, Float]>]
1940
1959
  # - when `:with_scores` is not specified, an array of members
1941
1960
  # - when `:with_scores` is specified, an array with `[member, score]` pairs
1942
- def zrangebyscore(key, min, max, options = {})
1943
- args = []
1944
-
1945
- with_scores = options[:with_scores] || options[:withscores]
1961
+ def zrangebyscore(key, min, max, withscores: false, with_scores: withscores, limit: nil)
1962
+ args = [:zrangebyscore, key, min, max]
1946
1963
 
1947
1964
  if with_scores
1948
1965
  args << "WITHSCORES"
1949
1966
  block = FloatifyPairs
1950
1967
  end
1951
1968
 
1952
- limit = options[:limit]
1953
- args.concat(["LIMIT"] + limit) if limit
1969
+ if limit
1970
+ args << "LIMIT"
1971
+ args.concat(limit)
1972
+ end
1954
1973
 
1955
1974
  synchronize do |client|
1956
- client.call([:zrangebyscore, key, min, max] + args, &block)
1975
+ client.call(args, &block)
1957
1976
  end
1958
1977
  end
1959
1978
 
@@ -1971,21 +1990,21 @@ class Redis
1971
1990
  # # => [["b", 64.0], ["a", 32.0]]
1972
1991
  #
1973
1992
  # @see #zrangebyscore
1974
- def zrevrangebyscore(key, max, min, options = {})
1975
- args = []
1976
-
1977
- with_scores = options[:with_scores] || options[:withscores]
1993
+ def zrevrangebyscore(key, max, min, withscores: false, with_scores: withscores, limit: nil)
1994
+ args = [:zrevrangebyscore, key, max, min]
1978
1995
 
1979
1996
  if with_scores
1980
- args << ["WITHSCORES"]
1997
+ args << "WITHSCORES"
1981
1998
  block = FloatifyPairs
1982
1999
  end
1983
2000
 
1984
- limit = options[:limit]
1985
- args.concat(["LIMIT"] + limit) if limit
2001
+ if limit
2002
+ args << "LIMIT"
2003
+ args.concat(limit)
2004
+ end
1986
2005
 
1987
2006
  synchronize do |client|
1988
- client.call([:zrevrangebyscore, key, max, min] + args, &block)
2007
+ client.call(args, &block)
1989
2008
  end
1990
2009
  end
1991
2010
 
@@ -2005,7 +2024,7 @@ class Redis
2005
2024
  # @param [String] max
2006
2025
  # - inclusive maximum score is specified verbatim
2007
2026
  # - exclusive maximum score is specified by prefixing `(`
2008
- # @return [Fixnum] number of members that were removed
2027
+ # @return [Integer] number of members that were removed
2009
2028
  def zremrangebyscore(key, min, max)
2010
2029
  synchronize do |client|
2011
2030
  client.call([:zremrangebyscore, key, min, max])
@@ -2028,7 +2047,7 @@ class Redis
2028
2047
  # @param [String] max
2029
2048
  # - inclusive maximum score is specified verbatim
2030
2049
  # - exclusive maximum score is specified by prefixing `(`
2031
- # @return [Fixnum] number of members in within the specified range
2050
+ # @return [Integer] number of members in within the specified range
2032
2051
  def zcount(key, min, max)
2033
2052
  synchronize do |client|
2034
2053
  client.call([:zcount, key, min, max])
@@ -2048,18 +2067,19 @@ class Redis
2048
2067
  # - `:weights => [Float, Float, ...]`: weights to associate with source
2049
2068
  # sorted sets
2050
2069
  # - `:aggregate => String`: aggregate function to use (sum, min, max, ...)
2051
- # @return [Fixnum] number of elements in the resulting sorted set
2052
- def zinterstore(destination, keys, options = {})
2053
- args = []
2070
+ # @return [Integer] number of elements in the resulting sorted set
2071
+ def zinterstore(destination, keys, weights: nil, aggregate: nil)
2072
+ args = [:zinterstore, destination, keys.size, *keys]
2054
2073
 
2055
- weights = options[:weights]
2056
- args.concat(["WEIGHTS"] + weights) if weights
2074
+ if weights
2075
+ args << "WEIGHTS"
2076
+ args.concat(weights)
2077
+ end
2057
2078
 
2058
- aggregate = options[:aggregate]
2059
- args.concat(["AGGREGATE", aggregate]) if aggregate
2079
+ args << "AGGREGATE" << aggregate if aggregate
2060
2080
 
2061
2081
  synchronize do |client|
2062
- client.call([:zinterstore, destination, keys.size] + keys + args)
2082
+ client.call(args)
2063
2083
  end
2064
2084
  end
2065
2085
 
@@ -2075,40 +2095,46 @@ class Redis
2075
2095
  # - `:weights => [Float, Float, ...]`: weights to associate with source
2076
2096
  # sorted sets
2077
2097
  # - `:aggregate => String`: aggregate function to use (sum, min, max, ...)
2078
- # @return [Fixnum] number of elements in the resulting sorted set
2079
- def zunionstore(destination, keys, options = {})
2080
- args = []
2098
+ # @return [Integer] number of elements in the resulting sorted set
2099
+ def zunionstore(destination, keys, weights: nil, aggregate: nil)
2100
+ args = [:zunionstore, destination, keys.size, *keys]
2081
2101
 
2082
- weights = options[:weights]
2083
- args.concat(["WEIGHTS"] + weights) if weights
2102
+ if weights
2103
+ args << "WEIGHTS"
2104
+ args.concat(weights)
2105
+ end
2084
2106
 
2085
- aggregate = options[:aggregate]
2086
- args.concat(["AGGREGATE", aggregate]) if aggregate
2107
+ args << "AGGREGATE" << aggregate if aggregate
2087
2108
 
2088
2109
  synchronize do |client|
2089
- client.call([:zunionstore, destination, keys.size] + keys + args)
2110
+ client.call(args)
2090
2111
  end
2091
2112
  end
2092
2113
 
2093
2114
  # Get the number of fields in a hash.
2094
2115
  #
2095
2116
  # @param [String] key
2096
- # @return [Fixnum] number of fields in the hash
2117
+ # @return [Integer] number of fields in the hash
2097
2118
  def hlen(key)
2098
2119
  synchronize do |client|
2099
2120
  client.call([:hlen, key])
2100
2121
  end
2101
2122
  end
2102
2123
 
2103
- # Set the string value of a hash field.
2124
+ # Set one or more hash values.
2125
+ #
2126
+ # @example
2127
+ # redis.hset("hash", "f1", "v1", "f2", "v2") # => 2
2128
+ # redis.hset("hash", { "f1" => "v1", "f2" => "v2" }) # => 2
2104
2129
  #
2105
2130
  # @param [String] key
2106
- # @param [String] field
2107
- # @param [String] value
2108
- # @return [Boolean] whether or not the field was **added** to the hash
2109
- def hset(key, field, value)
2131
+ # @param [Array<String> | Hash<String, String>] attrs array or hash of fields and values
2132
+ # @return [Integer] The number of fields that were added to the hash
2133
+ def hset(key, *attrs)
2134
+ attrs = attrs.first.flatten if attrs.size == 1 && attrs.first.is_a?(Hash)
2135
+
2110
2136
  synchronize do |client|
2111
- client.call([:hset, key, field, value], &Boolify)
2137
+ client.call([:hset, key, *attrs])
2112
2138
  end
2113
2139
  end
2114
2140
 
@@ -2197,7 +2223,7 @@ class Redis
2197
2223
  # @see #hmget
2198
2224
  def mapped_hmget(key, *fields)
2199
2225
  hmget(key, *fields) do |reply|
2200
- if reply.kind_of?(Array)
2226
+ if reply.is_a?(Array)
2201
2227
  Hash[fields.zip(reply)]
2202
2228
  else
2203
2229
  reply
@@ -2209,7 +2235,7 @@ class Redis
2209
2235
  #
2210
2236
  # @param [String] key
2211
2237
  # @param [String, Array<String>] field
2212
- # @return [Fixnum] the number of fields that were removed from the hash
2238
+ # @return [Integer] the number of fields that were removed from the hash
2213
2239
  def hdel(key, *fields)
2214
2240
  synchronize do |client|
2215
2241
  client.call([:hdel, key, *fields])
@@ -2231,8 +2257,8 @@ class Redis
2231
2257
  #
2232
2258
  # @param [String] key
2233
2259
  # @param [String] field
2234
- # @param [Fixnum] increment
2235
- # @return [Fixnum] value of the field after incrementing it
2260
+ # @param [Integer] increment
2261
+ # @return [Integer] value of the field after incrementing it
2236
2262
  def hincrby(key, field, increment)
2237
2263
  synchronize do |client|
2238
2264
  client.call([:hincrby, key, field, increment])
@@ -2290,20 +2316,21 @@ class Redis
2290
2316
 
2291
2317
  def subscribed?
2292
2318
  synchronize do |client|
2293
- client.kind_of? SubscribedClient
2319
+ client.is_a? SubscribedClient
2294
2320
  end
2295
2321
  end
2296
2322
 
2297
2323
  # Listen for messages published to the given channels.
2298
2324
  def subscribe(*channels, &block)
2299
- synchronize do |client|
2325
+ synchronize do |_client|
2300
2326
  _subscription(:subscribe, 0, channels, block)
2301
2327
  end
2302
2328
  end
2303
2329
 
2304
- # Listen for messages published to the given channels. Throw a timeout error if there is no messages for a timeout period.
2330
+ # Listen for messages published to the given channels. Throw a timeout error
2331
+ # if there is no messages for a timeout period.
2305
2332
  def subscribe_with_timeout(timeout, *channels, &block)
2306
- synchronize do |client|
2333
+ synchronize do |_client|
2307
2334
  _subscription(:subscribe_with_timeout, timeout, channels, block)
2308
2335
  end
2309
2336
  end
@@ -2311,21 +2338,23 @@ class Redis
2311
2338
  # Stop listening for messages posted to the given channels.
2312
2339
  def unsubscribe(*channels)
2313
2340
  synchronize do |client|
2314
- raise RuntimeError, "Can't unsubscribe if not subscribed." unless subscribed?
2341
+ raise "Can't unsubscribe if not subscribed." unless subscribed?
2342
+
2315
2343
  client.unsubscribe(*channels)
2316
2344
  end
2317
2345
  end
2318
2346
 
2319
2347
  # Listen for messages published to channels matching the given patterns.
2320
2348
  def psubscribe(*channels, &block)
2321
- synchronize do |client|
2349
+ synchronize do |_client|
2322
2350
  _subscription(:psubscribe, 0, channels, block)
2323
2351
  end
2324
2352
  end
2325
2353
 
2326
- # Listen for messages published to channels matching the given patterns. Throw a timeout error if there is no messages for a timeout period.
2354
+ # Listen for messages published to channels matching the given patterns.
2355
+ # Throw a timeout error if there is no messages for a timeout period.
2327
2356
  def psubscribe_with_timeout(timeout, *channels, &block)
2328
- synchronize do |client|
2357
+ synchronize do |_client|
2329
2358
  _subscription(:psubscribe_with_timeout, timeout, channels, block)
2330
2359
  end
2331
2360
  end
@@ -2333,7 +2362,8 @@ class Redis
2333
2362
  # Stop listening for messages posted to channels matching the given patterns.
2334
2363
  def punsubscribe(*channels)
2335
2364
  synchronize do |client|
2336
- raise RuntimeError, "Can't unsubscribe if not subscribed." unless subscribed?
2365
+ raise "Can't unsubscribe if not subscribed." unless subscribed?
2366
+
2337
2367
  client.punsubscribe(*channels)
2338
2368
  end
2339
2369
  end
@@ -2378,7 +2408,7 @@ class Redis
2378
2408
  # @see #multi
2379
2409
  def watch(*keys)
2380
2410
  synchronize do |client|
2381
- res = client.call([:watch] + keys)
2411
+ res = client.call([:watch, *keys])
2382
2412
 
2383
2413
  if block_given?
2384
2414
  begin
@@ -2408,7 +2438,7 @@ class Redis
2408
2438
  end
2409
2439
 
2410
2440
  def pipelined
2411
- synchronize do |client|
2441
+ synchronize do |_client|
2412
2442
  begin
2413
2443
  pipeline = Pipeline.new(@client)
2414
2444
  original, @client = @client, pipeline
@@ -2608,18 +2638,12 @@ class Redis
2608
2638
  _eval(:evalsha, args)
2609
2639
  end
2610
2640
 
2611
- def _scan(command, cursor, args, options = {}, &block)
2641
+ def _scan(command, cursor, args, match: nil, count: nil, &block)
2612
2642
  # SSCAN/ZSCAN/HSCAN already prepend the key to +args+.
2613
2643
 
2614
2644
  args << cursor
2615
-
2616
- if match = options[:match]
2617
- args.concat(["MATCH", match])
2618
- end
2619
-
2620
- if count = options[:count]
2621
- args.concat(["COUNT", count])
2622
- end
2645
+ args << "MATCH" << match if match
2646
+ args << "COUNT" << count if count
2623
2647
 
2624
2648
  synchronize do |client|
2625
2649
  client.call([command] + args, &block)
@@ -2641,8 +2665,8 @@ class Redis
2641
2665
  # - `:count => Integer`: return count keys at most per iteration
2642
2666
  #
2643
2667
  # @return [String, Array<String>] the next cursor and all found keys
2644
- def scan(cursor, options={})
2645
- _scan(:scan, cursor, [], options)
2668
+ def scan(cursor, **options)
2669
+ _scan(:scan, cursor, [], **options)
2646
2670
  end
2647
2671
 
2648
2672
  # Scan the keyspace
@@ -2660,11 +2684,12 @@ class Redis
2660
2684
  # - `:count => Integer`: return count keys at most per iteration
2661
2685
  #
2662
2686
  # @return [Enumerator] an enumerator for all found keys
2663
- def scan_each(options={}, &block)
2664
- return to_enum(:scan_each, options) unless block_given?
2687
+ def scan_each(**options, &block)
2688
+ return to_enum(:scan_each, **options) unless block_given?
2689
+
2665
2690
  cursor = 0
2666
2691
  loop do
2667
- cursor, keys = scan(cursor, options)
2692
+ cursor, keys = scan(cursor, **options)
2668
2693
  keys.each(&block)
2669
2694
  break if cursor == "0"
2670
2695
  end
@@ -2681,8 +2706,8 @@ class Redis
2681
2706
  # - `:count => Integer`: return count keys at most per iteration
2682
2707
  #
2683
2708
  # @return [String, Array<[String, String]>] the next cursor and all found keys
2684
- def hscan(key, cursor, options={})
2685
- _scan(:hscan, cursor, [key], options) do |reply|
2709
+ def hscan(key, cursor, **options)
2710
+ _scan(:hscan, cursor, [key], **options) do |reply|
2686
2711
  [reply[0], reply[1].each_slice(2).to_a]
2687
2712
  end
2688
2713
  end
@@ -2698,11 +2723,12 @@ class Redis
2698
2723
  # - `:count => Integer`: return count keys at most per iteration
2699
2724
  #
2700
2725
  # @return [Enumerator] an enumerator for all found keys
2701
- def hscan_each(key, options={}, &block)
2702
- return to_enum(:hscan_each, key, options) unless block_given?
2726
+ def hscan_each(key, **options, &block)
2727
+ return to_enum(:hscan_each, key, **options) unless block_given?
2728
+
2703
2729
  cursor = 0
2704
2730
  loop do
2705
- cursor, values = hscan(key, cursor, options)
2731
+ cursor, values = hscan(key, cursor, **options)
2706
2732
  values.each(&block)
2707
2733
  break if cursor == "0"
2708
2734
  end
@@ -2720,8 +2746,8 @@ class Redis
2720
2746
  #
2721
2747
  # @return [String, Array<[String, Float]>] the next cursor and all found
2722
2748
  # members and scores
2723
- def zscan(key, cursor, options={})
2724
- _scan(:zscan, cursor, [key], options) do |reply|
2749
+ def zscan(key, cursor, **options)
2750
+ _scan(:zscan, cursor, [key], **options) do |reply|
2725
2751
  [reply[0], FloatifyPairs.call(reply[1])]
2726
2752
  end
2727
2753
  end
@@ -2737,11 +2763,12 @@ class Redis
2737
2763
  # - `:count => Integer`: return count keys at most per iteration
2738
2764
  #
2739
2765
  # @return [Enumerator] an enumerator for all found scores and members
2740
- def zscan_each(key, options={}, &block)
2741
- return to_enum(:zscan_each, key, options) unless block_given?
2766
+ def zscan_each(key, **options, &block)
2767
+ return to_enum(:zscan_each, key, **options) unless block_given?
2768
+
2742
2769
  cursor = 0
2743
2770
  loop do
2744
- cursor, values = zscan(key, cursor, options)
2771
+ cursor, values = zscan(key, cursor, **options)
2745
2772
  values.each(&block)
2746
2773
  break if cursor == "0"
2747
2774
  end
@@ -2758,8 +2785,8 @@ class Redis
2758
2785
  # - `:count => Integer`: return count keys at most per iteration
2759
2786
  #
2760
2787
  # @return [String, Array<String>] the next cursor and all found members
2761
- def sscan(key, cursor, options={})
2762
- _scan(:sscan, cursor, [key], options)
2788
+ def sscan(key, cursor, **options)
2789
+ _scan(:sscan, cursor, [key], **options)
2763
2790
  end
2764
2791
 
2765
2792
  # Scan a set
@@ -2773,11 +2800,12 @@ class Redis
2773
2800
  # - `:count => Integer`: return count keys at most per iteration
2774
2801
  #
2775
2802
  # @return [Enumerator] an enumerator for all keys in the set
2776
- def sscan_each(key, options={}, &block)
2777
- return to_enum(:sscan_each, key, options) unless block_given?
2803
+ def sscan_each(key, **options, &block)
2804
+ return to_enum(:sscan_each, key, **options) unless block_given?
2805
+
2778
2806
  cursor = 0
2779
2807
  loop do
2780
- cursor, keys = sscan(key, cursor, options)
2808
+ cursor, keys = sscan(key, cursor, **options)
2781
2809
  keys.each(&block)
2782
2810
  break if cursor == "0"
2783
2811
  end
@@ -2800,7 +2828,7 @@ class Redis
2800
2828
  # union of the HyperLogLogs contained in the keys.
2801
2829
  #
2802
2830
  # @param [String, Array<String>] keys
2803
- # @return [Fixnum]
2831
+ # @return [Integer]
2804
2832
  def pfcount(*keys)
2805
2833
  synchronize do |client|
2806
2834
  client.call([:pfcount] + keys)
@@ -2823,7 +2851,7 @@ class Redis
2823
2851
  #
2824
2852
  # @param [String] key
2825
2853
  # @param [Array] member arguemnts for member or members: longitude, latitude, name
2826
- # @return [Intger] number of elements added to the sorted set
2854
+ # @return [Integer] number of elements added to the sorted set
2827
2855
  def geoadd(key, *member)
2828
2856
  synchronize do |client|
2829
2857
  client.call([:geoadd, key, *member])
@@ -2841,12 +2869,12 @@ class Redis
2841
2869
  end
2842
2870
  end
2843
2871
 
2844
-
2845
2872
  # Query a sorted set representing a geospatial index to fetch members matching a
2846
2873
  # given maximum distance from a point
2847
2874
  #
2848
2875
  # @param [Array] args key, longitude, latitude, radius, unit(m|km|ft|mi)
2849
- # @param ['asc', 'desc'] sort sort returned items from the nearest to the farthest or the farthest to the nearest relative to the center
2876
+ # @param ['asc', 'desc'] sort sort returned items from the nearest to the farthest
2877
+ # or the farthest to the nearest relative to the center
2850
2878
  # @param [Integer] count limit the results to the first N matching items
2851
2879
  # @param ['WITHDIST', 'WITHCOORD', 'WITHHASH'] options to return additional information
2852
2880
  # @return [Array<String>] may be changed with `options`
@@ -2863,7 +2891,8 @@ class Redis
2863
2891
  # given maximum distance from an already existing member
2864
2892
  #
2865
2893
  # @param [Array] args key, member, radius, unit(m|km|ft|mi)
2866
- # @param ['asc', 'desc'] sort sort returned items from the nearest to the farthest or the farthest to the nearest relative to the center
2894
+ # @param ['asc', 'desc'] sort sort returned items from the nearest to the farthest or the farthest
2895
+ # to the nearest relative to the center
2867
2896
  # @param [Integer] count limit the results to the first N matching items
2868
2897
  # @param ['WITHDIST', 'WITHCOORD', 'WITHHASH'] options to return additional information
2869
2898
  # @return [Array<String>] may be changed with `options`
@@ -2880,7 +2909,8 @@ class Redis
2880
2909
  #
2881
2910
  # @param [String] key
2882
2911
  # @param [String, Array<String>] member one member or array of members
2883
- # @return [Array<Array<String>, nil>] returns array of elements, where each element is either array of longitude and latitude or nil
2912
+ # @return [Array<Array<String>, nil>] returns array of elements, where each
2913
+ # element is either array of longitude and latitude or nil
2884
2914
  def geopos(key, member)
2885
2915
  synchronize do |client|
2886
2916
  client.call([:geopos, key, member])
@@ -2944,10 +2974,14 @@ class Redis
2944
2974
  # @option opts [Boolean] :approximate whether to add `~` modifier of maxlen or not
2945
2975
  #
2946
2976
  # @return [String] the entry id
2947
- def xadd(key, entry, opts = {})
2977
+ def xadd(key, entry, approximate: nil, maxlen: nil, id: '*')
2948
2978
  args = [:xadd, key]
2949
- args.concat(['MAXLEN', (opts[:approximate] ? '~' : nil), opts[:maxlen]].compact) if opts[:maxlen]
2950
- args << (opts[:id] || '*')
2979
+ if maxlen
2980
+ args << "MAXLEN"
2981
+ args << "~" if approximate
2982
+ args << maxlen
2983
+ end
2984
+ args << id
2951
2985
  args.concat(entry.to_a.flatten)
2952
2986
  synchronize { |client| client.call(args) }
2953
2987
  end
@@ -3002,8 +3036,8 @@ class Redis
3002
3036
  # @param count [Integer] the number of entries as limit
3003
3037
  #
3004
3038
  # @return [Array<Array<String, Hash>>] the ids and entries pairs
3005
- def xrange(key, start = '-', _end = '+', count: nil)
3006
- args = [:xrange, key, start, _end]
3039
+ def xrange(key, start = '-', range_end = '+', count: nil)
3040
+ args = [:xrange, key, start, range_end]
3007
3041
  args.concat(['COUNT', count]) if count
3008
3042
  synchronize { |client| client.call(args, &HashifyStreamEntries) }
3009
3043
  end
@@ -3025,8 +3059,8 @@ class Redis
3025
3059
  # @params count [Integer] the number of entries as limit
3026
3060
  #
3027
3061
  # @return [Array<Array<String, Hash>>] the ids and entries pairs
3028
- def xrevrange(key, _end = '+', start = '-', count: nil)
3029
- args = [:xrevrange, key, _end, start]
3062
+ def xrevrange(key, range_end = '+', start = '-', count: nil)
3063
+ args = [:xrevrange, key, range_end, start]
3030
3064
  args.concat(['COUNT', count]) if count
3031
3065
  synchronize { |client| client.call(args, &HashifyStreamEntries) }
3032
3066
  end
@@ -3118,12 +3152,12 @@ class Redis
3118
3152
  # @option opts [Boolean] :noack whether message loss is acceptable or not
3119
3153
  #
3120
3154
  # @return [Hash{String => Hash{String => Hash}}] the entries
3121
- def xreadgroup(group, consumer, keys, ids, opts = {})
3155
+ def xreadgroup(group, consumer, keys, ids, count: nil, block: nil, noack: nil)
3122
3156
  args = [:xreadgroup, 'GROUP', group, consumer]
3123
- args << 'COUNT' << opts[:count] if opts[:count]
3124
- args << 'BLOCK' << opts[:block].to_i if opts[:block]
3125
- args << 'NOACK' if opts[:noack]
3126
- _xread(args, keys, ids, opts[:block])
3157
+ args << 'COUNT' << count if count
3158
+ args << 'BLOCK' << block.to_i if block
3159
+ args << 'NOACK' if noack
3160
+ _xread(args, keys, ids, block)
3127
3161
  end
3128
3162
 
3129
3163
  # Removes one or multiple entries from the pending entries list of a stream consumer group.
@@ -3233,8 +3267,8 @@ class Redis
3233
3267
  when "get-master-addr-by-name"
3234
3268
  reply
3235
3269
  else
3236
- if reply.kind_of?(Array)
3237
- if reply[0].kind_of?(Array)
3270
+ if reply.is_a?(Array)
3271
+ if reply[0].is_a?(Array)
3238
3272
  reply.map(&Hashify)
3239
3273
  else
3240
3274
  Hashify.call(reply)
@@ -3258,12 +3292,17 @@ class Redis
3258
3292
  def cluster(subcommand, *args)
3259
3293
  subcommand = subcommand.to_s.downcase
3260
3294
  block = case subcommand
3261
- when 'slots' then HashifyClusterSlots
3262
- when 'nodes' then HashifyClusterNodes
3263
- when 'slaves' then HashifyClusterSlaves
3264
- when 'info' then HashifyInfo
3265
- else Noop
3266
- end
3295
+ when 'slots'
3296
+ HashifyClusterSlots
3297
+ when 'nodes'
3298
+ HashifyClusterNodes
3299
+ when 'slaves'
3300
+ HashifyClusterSlaves
3301
+ when 'info'
3302
+ HashifyInfo
3303
+ else
3304
+ Noop
3305
+ end
3267
3306
 
3268
3307
  # @see https://github.com/antirez/redis/blob/unstable/src/redis-trib.rb#L127 raw reply expected
3269
3308
  block = Noop unless @cluster_mode
@@ -3298,21 +3337,21 @@ class Redis
3298
3337
  return @original_client.connection_info if @cluster_mode
3299
3338
 
3300
3339
  {
3301
- host: @original_client.host,
3302
- port: @original_client.port,
3303
- db: @original_client.db,
3304
- id: @original_client.id,
3340
+ host: @original_client.host,
3341
+ port: @original_client.port,
3342
+ db: @original_client.db,
3343
+ id: @original_client.id,
3305
3344
  location: @original_client.location
3306
3345
  }
3307
3346
  end
3308
3347
 
3309
- def method_missing(command, *args)
3348
+ def method_missing(command, *args) # rubocop:disable Style/MissingRespondToMissing
3310
3349
  synchronize do |client|
3311
3350
  client.call([command] + args)
3312
3351
  end
3313
3352
  end
3314
3353
 
3315
- private
3354
+ private
3316
3355
 
3317
3356
  # Commands returning 1 for true and 0 for false may be executed in a pipeline
3318
3357
  # where the method call will return nil. Propagate the nil instead of falsely
@@ -3392,10 +3431,10 @@ private
3392
3431
 
3393
3432
  HashifyStreamPendings = lambda { |reply|
3394
3433
  {
3395
- 'size' => reply[0],
3434
+ 'size' => reply[0],
3396
3435
  'min_entry_id' => reply[1],
3397
3436
  'max_entry_id' => reply[2],
3398
- 'consumers' => reply[3].nil? ? {} : reply[3].to_h
3437
+ 'consumers' => reply[3].nil? ? {} : reply[3].to_h
3399
3438
  }
3400
3439
  }
3401
3440
 
@@ -3404,8 +3443,8 @@ private
3404
3443
  {
3405
3444
  'entry_id' => arr[0],
3406
3445
  'consumer' => arr[1],
3407
- 'elapsed' => arr[2],
3408
- 'count' => arr[3]
3446
+ 'elapsed' => arr[2],
3447
+ 'count' => arr[3]
3409
3448
  }
3410
3449
  end
3411
3450
  }
@@ -3413,15 +3452,15 @@ private
3413
3452
  HashifyClusterNodeInfo = lambda { |str|
3414
3453
  arr = str.split(' ')
3415
3454
  {
3416
- 'node_id' => arr[0],
3417
- 'ip_port' => arr[1],
3418
- 'flags' => arr[2].split(','),
3455
+ 'node_id' => arr[0],
3456
+ 'ip_port' => arr[1],
3457
+ 'flags' => arr[2].split(','),
3419
3458
  'master_node_id' => arr[3],
3420
- 'ping_sent' => arr[4],
3421
- 'pong_recv' => arr[5],
3422
- 'config_epoch' => arr[6],
3423
- 'link_state' => arr[7],
3424
- 'slots' => arr[8].nil? ? nil : Range.new(*arr[8].split('-'))
3459
+ 'ping_sent' => arr[4],
3460
+ 'pong_recv' => arr[5],
3461
+ 'config_epoch' => arr[6],
3462
+ 'link_state' => arr[7],
3463
+ 'slots' => arr[8].nil? ? nil : Range.new(*arr[8].split('-'))
3425
3464
  }
3426
3465
  }
3427
3466
 
@@ -3432,9 +3471,9 @@ private
3432
3471
  replicas = arr[3..-1].map { |r| { 'ip' => r[0], 'port' => r[1], 'node_id' => r[2] } }
3433
3472
  {
3434
3473
  'start_slot' => first_slot,
3435
- 'end_slot' => last_slot,
3436
- 'master' => master,
3437
- 'replicas' => replicas
3474
+ 'end_slot' => last_slot,
3475
+ 'master' => master,
3476
+ 'replicas' => replicas
3438
3477
  }
3439
3478
  end
3440
3479
  }