redis 4.1.4 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 83f1f7270db68603d63e86ec43e68348cb5ccb2b4e6759642d89898566bdbaf6
4
- data.tar.gz: 45c5bcc92629ec7d85cdc2b913e7922cd5425f2e6691891efc379aeec73026b3
3
+ metadata.gz: 9796f6646b7d3aaeeb5ef37629fb1a43422285724d8d2901a219ef4f2882eff5
4
+ data.tar.gz: b89f4f1d6a3c9ee93202ce08cdcd3ed184694b5693f7461be7cf7e517139a278
5
5
  SHA512:
6
- metadata.gz: 692dfc5c73c6410492589f38f279976a023f6a2ff13f7b1476806011eb387f41bed784bdeac746de5f4b990b6d22bf297b36dddc7b8e448a842241a389f50796
7
- data.tar.gz: 55a9e305c7563f5dd7d38f50dc7b919967dbb0f6a131ebc5e1569f49f196ab458203b6594394fa9a33ea9e337b741113e781378113783683dd36b87196607b8f
6
+ metadata.gz: be709e1aad1acee8d7c3e121e946060ce9b693ac80e25af200e2a579988f3952d6522cb9855917dc76628ae2038365bb8754b49a7cc6e90395706ba30fc87a86
7
+ data.tar.gz: 00102b01b4b37daab76fc90990f980a4710bec0e797a70d65a7544ef304f01f9b9babbdcc680da71513dd8f79649bd5f529e6804e71297b26978625bea746367
@@ -1,5 +1,18 @@
1
1
  # Unreleased
2
2
 
3
+ # 4.2.0
4
+
5
+ * Convert commands to accept keyword arguments rather than option hashes. This both help catching typos, and reduce needless allocations.
6
+ * Deprecate the synchrony driver. It will be removed in 5.0 and hopefully maintained as a separate gem. See #915.
7
+ * Make `Redis#exists` variadic, will return an Integer if called with multiple keys.
8
+ * Add `Redis#exists?` to get a Boolean if any of the keys exists.
9
+ * `Redis#exists` when called with a single key will warn that future versions will return an Integer.
10
+ Set `Redis.exists_returns_integer = true` to opt-in to the new behavior.
11
+ * Support `keepttl` ooption in `set`. See #913.
12
+ * Optimized initialization of Redis::Cluster. See #912.
13
+ * Accept sentinel options even with string key. See #599.
14
+ * Verify TLS connections by default. See #900.
15
+
3
16
  # 4.1.4
4
17
 
5
18
  * Alias `Redis#disconnect` as `#close`. See #901.
@@ -9,6 +22,7 @@
9
22
  * Increase buffer size in the ruby connector. See #880.
10
23
  * Fix thread safety of `Redis.queue`. See #878.
11
24
  * Deprecate `Redis::Future#==` as it's likely to be a mistake. See #876.
25
+ * Support `KEEPTTL` option for SET command. See #913.
12
26
 
13
27
  # 4.1.3
14
28
 
data/README.md CHANGED
@@ -3,6 +3,7 @@
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.
@@ -147,8 +151,8 @@ redis.mget('{key}1', '{key}2')
147
151
 
148
152
  ## Storing objects
149
153
 
150
- Redis only stores strings as values. If you want to store an object, you
151
- 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:
152
156
 
153
157
  ```ruby
154
158
  require "json"
@@ -322,7 +326,7 @@ This library supports natively terminating client side SSL/TLS connections
322
326
  when talking to Redis via a server-side proxy such as [stunnel], [hitch],
323
327
  or [ghostunnel].
324
328
 
325
- 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
326
330
  Redis client, or pass in `:url => "rediss://..."` (like HTTPS for Redis).
327
331
  You will also need to pass in an `:ssl_params => { ... }` hash used to
328
332
  configure the `OpenSSL::SSL::SSLContext` object used for the connection:
@@ -451,7 +455,7 @@ client and evangelized Redis in Rubyland. Thank you, Ezra.
451
455
  ## Contributing
452
456
 
453
457
  [Fork the project](https://github.com/redis/redis-rb) and send pull
454
- requests. You can also ask for help at `#redis-rb` on Freenode.
458
+ requests.
455
459
 
456
460
 
457
461
  [inchpages-image]: https://inch-ci.org/github/redis/redis-rb.svg
@@ -4,12 +4,13 @@ require "monitor"
4
4
  require_relative "redis/errors"
5
5
 
6
6
  class Redis
7
- def self.current
8
- @current ||= Redis.new
7
+ class << self
8
+ attr_accessor :exists_returns_integer
9
+ attr_writer :current
9
10
  end
10
11
 
11
- def self.current=(redis)
12
- @current = redis
12
+ def self.current
13
+ @current ||= Redis.new
13
14
  end
14
15
 
15
16
  include MonitorMixin
@@ -17,7 +18,9 @@ class Redis
17
18
  # Create a new client instance
18
19
  #
19
20
  # @param [Hash] options
20
- # @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.
21
+ # @option options [String] :url (value of the environment variable REDIS_URL) a Redis URL, for a TCP connection:
22
+ # `redis://:[password]@[hostname]:[port]/[db]` (password, port and database are optional), for a unix socket
23
+ # connection: `unix://[path to Redis socket]`. This overrides all other options.
21
24
  # @option options [String] :host ("127.0.0.1") server hostname
22
25
  # @option options [Integer] :port (6379) server port
23
26
  # @option options [String] :path path to server socket (overrides host and port)
@@ -26,8 +29,10 @@ class Redis
26
29
  # @option options [String] :password Password to authenticate against server
27
30
  # @option options [Integer] :db (0) Database to select after initial connect
28
31
  # @option options [Symbol] :driver Driver to use, currently supported: `:ruby`, `:hiredis`, `:synchrony`
29
- # @option options [String] :id ID for the client connection, assigns name to current connection by sending `CLIENT SETNAME`
30
- # @option options [Hash, Integer] :tcp_keepalive Keepalive values, if Integer `intvl` and `probe` are calculated based on the value, if Hash `time`, `intvl` and `probes` can be specified as a Integer
32
+ # @option options [String] :id ID for the client connection, assigns name to current connection by sending
33
+ # `CLIENT SETNAME`
34
+ # @option options [Hash, Integer] :tcp_keepalive Keepalive values, if Integer `intvl` and `probe` are calculated
35
+ # based on the value, if Hash `time`, `intvl` and `probes` can be specified as a Integer
31
36
  # @option options [Integer] :reconnect_attempts Number of attempts trying to connect
32
37
  # @option options [Boolean] :inherit_socket (false) Whether to use socket in forked process or not
33
38
  # @option options [Array] :sentinels List of sentinels to contact
@@ -52,7 +57,7 @@ class Redis
52
57
  end
53
58
 
54
59
  # Run code with the client reconnecting
55
- def with_reconnect(val=true, &blk)
60
+ def with_reconnect(val = true, &blk)
56
61
  synchronize do |client|
57
62
  client.with_reconnect(val, &blk)
58
63
  end
@@ -205,7 +210,7 @@ class Redis
205
210
  def config(action, *args)
206
211
  synchronize do |client|
207
212
  client.call([:config, action] + args) do |reply|
208
- if reply.kind_of?(Array) && action == :get
213
+ if reply.is_a?(Array) && action == :get
209
214
  Hashify.call(reply)
210
215
  else
211
216
  reply
@@ -256,7 +261,7 @@ class Redis
256
261
  def flushall(options = nil)
257
262
  synchronize do |client|
258
263
  if options && options[:async]
259
- client.call([:flushall, :async])
264
+ client.call(%i[flushall async])
260
265
  else
261
266
  client.call([:flushall])
262
267
  end
@@ -271,7 +276,7 @@ class Redis
271
276
  def flushdb(options = nil)
272
277
  synchronize do |client|
273
278
  if options && options[:async]
274
- client.call([:flushdb, :async])
279
+ client.call(%i[flushdb async])
275
280
  else
276
281
  client.call([:flushdb])
277
282
  end
@@ -285,7 +290,7 @@ class Redis
285
290
  def info(cmd = nil)
286
291
  synchronize do |client|
287
292
  client.call([:info, cmd].compact) do |reply|
288
- if reply.kind_of?(String)
293
+ if reply.is_a?(String)
289
294
  reply = HashifyInfo.call(reply)
290
295
 
291
296
  if cmd && cmd.to_s == "commandstats"
@@ -358,7 +363,7 @@ class Redis
358
363
  # @param [String] subcommand e.g. `get`, `len`, `reset`
359
364
  # @param [Integer] length maximum number of entries to return
360
365
  # @return [Array<String>, Integer, String] depends on subcommand
361
- def slowlog(subcommand, length=nil)
366
+ def slowlog(subcommand, length = nil)
362
367
  synchronize do |client|
363
368
  args = [:slowlog, subcommand]
364
369
  args << length if length
@@ -383,7 +388,7 @@ class Redis
383
388
  def time
384
389
  synchronize do |client|
385
390
  client.call([:time]) do |reply|
386
- reply.map(&:to_i) if reply
391
+ reply&.map(&:to_i)
387
392
  end
388
393
  end
389
394
  end
@@ -496,9 +501,9 @@ class Redis
496
501
  # - `:replace => Boolean`: if false, raises an error if key already exists
497
502
  # @raise [Redis::CommandError]
498
503
  # @return [String] `"OK"`
499
- def restore(key, ttl, serialized_value, options = {})
504
+ def restore(key, ttl, serialized_value, replace: nil)
500
505
  args = [:restore, key, ttl, serialized_value]
501
- args << 'REPLACE' if options[:replace]
506
+ args << 'REPLACE' if replace
502
507
 
503
508
  synchronize do |client|
504
509
  client.call(args)
@@ -550,13 +555,36 @@ class Redis
550
555
  end
551
556
  end
552
557
 
553
- # Determine if a key exists.
558
+ # Determine how many of the keys exists.
554
559
  #
555
- # @param [String] key
560
+ # @param [String, Array<String>] keys
561
+ # @return [Integer]
562
+ def exists(*keys)
563
+ if !Redis.exists_returns_integer && keys.size == 1
564
+ message = "`Redis#exists(key)` will return an Integer in redis-rb 4.3, if you want to keep the old behavior, " \
565
+ "use `exists?` instead. To opt-in to the new behavior now you can set Redis.exists_returns_integer = true. " \
566
+ "(#{::Kernel.caller(1, 1).first})\n"
567
+
568
+ ::Kernel.warn(message)
569
+ exists?(*keys)
570
+ else
571
+ _exists(*keys)
572
+ end
573
+ end
574
+
575
+ def _exists(*keys)
576
+ synchronize do |client|
577
+ client.call([:exists, *keys])
578
+ end
579
+ end
580
+
581
+ # Determine if any of the keys exists.
582
+ #
583
+ # @param [String, Array<String>] keys
556
584
  # @return [Boolean]
557
- def exists(key)
585
+ def exists?(*keys)
558
586
  synchronize do |client|
559
- client.call([:exists, key], &Boolify)
587
+ client.call([:exists, *keys], &Boolify)
560
588
  end
561
589
  end
562
590
 
@@ -567,7 +595,7 @@ class Redis
567
595
  def keys(pattern = "*")
568
596
  synchronize do |client|
569
597
  client.call([:keys, pattern]) do |reply|
570
- if reply.kind_of?(String)
598
+ if reply.is_a?(String)
571
599
  reply.split(" ")
572
600
  else
573
601
  reply
@@ -663,30 +691,27 @@ class Redis
663
691
  # elements where every element is an array with the result for every
664
692
  # element specified in `:get`
665
693
  # - when `:store` is specified, the number of elements in the stored result
666
- def sort(key, options = {})
667
- args = []
668
-
669
- by = options[:by]
670
- args.concat(["BY", by]) if by
694
+ def sort(key, by: nil, limit: nil, get: nil, order: nil, store: nil)
695
+ args = [:sort, key]
696
+ args << "BY" << by if by
671
697
 
672
- limit = options[:limit]
673
- args.concat(["LIMIT"] + limit) if limit
698
+ if limit
699
+ args << "LIMIT"
700
+ args.concat(limit)
701
+ end
674
702
 
675
- get = Array(options[:get])
676
- args.concat(["GET"].product(get).flatten) unless get.empty?
703
+ get = Array(get)
704
+ get.each do |item|
705
+ args << "GET" << item
706
+ end
677
707
 
678
- order = options[:order]
679
708
  args.concat(order.split(" ")) if order
680
-
681
- store = options[:store]
682
- args.concat(["STORE", store]) if store
709
+ args << "STORE" << store if store
683
710
 
684
711
  synchronize do |client|
685
- client.call([:sort, key] + args) do |reply|
712
+ client.call(args) do |reply|
686
713
  if get.size > 1 && !store
687
- if reply
688
- reply.each_slice(get.size).to_a
689
- end
714
+ reply.each_slice(get.size).to_a if reply
690
715
  else
691
716
  reply
692
717
  end
@@ -786,27 +811,21 @@ class Redis
786
811
  # - `:px => Integer`: Set the specified expire time, in milliseconds.
787
812
  # - `:nx => true`: Only set the key if it does not already exist.
788
813
  # - `:xx => true`: Only set the key if it already exist.
814
+ # - `:keepttl => true`: Retain the time to live associated with the key.
789
815
  # @return [String, Boolean] `"OK"` or true, false if `:nx => true` or `:xx => true`
790
- def set(key, value, options = {})
791
- args = []
792
-
793
- ex = options[:ex]
794
- args.concat(["EX", ex]) if ex
795
-
796
- px = options[:px]
797
- args.concat(["PX", px]) if px
798
-
799
- nx = options[:nx]
800
- args.concat(["NX"]) if nx
801
-
802
- xx = options[:xx]
803
- args.concat(["XX"]) if xx
816
+ def set(key, value, ex: nil, px: nil, nx: nil, xx: nil, keepttl: nil)
817
+ args = [:set, key, value.to_s]
818
+ args << "EX" << ex if ex
819
+ args << "PX" << px if px
820
+ args << "NX" if nx
821
+ args << "XX" if xx
822
+ args << "KEEPTTL" if keepttl
804
823
 
805
824
  synchronize do |client|
806
825
  if nx || xx
807
- client.call([:set, key, value.to_s] + args, &BoolifySet)
826
+ client.call(args, &BoolifySet)
808
827
  else
809
- client.call([:set, key, value.to_s] + args)
828
+ client.call(args)
810
829
  end
811
830
  end
812
831
  end
@@ -888,7 +907,7 @@ class Redis
888
907
  # @see #mapped_msetnx
889
908
  def msetnx(*args)
890
909
  synchronize do |client|
891
- client.call([:msetnx] + args, &Boolify)
910
+ client.call([:msetnx, *args], &Boolify)
892
911
  end
893
912
  end
894
913
 
@@ -928,7 +947,7 @@ class Redis
928
947
  # @see #mapped_mget
929
948
  def mget(*keys, &blk)
930
949
  synchronize do |client|
931
- client.call([:mget] + keys, &blk)
950
+ client.call([:mget, *keys], &blk)
932
951
  end
933
952
  end
934
953
 
@@ -944,7 +963,7 @@ class Redis
944
963
  # @see #mget
945
964
  def mapped_mget(*keys)
946
965
  mget(*keys) do |reply|
947
- if reply.kind_of?(Array)
966
+ if reply.is_a?(Array)
948
967
  Hash[keys.zip(reply)]
949
968
  else
950
969
  reply
@@ -1031,7 +1050,7 @@ class Redis
1031
1050
  # @return [Integer] the length of the string stored in `destkey`
1032
1051
  def bitop(operation, destkey, *keys)
1033
1052
  synchronize do |client|
1034
- client.call([:bitop, operation, destkey] + keys)
1053
+ client.call([:bitop, operation, destkey, *keys])
1035
1054
  end
1036
1055
  end
1037
1056
 
@@ -1043,10 +1062,8 @@ class Redis
1043
1062
  # @param [Integer] stop stop index
1044
1063
  # @return [Integer] the position of the first 1/0 bit.
1045
1064
  # -1 if looking for 1 and it is not found or start and stop are given.
1046
- def bitpos(key, bit, start=nil, stop=nil)
1047
- if stop and not start
1048
- raise(ArgumentError, 'stop parameter specified without start parameter')
1049
- end
1065
+ def bitpos(key, bit, start = nil, stop = nil)
1066
+ raise(ArgumentError, 'stop parameter specified without start parameter') if stop && !start
1050
1067
 
1051
1068
  synchronize do |client|
1052
1069
  command = [:bitpos, key, bit]
@@ -1240,15 +1257,7 @@ class Redis
1240
1257
  # @return [nil, String]
1241
1258
  # - `nil` when the operation timed out
1242
1259
  # - the element was popped and pushed otherwise
1243
- def brpoplpush(source, destination, options = {})
1244
- case options
1245
- when Integer
1246
- # Issue deprecation notice in obnoxious mode...
1247
- options = { :timeout => options }
1248
- end
1249
-
1250
- timeout = options[:timeout] || 0
1251
-
1260
+ def brpoplpush(source, destination, deprecated_timeout = 0, timeout: deprecated_timeout)
1252
1261
  synchronize do |client|
1253
1262
  command = [:brpoplpush, source, destination, timeout]
1254
1263
  timeout += client.timeout if timeout > 0
@@ -1455,7 +1464,7 @@ class Redis
1455
1464
  # @return [Array<String>] members in the difference
1456
1465
  def sdiff(*keys)
1457
1466
  synchronize do |client|
1458
- client.call([:sdiff] + keys)
1467
+ client.call([:sdiff, *keys])
1459
1468
  end
1460
1469
  end
1461
1470
 
@@ -1466,7 +1475,7 @@ class Redis
1466
1475
  # @return [Integer] number of elements in the resulting set
1467
1476
  def sdiffstore(destination, *keys)
1468
1477
  synchronize do |client|
1469
- client.call([:sdiffstore, destination] + keys)
1478
+ client.call([:sdiffstore, destination, *keys])
1470
1479
  end
1471
1480
  end
1472
1481
 
@@ -1476,7 +1485,7 @@ class Redis
1476
1485
  # @return [Array<String>] members in the intersection
1477
1486
  def sinter(*keys)
1478
1487
  synchronize do |client|
1479
- client.call([:sinter] + keys)
1488
+ client.call([:sinter, *keys])
1480
1489
  end
1481
1490
  end
1482
1491
 
@@ -1487,7 +1496,7 @@ class Redis
1487
1496
  # @return [Integer] number of elements in the resulting set
1488
1497
  def sinterstore(destination, *keys)
1489
1498
  synchronize do |client|
1490
- client.call([:sinterstore, destination] + keys)
1499
+ client.call([:sinterstore, destination, *keys])
1491
1500
  end
1492
1501
  end
1493
1502
 
@@ -1497,7 +1506,7 @@ class Redis
1497
1506
  # @return [Array<String>] members in the union
1498
1507
  def sunion(*keys)
1499
1508
  synchronize do |client|
1500
- client.call([:sunion] + keys)
1509
+ client.call([:sunion, *keys])
1501
1510
  end
1502
1511
  end
1503
1512
 
@@ -1508,7 +1517,7 @@ class Redis
1508
1517
  # @return [Integer] number of elements in the resulting set
1509
1518
  def sunionstore(destination, *keys)
1510
1519
  synchronize do |client|
1511
- client.call([:sunionstore, destination] + keys)
1520
+ client.call([:sunionstore, destination, *keys])
1512
1521
  end
1513
1522
  end
1514
1523
 
@@ -1557,31 +1566,20 @@ class Redis
1557
1566
  # pairs that were **added** to the sorted set.
1558
1567
  # - `Float` when option :incr is specified, holding the score of the member
1559
1568
  # after incrementing it.
1560
- def zadd(key, *args) #, options
1561
- zadd_options = []
1562
- if args.last.is_a?(Hash)
1563
- options = args.pop
1564
-
1565
- nx = options[:nx]
1566
- zadd_options << "NX" if nx
1567
-
1568
- xx = options[:xx]
1569
- zadd_options << "XX" if xx
1570
-
1571
- ch = options[:ch]
1572
- zadd_options << "CH" if ch
1573
-
1574
- incr = options[:incr]
1575
- zadd_options << "INCR" if incr
1576
- end
1569
+ def zadd(key, *args, nx: nil, xx: nil, ch: nil, incr: nil)
1570
+ command = [:zadd, key]
1571
+ command << "NX" if nx
1572
+ command << "XX" if xx
1573
+ command << "CH" if ch
1574
+ command << "INCR" if incr
1577
1575
 
1578
1576
  synchronize do |client|
1579
1577
  if args.size == 1 && args[0].is_a?(Array)
1580
1578
  # Variadic: return float if INCR, integer if !INCR
1581
- client.call([:zadd, key] + zadd_options + args[0], &(incr ? Floatify : nil))
1579
+ client.call(command + args[0], &(incr ? Floatify : nil))
1582
1580
  elsif args.size == 2
1583
1581
  # Single pair: return float if INCR, boolean if !INCR
1584
- client.call([:zadd, key] + zadd_options + args, &(incr ? Floatify : Boolify))
1582
+ client.call(command + args, &(incr ? Floatify : Boolify))
1585
1583
  else
1586
1584
  raise ArgumentError, "wrong number of arguments"
1587
1585
  end
@@ -1752,10 +1750,8 @@ class Redis
1752
1750
  # @return [Array<String>, Array<[String, Float]>]
1753
1751
  # - when `:with_scores` is not specified, an array of members
1754
1752
  # - when `:with_scores` is specified, an array with `[member, score]` pairs
1755
- def zrange(key, start, stop, options = {})
1756
- args = []
1757
-
1758
- with_scores = options[:with_scores] || options[:withscores]
1753
+ def zrange(key, start, stop, withscores: false, with_scores: withscores)
1754
+ args = [:zrange, key, start, stop]
1759
1755
 
1760
1756
  if with_scores
1761
1757
  args << "WITHSCORES"
@@ -1763,7 +1759,7 @@ class Redis
1763
1759
  end
1764
1760
 
1765
1761
  synchronize do |client|
1766
- client.call([:zrange, key, start, stop] + args, &block)
1762
+ client.call(args, &block)
1767
1763
  end
1768
1764
  end
1769
1765
 
@@ -1778,10 +1774,8 @@ class Redis
1778
1774
  # # => [["b", 64.0], ["a", 32.0]]
1779
1775
  #
1780
1776
  # @see #zrange
1781
- def zrevrange(key, start, stop, options = {})
1782
- args = []
1783
-
1784
- with_scores = options[:with_scores] || options[:withscores]
1777
+ def zrevrange(key, start, stop, withscores: false, with_scores: withscores)
1778
+ args = [:zrevrange, key, start, stop]
1785
1779
 
1786
1780
  if with_scores
1787
1781
  args << "WITHSCORES"
@@ -1789,7 +1783,7 @@ class Redis
1789
1783
  end
1790
1784
 
1791
1785
  synchronize do |client|
1792
- client.call([:zrevrange, key, start, stop] + args, &block)
1786
+ client.call(args, &block)
1793
1787
  end
1794
1788
  end
1795
1789
 
@@ -1880,14 +1874,16 @@ class Redis
1880
1874
  # `count` members
1881
1875
  #
1882
1876
  # @return [Array<String>, Array<[String, Float]>]
1883
- def zrangebylex(key, min, max, options = {})
1884
- args = []
1877
+ def zrangebylex(key, min, max, limit: nil)
1878
+ args = [:zrangebylex, key, min, max]
1885
1879
 
1886
- limit = options[:limit]
1887
- args.concat(["LIMIT"] + limit) if limit
1880
+ if limit
1881
+ args << "LIMIT"
1882
+ args.concat(limit)
1883
+ end
1888
1884
 
1889
1885
  synchronize do |client|
1890
- client.call([:zrangebylex, key, min, max] + args)
1886
+ client.call(args)
1891
1887
  end
1892
1888
  end
1893
1889
 
@@ -1902,14 +1898,16 @@ class Redis
1902
1898
  # # => ["abbygail", "abby"]
1903
1899
  #
1904
1900
  # @see #zrangebylex
1905
- def zrevrangebylex(key, max, min, options = {})
1906
- args = []
1901
+ def zrevrangebylex(key, max, min, limit: nil)
1902
+ args = [:zrevrangebylex, key, max, min]
1907
1903
 
1908
- limit = options[:limit]
1909
- args.concat(["LIMIT"] + limit) if limit
1904
+ if limit
1905
+ args << "LIMIT"
1906
+ args.concat(limit)
1907
+ end
1910
1908
 
1911
1909
  synchronize do |client|
1912
- client.call([:zrevrangebylex, key, max, min] + args)
1910
+ client.call(args)
1913
1911
  end
1914
1912
  end
1915
1913
 
@@ -1940,21 +1938,21 @@ class Redis
1940
1938
  # @return [Array<String>, Array<[String, Float]>]
1941
1939
  # - when `:with_scores` is not specified, an array of members
1942
1940
  # - when `:with_scores` is specified, an array with `[member, score]` pairs
1943
- def zrangebyscore(key, min, max, options = {})
1944
- args = []
1945
-
1946
- with_scores = options[:with_scores] || options[:withscores]
1941
+ def zrangebyscore(key, min, max, withscores: false, with_scores: withscores, limit: nil)
1942
+ args = [:zrangebyscore, key, min, max]
1947
1943
 
1948
1944
  if with_scores
1949
1945
  args << "WITHSCORES"
1950
1946
  block = FloatifyPairs
1951
1947
  end
1952
1948
 
1953
- limit = options[:limit]
1954
- args.concat(["LIMIT"] + limit) if limit
1949
+ if limit
1950
+ args << "LIMIT"
1951
+ args.concat(limit)
1952
+ end
1955
1953
 
1956
1954
  synchronize do |client|
1957
- client.call([:zrangebyscore, key, min, max] + args, &block)
1955
+ client.call(args, &block)
1958
1956
  end
1959
1957
  end
1960
1958
 
@@ -1972,21 +1970,21 @@ class Redis
1972
1970
  # # => [["b", 64.0], ["a", 32.0]]
1973
1971
  #
1974
1972
  # @see #zrangebyscore
1975
- def zrevrangebyscore(key, max, min, options = {})
1976
- args = []
1977
-
1978
- with_scores = options[:with_scores] || options[:withscores]
1973
+ def zrevrangebyscore(key, max, min, withscores: false, with_scores: withscores, limit: nil)
1974
+ args = [:zrevrangebyscore, key, max, min]
1979
1975
 
1980
1976
  if with_scores
1981
- args << ["WITHSCORES"]
1977
+ args << "WITHSCORES"
1982
1978
  block = FloatifyPairs
1983
1979
  end
1984
1980
 
1985
- limit = options[:limit]
1986
- args.concat(["LIMIT"] + limit) if limit
1981
+ if limit
1982
+ args << "LIMIT"
1983
+ args.concat(limit)
1984
+ end
1987
1985
 
1988
1986
  synchronize do |client|
1989
- client.call([:zrevrangebyscore, key, max, min] + args, &block)
1987
+ client.call(args, &block)
1990
1988
  end
1991
1989
  end
1992
1990
 
@@ -2050,17 +2048,18 @@ class Redis
2050
2048
  # sorted sets
2051
2049
  # - `:aggregate => String`: aggregate function to use (sum, min, max, ...)
2052
2050
  # @return [Integer] number of elements in the resulting sorted set
2053
- def zinterstore(destination, keys, options = {})
2054
- args = []
2051
+ def zinterstore(destination, keys, weights: nil, aggregate: nil)
2052
+ args = [:zinterstore, destination, keys.size, *keys]
2055
2053
 
2056
- weights = options[:weights]
2057
- args.concat(["WEIGHTS"] + weights) if weights
2054
+ if weights
2055
+ args << "WEIGHTS"
2056
+ args.concat(weights)
2057
+ end
2058
2058
 
2059
- aggregate = options[:aggregate]
2060
- args.concat(["AGGREGATE", aggregate]) if aggregate
2059
+ args << "AGGREGATE" << aggregate if aggregate
2061
2060
 
2062
2061
  synchronize do |client|
2063
- client.call([:zinterstore, destination, keys.size] + keys + args)
2062
+ client.call(args)
2064
2063
  end
2065
2064
  end
2066
2065
 
@@ -2077,17 +2076,18 @@ class Redis
2077
2076
  # sorted sets
2078
2077
  # - `:aggregate => String`: aggregate function to use (sum, min, max, ...)
2079
2078
  # @return [Integer] number of elements in the resulting sorted set
2080
- def zunionstore(destination, keys, options = {})
2081
- args = []
2079
+ def zunionstore(destination, keys, weights: nil, aggregate: nil)
2080
+ args = [:zunionstore, destination, keys.size, *keys]
2082
2081
 
2083
- weights = options[:weights]
2084
- args.concat(["WEIGHTS"] + weights) if weights
2082
+ if weights
2083
+ args << "WEIGHTS"
2084
+ args.concat(weights)
2085
+ end
2085
2086
 
2086
- aggregate = options[:aggregate]
2087
- args.concat(["AGGREGATE", aggregate]) if aggregate
2087
+ args << "AGGREGATE" << aggregate if aggregate
2088
2088
 
2089
2089
  synchronize do |client|
2090
- client.call([:zunionstore, destination, keys.size] + keys + args)
2090
+ client.call(args)
2091
2091
  end
2092
2092
  end
2093
2093
 
@@ -2101,15 +2101,20 @@ class Redis
2101
2101
  end
2102
2102
  end
2103
2103
 
2104
- # Set the string value of a hash field.
2104
+ # Set one or more hash values.
2105
+ #
2106
+ # @example
2107
+ # redis.hset("hash", "f1", "v1", "f2", "v2") # => 2
2108
+ # redis.hset("hash", { "f1" => "v1", "f2" => "v2" }) # => 2
2105
2109
  #
2106
2110
  # @param [String] key
2107
- # @param [String] field
2108
- # @param [String] value
2109
- # @return [Boolean] whether or not the field was **added** to the hash
2110
- def hset(key, field, value)
2111
+ # @param [Array<String> | Hash<String, String>] attrs array or hash of fields and values
2112
+ # @return [Integer] The number of fields that were added to the hash
2113
+ def hset(key, *attrs)
2114
+ attrs = attrs.first.flatten if attrs.size == 1 && attrs.first.is_a?(Hash)
2115
+
2111
2116
  synchronize do |client|
2112
- client.call([:hset, key, field, value], &Boolify)
2117
+ client.call([:hset, key, *attrs])
2113
2118
  end
2114
2119
  end
2115
2120
 
@@ -2198,7 +2203,7 @@ class Redis
2198
2203
  # @see #hmget
2199
2204
  def mapped_hmget(key, *fields)
2200
2205
  hmget(key, *fields) do |reply|
2201
- if reply.kind_of?(Array)
2206
+ if reply.is_a?(Array)
2202
2207
  Hash[fields.zip(reply)]
2203
2208
  else
2204
2209
  reply
@@ -2291,20 +2296,21 @@ class Redis
2291
2296
 
2292
2297
  def subscribed?
2293
2298
  synchronize do |client|
2294
- client.kind_of? SubscribedClient
2299
+ client.is_a? SubscribedClient
2295
2300
  end
2296
2301
  end
2297
2302
 
2298
2303
  # Listen for messages published to the given channels.
2299
2304
  def subscribe(*channels, &block)
2300
- synchronize do |client|
2305
+ synchronize do |_client|
2301
2306
  _subscription(:subscribe, 0, channels, block)
2302
2307
  end
2303
2308
  end
2304
2309
 
2305
- # Listen for messages published to the given channels. Throw a timeout error if there is no messages for a timeout period.
2310
+ # Listen for messages published to the given channels. Throw a timeout error
2311
+ # if there is no messages for a timeout period.
2306
2312
  def subscribe_with_timeout(timeout, *channels, &block)
2307
- synchronize do |client|
2313
+ synchronize do |_client|
2308
2314
  _subscription(:subscribe_with_timeout, timeout, channels, block)
2309
2315
  end
2310
2316
  end
@@ -2312,21 +2318,23 @@ class Redis
2312
2318
  # Stop listening for messages posted to the given channels.
2313
2319
  def unsubscribe(*channels)
2314
2320
  synchronize do |client|
2315
- raise RuntimeError, "Can't unsubscribe if not subscribed." unless subscribed?
2321
+ raise "Can't unsubscribe if not subscribed." unless subscribed?
2322
+
2316
2323
  client.unsubscribe(*channels)
2317
2324
  end
2318
2325
  end
2319
2326
 
2320
2327
  # Listen for messages published to channels matching the given patterns.
2321
2328
  def psubscribe(*channels, &block)
2322
- synchronize do |client|
2329
+ synchronize do |_client|
2323
2330
  _subscription(:psubscribe, 0, channels, block)
2324
2331
  end
2325
2332
  end
2326
2333
 
2327
- # Listen for messages published to channels matching the given patterns. Throw a timeout error if there is no messages for a timeout period.
2334
+ # Listen for messages published to channels matching the given patterns.
2335
+ # Throw a timeout error if there is no messages for a timeout period.
2328
2336
  def psubscribe_with_timeout(timeout, *channels, &block)
2329
- synchronize do |client|
2337
+ synchronize do |_client|
2330
2338
  _subscription(:psubscribe_with_timeout, timeout, channels, block)
2331
2339
  end
2332
2340
  end
@@ -2334,7 +2342,8 @@ class Redis
2334
2342
  # Stop listening for messages posted to channels matching the given patterns.
2335
2343
  def punsubscribe(*channels)
2336
2344
  synchronize do |client|
2337
- raise RuntimeError, "Can't unsubscribe if not subscribed." unless subscribed?
2345
+ raise "Can't unsubscribe if not subscribed." unless subscribed?
2346
+
2338
2347
  client.punsubscribe(*channels)
2339
2348
  end
2340
2349
  end
@@ -2379,7 +2388,7 @@ class Redis
2379
2388
  # @see #multi
2380
2389
  def watch(*keys)
2381
2390
  synchronize do |client|
2382
- res = client.call([:watch] + keys)
2391
+ res = client.call([:watch, *keys])
2383
2392
 
2384
2393
  if block_given?
2385
2394
  begin
@@ -2409,7 +2418,7 @@ class Redis
2409
2418
  end
2410
2419
 
2411
2420
  def pipelined
2412
- synchronize do |client|
2421
+ synchronize do |_client|
2413
2422
  begin
2414
2423
  pipeline = Pipeline.new(@client)
2415
2424
  original, @client = @client, pipeline
@@ -2609,18 +2618,12 @@ class Redis
2609
2618
  _eval(:evalsha, args)
2610
2619
  end
2611
2620
 
2612
- def _scan(command, cursor, args, options = {}, &block)
2621
+ def _scan(command, cursor, args, match: nil, count: nil, &block)
2613
2622
  # SSCAN/ZSCAN/HSCAN already prepend the key to +args+.
2614
2623
 
2615
2624
  args << cursor
2616
-
2617
- if match = options[:match]
2618
- args.concat(["MATCH", match])
2619
- end
2620
-
2621
- if count = options[:count]
2622
- args.concat(["COUNT", count])
2623
- end
2625
+ args << "MATCH" << match if match
2626
+ args << "COUNT" << count if count
2624
2627
 
2625
2628
  synchronize do |client|
2626
2629
  client.call([command] + args, &block)
@@ -2642,8 +2645,8 @@ class Redis
2642
2645
  # - `:count => Integer`: return count keys at most per iteration
2643
2646
  #
2644
2647
  # @return [String, Array<String>] the next cursor and all found keys
2645
- def scan(cursor, options={})
2646
- _scan(:scan, cursor, [], options)
2648
+ def scan(cursor, **options)
2649
+ _scan(:scan, cursor, [], **options)
2647
2650
  end
2648
2651
 
2649
2652
  # Scan the keyspace
@@ -2661,11 +2664,12 @@ class Redis
2661
2664
  # - `:count => Integer`: return count keys at most per iteration
2662
2665
  #
2663
2666
  # @return [Enumerator] an enumerator for all found keys
2664
- def scan_each(options={}, &block)
2665
- return to_enum(:scan_each, options) unless block_given?
2667
+ def scan_each(**options, &block)
2668
+ return to_enum(:scan_each, **options) unless block_given?
2669
+
2666
2670
  cursor = 0
2667
2671
  loop do
2668
- cursor, keys = scan(cursor, options)
2672
+ cursor, keys = scan(cursor, **options)
2669
2673
  keys.each(&block)
2670
2674
  break if cursor == "0"
2671
2675
  end
@@ -2682,8 +2686,8 @@ class Redis
2682
2686
  # - `:count => Integer`: return count keys at most per iteration
2683
2687
  #
2684
2688
  # @return [String, Array<[String, String]>] the next cursor and all found keys
2685
- def hscan(key, cursor, options={})
2686
- _scan(:hscan, cursor, [key], options) do |reply|
2689
+ def hscan(key, cursor, **options)
2690
+ _scan(:hscan, cursor, [key], **options) do |reply|
2687
2691
  [reply[0], reply[1].each_slice(2).to_a]
2688
2692
  end
2689
2693
  end
@@ -2699,11 +2703,12 @@ class Redis
2699
2703
  # - `:count => Integer`: return count keys at most per iteration
2700
2704
  #
2701
2705
  # @return [Enumerator] an enumerator for all found keys
2702
- def hscan_each(key, options={}, &block)
2703
- return to_enum(:hscan_each, key, options) unless block_given?
2706
+ def hscan_each(key, **options, &block)
2707
+ return to_enum(:hscan_each, key, **options) unless block_given?
2708
+
2704
2709
  cursor = 0
2705
2710
  loop do
2706
- cursor, values = hscan(key, cursor, options)
2711
+ cursor, values = hscan(key, cursor, **options)
2707
2712
  values.each(&block)
2708
2713
  break if cursor == "0"
2709
2714
  end
@@ -2721,8 +2726,8 @@ class Redis
2721
2726
  #
2722
2727
  # @return [String, Array<[String, Float]>] the next cursor and all found
2723
2728
  # members and scores
2724
- def zscan(key, cursor, options={})
2725
- _scan(:zscan, cursor, [key], options) do |reply|
2729
+ def zscan(key, cursor, **options)
2730
+ _scan(:zscan, cursor, [key], **options) do |reply|
2726
2731
  [reply[0], FloatifyPairs.call(reply[1])]
2727
2732
  end
2728
2733
  end
@@ -2738,11 +2743,12 @@ class Redis
2738
2743
  # - `:count => Integer`: return count keys at most per iteration
2739
2744
  #
2740
2745
  # @return [Enumerator] an enumerator for all found scores and members
2741
- def zscan_each(key, options={}, &block)
2742
- return to_enum(:zscan_each, key, options) unless block_given?
2746
+ def zscan_each(key, **options, &block)
2747
+ return to_enum(:zscan_each, key, **options) unless block_given?
2748
+
2743
2749
  cursor = 0
2744
2750
  loop do
2745
- cursor, values = zscan(key, cursor, options)
2751
+ cursor, values = zscan(key, cursor, **options)
2746
2752
  values.each(&block)
2747
2753
  break if cursor == "0"
2748
2754
  end
@@ -2759,8 +2765,8 @@ class Redis
2759
2765
  # - `:count => Integer`: return count keys at most per iteration
2760
2766
  #
2761
2767
  # @return [String, Array<String>] the next cursor and all found members
2762
- def sscan(key, cursor, options={})
2763
- _scan(:sscan, cursor, [key], options)
2768
+ def sscan(key, cursor, **options)
2769
+ _scan(:sscan, cursor, [key], **options)
2764
2770
  end
2765
2771
 
2766
2772
  # Scan a set
@@ -2774,11 +2780,12 @@ class Redis
2774
2780
  # - `:count => Integer`: return count keys at most per iteration
2775
2781
  #
2776
2782
  # @return [Enumerator] an enumerator for all keys in the set
2777
- def sscan_each(key, options={}, &block)
2778
- return to_enum(:sscan_each, key, options) unless block_given?
2783
+ def sscan_each(key, **options, &block)
2784
+ return to_enum(:sscan_each, key, **options) unless block_given?
2785
+
2779
2786
  cursor = 0
2780
2787
  loop do
2781
- cursor, keys = sscan(key, cursor, options)
2788
+ cursor, keys = sscan(key, cursor, **options)
2782
2789
  keys.each(&block)
2783
2790
  break if cursor == "0"
2784
2791
  end
@@ -2842,12 +2849,12 @@ class Redis
2842
2849
  end
2843
2850
  end
2844
2851
 
2845
-
2846
2852
  # Query a sorted set representing a geospatial index to fetch members matching a
2847
2853
  # given maximum distance from a point
2848
2854
  #
2849
2855
  # @param [Array] args key, longitude, latitude, radius, unit(m|km|ft|mi)
2850
- # @param ['asc', 'desc'] sort sort returned items from the nearest to the farthest or the farthest to the nearest relative to the center
2856
+ # @param ['asc', 'desc'] sort sort returned items from the nearest to the farthest
2857
+ # or the farthest to the nearest relative to the center
2851
2858
  # @param [Integer] count limit the results to the first N matching items
2852
2859
  # @param ['WITHDIST', 'WITHCOORD', 'WITHHASH'] options to return additional information
2853
2860
  # @return [Array<String>] may be changed with `options`
@@ -2864,7 +2871,8 @@ class Redis
2864
2871
  # given maximum distance from an already existing member
2865
2872
  #
2866
2873
  # @param [Array] args key, member, radius, unit(m|km|ft|mi)
2867
- # @param ['asc', 'desc'] sort sort returned items from the nearest to the farthest or the farthest to the nearest relative to the center
2874
+ # @param ['asc', 'desc'] sort sort returned items from the nearest to the farthest or the farthest
2875
+ # to the nearest relative to the center
2868
2876
  # @param [Integer] count limit the results to the first N matching items
2869
2877
  # @param ['WITHDIST', 'WITHCOORD', 'WITHHASH'] options to return additional information
2870
2878
  # @return [Array<String>] may be changed with `options`
@@ -2881,7 +2889,8 @@ class Redis
2881
2889
  #
2882
2890
  # @param [String] key
2883
2891
  # @param [String, Array<String>] member one member or array of members
2884
- # @return [Array<Array<String>, nil>] returns array of elements, where each element is either array of longitude and latitude or nil
2892
+ # @return [Array<Array<String>, nil>] returns array of elements, where each
2893
+ # element is either array of longitude and latitude or nil
2885
2894
  def geopos(key, member)
2886
2895
  synchronize do |client|
2887
2896
  client.call([:geopos, key, member])
@@ -2945,10 +2954,14 @@ class Redis
2945
2954
  # @option opts [Boolean] :approximate whether to add `~` modifier of maxlen or not
2946
2955
  #
2947
2956
  # @return [String] the entry id
2948
- def xadd(key, entry, opts = {})
2957
+ def xadd(key, entry, approximate: nil, maxlen: nil, id: '*')
2949
2958
  args = [:xadd, key]
2950
- args.concat(['MAXLEN', (opts[:approximate] ? '~' : nil), opts[:maxlen]].compact) if opts[:maxlen]
2951
- args << (opts[:id] || '*')
2959
+ if maxlen
2960
+ args << "MAXLEN"
2961
+ args << "~" if approximate
2962
+ args << maxlen
2963
+ end
2964
+ args << id
2952
2965
  args.concat(entry.to_a.flatten)
2953
2966
  synchronize { |client| client.call(args) }
2954
2967
  end
@@ -3003,8 +3016,8 @@ class Redis
3003
3016
  # @param count [Integer] the number of entries as limit
3004
3017
  #
3005
3018
  # @return [Array<Array<String, Hash>>] the ids and entries pairs
3006
- def xrange(key, start = '-', _end = '+', count: nil)
3007
- args = [:xrange, key, start, _end]
3019
+ def xrange(key, start = '-', range_end = '+', count: nil)
3020
+ args = [:xrange, key, start, range_end]
3008
3021
  args.concat(['COUNT', count]) if count
3009
3022
  synchronize { |client| client.call(args, &HashifyStreamEntries) }
3010
3023
  end
@@ -3026,8 +3039,8 @@ class Redis
3026
3039
  # @params count [Integer] the number of entries as limit
3027
3040
  #
3028
3041
  # @return [Array<Array<String, Hash>>] the ids and entries pairs
3029
- def xrevrange(key, _end = '+', start = '-', count: nil)
3030
- args = [:xrevrange, key, _end, start]
3042
+ def xrevrange(key, range_end = '+', start = '-', count: nil)
3043
+ args = [:xrevrange, key, range_end, start]
3031
3044
  args.concat(['COUNT', count]) if count
3032
3045
  synchronize { |client| client.call(args, &HashifyStreamEntries) }
3033
3046
  end
@@ -3119,12 +3132,12 @@ class Redis
3119
3132
  # @option opts [Boolean] :noack whether message loss is acceptable or not
3120
3133
  #
3121
3134
  # @return [Hash{String => Hash{String => Hash}}] the entries
3122
- def xreadgroup(group, consumer, keys, ids, opts = {})
3135
+ def xreadgroup(group, consumer, keys, ids, count: nil, block: nil, noack: nil)
3123
3136
  args = [:xreadgroup, 'GROUP', group, consumer]
3124
- args << 'COUNT' << opts[:count] if opts[:count]
3125
- args << 'BLOCK' << opts[:block].to_i if opts[:block]
3126
- args << 'NOACK' if opts[:noack]
3127
- _xread(args, keys, ids, opts[:block])
3137
+ args << 'COUNT' << count if count
3138
+ args << 'BLOCK' << block.to_i if block
3139
+ args << 'NOACK' if noack
3140
+ _xread(args, keys, ids, block)
3128
3141
  end
3129
3142
 
3130
3143
  # Removes one or multiple entries from the pending entries list of a stream consumer group.
@@ -3234,8 +3247,8 @@ class Redis
3234
3247
  when "get-master-addr-by-name"
3235
3248
  reply
3236
3249
  else
3237
- if reply.kind_of?(Array)
3238
- if reply[0].kind_of?(Array)
3250
+ if reply.is_a?(Array)
3251
+ if reply[0].is_a?(Array)
3239
3252
  reply.map(&Hashify)
3240
3253
  else
3241
3254
  Hashify.call(reply)
@@ -3259,12 +3272,17 @@ class Redis
3259
3272
  def cluster(subcommand, *args)
3260
3273
  subcommand = subcommand.to_s.downcase
3261
3274
  block = case subcommand
3262
- when 'slots' then HashifyClusterSlots
3263
- when 'nodes' then HashifyClusterNodes
3264
- when 'slaves' then HashifyClusterSlaves
3265
- when 'info' then HashifyInfo
3266
- else Noop
3267
- end
3275
+ when 'slots'
3276
+ HashifyClusterSlots
3277
+ when 'nodes'
3278
+ HashifyClusterNodes
3279
+ when 'slaves'
3280
+ HashifyClusterSlaves
3281
+ when 'info'
3282
+ HashifyInfo
3283
+ else
3284
+ Noop
3285
+ end
3268
3286
 
3269
3287
  # @see https://github.com/antirez/redis/blob/unstable/src/redis-trib.rb#L127 raw reply expected
3270
3288
  block = Noop unless @cluster_mode
@@ -3299,21 +3317,21 @@ class Redis
3299
3317
  return @original_client.connection_info if @cluster_mode
3300
3318
 
3301
3319
  {
3302
- host: @original_client.host,
3303
- port: @original_client.port,
3304
- db: @original_client.db,
3305
- id: @original_client.id,
3320
+ host: @original_client.host,
3321
+ port: @original_client.port,
3322
+ db: @original_client.db,
3323
+ id: @original_client.id,
3306
3324
  location: @original_client.location
3307
3325
  }
3308
3326
  end
3309
3327
 
3310
- def method_missing(command, *args)
3328
+ def method_missing(command, *args) # rubocop:disable Style/MissingRespondToMissing
3311
3329
  synchronize do |client|
3312
3330
  client.call([command] + args)
3313
3331
  end
3314
3332
  end
3315
3333
 
3316
- private
3334
+ private
3317
3335
 
3318
3336
  # Commands returning 1 for true and 0 for false may be executed in a pipeline
3319
3337
  # where the method call will return nil. Propagate the nil instead of falsely
@@ -3393,10 +3411,10 @@ private
3393
3411
 
3394
3412
  HashifyStreamPendings = lambda { |reply|
3395
3413
  {
3396
- 'size' => reply[0],
3414
+ 'size' => reply[0],
3397
3415
  'min_entry_id' => reply[1],
3398
3416
  'max_entry_id' => reply[2],
3399
- 'consumers' => reply[3].nil? ? {} : reply[3].to_h
3417
+ 'consumers' => reply[3].nil? ? {} : reply[3].to_h
3400
3418
  }
3401
3419
  }
3402
3420
 
@@ -3405,8 +3423,8 @@ private
3405
3423
  {
3406
3424
  'entry_id' => arr[0],
3407
3425
  'consumer' => arr[1],
3408
- 'elapsed' => arr[2],
3409
- 'count' => arr[3]
3426
+ 'elapsed' => arr[2],
3427
+ 'count' => arr[3]
3410
3428
  }
3411
3429
  end
3412
3430
  }
@@ -3414,15 +3432,15 @@ private
3414
3432
  HashifyClusterNodeInfo = lambda { |str|
3415
3433
  arr = str.split(' ')
3416
3434
  {
3417
- 'node_id' => arr[0],
3418
- 'ip_port' => arr[1],
3419
- 'flags' => arr[2].split(','),
3435
+ 'node_id' => arr[0],
3436
+ 'ip_port' => arr[1],
3437
+ 'flags' => arr[2].split(','),
3420
3438
  'master_node_id' => arr[3],
3421
- 'ping_sent' => arr[4],
3422
- 'pong_recv' => arr[5],
3423
- 'config_epoch' => arr[6],
3424
- 'link_state' => arr[7],
3425
- 'slots' => arr[8].nil? ? nil : Range.new(*arr[8].split('-'))
3439
+ 'ping_sent' => arr[4],
3440
+ 'pong_recv' => arr[5],
3441
+ 'config_epoch' => arr[6],
3442
+ 'link_state' => arr[7],
3443
+ 'slots' => arr[8].nil? ? nil : Range.new(*arr[8].split('-'))
3426
3444
  }
3427
3445
  }
3428
3446
 
@@ -3433,9 +3451,9 @@ private
3433
3451
  replicas = arr[3..-1].map { |r| { 'ip' => r[0], 'port' => r[1], 'node_id' => r[2] } }
3434
3452
  {
3435
3453
  'start_slot' => first_slot,
3436
- 'end_slot' => last_slot,
3437
- 'master' => master,
3438
- 'replicas' => replicas
3454
+ 'end_slot' => last_slot,
3455
+ 'master' => master,
3456
+ 'replicas' => replicas
3439
3457
  }
3440
3458
  end
3441
3459
  }