redis 5.0.6 → 5.0.8

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
2
  SHA256:
3
- metadata.gz: 7b000349da8b2f7ae8ed14909175306d2c719a9873bf1dabe05c4719ae96d0da
4
- data.tar.gz: fdcda2f50f9d33265f7ba24d3f29a2e078fabe5240e1eaf01efae51e0b83eb0b
3
+ metadata.gz: 68e827844bdac2fa5954e99fd259060a232719927db426788368408b02011eff
4
+ data.tar.gz: 46f7f0f74538f29ac4b8f72bc0e2cecaeeea44568174c25d61cf3532869c9f3d
5
5
  SHA512:
6
- metadata.gz: 990972ebefe548f952cbf630708298f52c1856fa5a142a341f2548bd9173f03f0106d6b745c7e39cc5baa9f084d5fea5e4c0bf42cf1d42df94e404f3558d7816
7
- data.tar.gz: e52615e0d5b7ca9d554ffc540fdfec524d2aed74ac1c7fc3c727d3096504aa81ff43a85b9e2ce7b21da87edf21ca5f92197171ff1b1c62fa85c7551839e9df83
6
+ metadata.gz: 996e87442dda9f5750a529b9a14627c371b8e042bc6a7c0a5a32d0c36effa24728d10404a983cea0ef07f19c6e6f1571ac75af1d14a5480021445e23a7eb24e5
7
+ data.tar.gz: d36cc39b9d847badfe8d63a94ac74ee588a4fa856581e93f113261156be4b6d6e802b207af6fbe526ff7fb3a00b00f27e4f935a2164da18eb329b6eb007dfb4d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Unreleased
2
2
 
3
+ # 5.0.8
4
+
5
+ - Fix `Redis#without_reconnect` for sentinel clients. Fix #1212.
6
+ - Add `sentinel_username`, `sentinel_password` for sentinel clients. Bump `redis-client` to `>=0.17.0`. See #1213
7
+
8
+ # 5.0.7
9
+
10
+ - Fix compatibility with `redis-client 0.15.0` when using Redis Sentinel. Fix #1209.
11
+
3
12
  # 5.0.6
4
13
 
5
14
  - Wait for an extra `config.read_timeout` in blocking commands rather than an arbitrary 100ms. See #1175.
@@ -27,6 +36,7 @@
27
36
 
28
37
  # 5.0.0
29
38
 
39
+ - Default client timeout decreased from 5 seconds to 1 second.
30
40
  - Eagerly and strictly cast Integer and Float parameters.
31
41
  - Allow to call `subscribe`, `unsubscribe`, `psubscribe` and `punsubscribe` from a subscribed client. See #1131.
32
42
  - Use `MD5` for hashing server nodes in `Redis::Distributed`. This should improve keys distribution among servers. See #1089.
@@ -49,6 +59,10 @@
49
59
  - Removed the `synchrony` driver.
50
60
  - Removed `Redis.exists_returns_integer`, it's now always enabled.
51
61
 
62
+ # 4.8.1
63
+
64
+ * Automatically reconnect after fork regardless of `reconnect_attempts`
65
+
52
66
  # 4.8.0
53
67
 
54
68
  * Introduce `sadd?` and `srem?` as boolean returning versions of `sadd` and `srem`.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # redis-rb [![Build Status][gh-actions-image]][gh-actions-link] [![Inline docs][inchpages-image]][inchpages-link]
1
+ # redis-rb [![Build Status][gh-actions-image]][gh-actions-link] [![Inline docs][rdoc-master-image]][rdoc-master-link]
2
2
 
3
3
  A Ruby client that tries to match [Redis][redis-home]' API one-to-one, while still providing an idiomatic interface.
4
4
 
@@ -103,7 +103,7 @@ To connect using Sentinel, use:
103
103
  SENTINELS = [{ host: "127.0.0.1", port: 26380 },
104
104
  { host: "127.0.0.1", port: 26381 }]
105
105
 
106
- redis = Redis.new(url: "redis://mymaster", sentinels: SENTINELS, role: :master)
106
+ redis = Redis.new(name: "mymaster", sentinels: SENTINELS, role: :master)
107
107
  ```
108
108
 
109
109
  * The master name identifies a group of Redis instances composed of a master
@@ -120,13 +120,39 @@ but a few so that if one is down the client will try the next one. The client
120
120
  is able to remember the last Sentinel that was able to reply correctly and will
121
121
  use it for the next requests.
122
122
 
123
- 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.
123
+ To [authenticate](https://redis.io/docs/management/sentinel/#configuring-sentinel-instances-with-authentication) Sentinel itself, you can specify the `sentinel_username` and `sentinel_password`. Exclude the `sentinel_username` option if you're using password-only authentication.
124
124
 
125
125
  ```ruby
126
- SENTINELS = [{ host: '127.0.0.1', port: 26380, password: 'mysecret' },
127
- { host: '127.0.0.1', port: 26381, password: 'mysecret' }]
126
+ SENTINELS = [{ host: '127.0.0.1', port: 26380},
127
+ { host: '127.0.0.1', port: 26381}]
128
128
 
129
- redis = Redis.new(name: 'mymaster', sentinels: SENTINELS, role: :master)
129
+ redis = Redis.new(name: 'mymaster', sentinels: SENTINELS, sentinel_username: 'appuser', sentinel_password: 'mysecret', role: :master)
130
+ ```
131
+
132
+ If you specify a username and/or password at the top level for your main Redis instance, Sentinel *will not* using thouse credentials
133
+
134
+ ```ruby
135
+ # Use 'mysecret' to authenticate against the mymaster instance, but skip authentication for the sentinels:
136
+ SENTINELS = [{ host: '127.0.0.1', port: 26380 },
137
+ { host: '127.0.0.1', port: 26381 }]
138
+
139
+ redis = Redis.new(name: 'mymaster', sentinels: SENTINELS, role: :master, password: 'mysecret')
140
+ ```
141
+
142
+ So you have to provide Sentinel credential and Redis explictly even they are the same
143
+
144
+ ```ruby
145
+ # Use 'mysecret' to authenticate against the mymaster instance and sentinel
146
+ SENTINELS = [{ host: '127.0.0.1', port: 26380 },
147
+ { host: '127.0.0.1', port: 26381 }]
148
+
149
+ redis = Redis.new(name: 'mymaster', sentinels: SENTINELS, role: :master, password: 'mysecret', sentinel_password: 'mysecret')
150
+ ```
151
+
152
+ Also the `name`, `password`, `username` and `db` for Redis instance can be passed as an url:
153
+
154
+ ```ruby
155
+ redis = Redis.new(url: "redis://appuser:mysecret@mymaster/10", sentinels: SENTINELS, role: :master)
130
156
  ```
131
157
 
132
158
  ## Cluster support
@@ -394,11 +420,11 @@ client and evangelized Redis in Rubyland. Thank you, Ezra.
394
420
  requests.
395
421
 
396
422
 
397
- [inchpages-image]: https://inch-ci.org/github/redis/redis-rb.svg
398
- [inchpages-link]: https://inch-ci.org/github/redis/redis-rb
399
- [redis-commands]: https://redis.io/commands
400
- [redis-home]: https://redis.io
401
- [redis-url]: http://www.iana.org/assignments/uri-schemes/prov/redis
402
- [gh-actions-image]: https://github.com/redis/redis-rb/workflows/Test/badge.svg
403
- [gh-actions-link]: https://github.com/redis/redis-rb/actions
404
- [rubydoc]: http://www.rubydoc.info/gems/redis
423
+ [rdoc-master-image]: https://img.shields.io/badge/docs-rdoc.info-blue.svg
424
+ [rdoc-master-link]: https://rubydoc.info/github/redis/redis-rb
425
+ [redis-commands]: https://redis.io/commands
426
+ [redis-home]: https://redis.io
427
+ [redis-url]: https://www.iana.org/assignments/uri-schemes/prov/redis
428
+ [gh-actions-image]: https://github.com/redis/redis-rb/workflows/Test/badge.svg
429
+ [gh-actions-link]: https://github.com/redis/redis-rb/actions
430
+ [rubydoc]: https://rubydoc.info/gems/redis
data/lib/redis/client.rb CHANGED
@@ -24,7 +24,24 @@ class Redis
24
24
  end
25
25
 
26
26
  def sentinel(**kwargs)
27
- super(protocol: 2, **kwargs)
27
+ super(protocol: 2, **kwargs, client_implementation: ::RedisClient)
28
+ end
29
+
30
+ def translate_error!(error)
31
+ redis_error = translate_error_class(error.class)
32
+ raise redis_error, error.message, error.backtrace
33
+ end
34
+
35
+ private
36
+
37
+ def translate_error_class(error_class)
38
+ ERROR_MAPPING.fetch(error_class)
39
+ rescue IndexError
40
+ if (client_error = error_class.ancestors.find { |a| ERROR_MAPPING[a] })
41
+ ERROR_MAPPING[error_class] = ERROR_MAPPING[client_error]
42
+ else
43
+ raise
44
+ end
28
45
  end
29
46
  end
30
47
 
@@ -72,7 +89,7 @@ class Redis
72
89
  def call_v(command, &block)
73
90
  super(command, &block)
74
91
  rescue ::RedisClient::Error => error
75
- translate_error!(error)
92
+ Client.translate_error!(error)
76
93
  end
77
94
 
78
95
  def blocking_call_v(timeout, command, &block)
@@ -85,44 +102,23 @@ class Redis
85
102
 
86
103
  super(timeout, command, &block)
87
104
  rescue ::RedisClient::Error => error
88
- translate_error!(error)
105
+ Client.translate_error!(error)
89
106
  end
90
107
 
91
108
  def pipelined
92
109
  super
93
110
  rescue ::RedisClient::Error => error
94
- translate_error!(error)
111
+ Client.translate_error!(error)
95
112
  end
96
113
 
97
114
  def multi
98
115
  super
99
116
  rescue ::RedisClient::Error => error
100
- translate_error!(error)
101
- end
102
-
103
- def disable_reconnection(&block)
104
- ensure_connected(retryable: false, &block)
117
+ Client.translate_error!(error)
105
118
  end
106
119
 
107
120
  def inherit_socket!
108
121
  @inherit_socket = true
109
122
  end
110
-
111
- private
112
-
113
- def translate_error!(error)
114
- redis_error = translate_error_class(error.class)
115
- raise redis_error, error.message, error.backtrace
116
- end
117
-
118
- def translate_error_class(error_class)
119
- ERROR_MAPPING.fetch(error_class)
120
- rescue IndexError
121
- if (client_error = error_class.ancestors.find { |a| ERROR_MAPPING[a] })
122
- ERROR_MAPPING[error_class] = ERROR_MAPPING[client_error]
123
- else
124
- raise
125
- end
126
- end
127
123
  end
128
124
  end
@@ -183,6 +183,60 @@ class Redis
183
183
  send_blocking_command(command, timeout)
184
184
  end
185
185
 
186
+ # Pops one or more elements from the first non-empty list key from the list
187
+ # of provided key names. If lists are empty, blocks until timeout has passed.
188
+ #
189
+ # @example Popping a element
190
+ # redis.blmpop(1.0, 'list')
191
+ # #=> ['list', ['a']]
192
+ # @example With count option
193
+ # redis.blmpop(1.0, 'list', count: 2)
194
+ # #=> ['list', ['a', 'b']]
195
+ #
196
+ # @params timeout [Float] a float value specifying the maximum number of seconds to block) elapses.
197
+ # A timeout of zero can be used to block indefinitely.
198
+ # @params key [String, Array<String>] one or more keys with lists
199
+ # @params modifier [String]
200
+ # - when `"LEFT"` - the elements popped are those from the left of the list
201
+ # - when `"RIGHT"` - the elements popped are those from the right of the list
202
+ # @params count [Integer] a number of elements to pop
203
+ #
204
+ # @return [Array<String, Array<String, Float>>] list of popped elements or nil
205
+ def blmpop(timeout, *keys, modifier: "LEFT", count: nil)
206
+ raise ArgumentError, "Pick either LEFT or RIGHT" unless modifier == "LEFT" || modifier == "RIGHT"
207
+
208
+ args = [:lmpop, keys.size, *keys, modifier]
209
+ args << "COUNT" << Integer(count) if count
210
+
211
+ send_blocking_command(args, timeout)
212
+ end
213
+
214
+ # Pops one or more elements from the first non-empty list key from the list
215
+ # of provided key names.
216
+ #
217
+ # @example Popping a element
218
+ # redis.lmpop('list')
219
+ # #=> ['list', ['a']]
220
+ # @example With count option
221
+ # redis.lmpop('list', count: 2)
222
+ # #=> ['list', ['a', 'b']]
223
+ #
224
+ # @params key [String, Array<String>] one or more keys with lists
225
+ # @params modifier [String]
226
+ # - when `"LEFT"` - the elements popped are those from the left of the list
227
+ # - when `"RIGHT"` - the elements popped are those from the right of the list
228
+ # @params count [Integer] a number of elements to pop
229
+ #
230
+ # @return [Array<String, Array<String, Float>>] list of popped elements or nil
231
+ def lmpop(*keys, modifier: "LEFT", count: nil)
232
+ raise ArgumentError, "Pick either LEFT or RIGHT" unless modifier == "LEFT" || modifier == "RIGHT"
233
+
234
+ args = [:lmpop, keys.size, *keys, modifier]
235
+ args << "COUNT" << Integer(count) if count
236
+
237
+ send_command(args)
238
+ end
239
+
186
240
  # Get an element from a list by its index.
187
241
  #
188
242
  # @param [String] key
@@ -49,6 +49,27 @@ class Redis
49
49
  def pubsub(subcommand, *args)
50
50
  send_command([:pubsub, subcommand] + args)
51
51
  end
52
+
53
+ # Post a message to a channel in a shard.
54
+ def spublish(channel, message)
55
+ send_command([:spublish, channel, message])
56
+ end
57
+
58
+ # Listen for messages published to the given channels in a shard.
59
+ def ssubscribe(*channels, &block)
60
+ _subscription(:ssubscribe, 0, channels, block)
61
+ end
62
+
63
+ # Listen for messages published to the given channels in a shard.
64
+ # Throw a timeout error if there is no messages for a timeout period.
65
+ def ssubscribe_with_timeout(timeout, *channels, &block)
66
+ _subscription(:ssubscribe_with_timeout, timeout, channels, block)
67
+ end
68
+
69
+ # Stop listening for messages posted to the given channels in a shard.
70
+ def sunsubscribe(*channels)
71
+ _subscription(:sunsubscribe, 0, channels, nil)
72
+ end
52
73
  end
53
74
  end
54
75
  end
@@ -167,6 +167,72 @@ class Redis
167
167
  end
168
168
  end
169
169
 
170
+ # Removes and returns up to count members with scores in the sorted set stored at key.
171
+ #
172
+ # @example Popping a member
173
+ # redis.bzmpop('zset')
174
+ # #=> ['zset', ['a', 1.0]]
175
+ # @example With count option
176
+ # redis.bzmpop('zset', count: 2)
177
+ # #=> ['zset', [['a', 1.0], ['b', 2.0]]
178
+ #
179
+ # @params timeout [Float] a float value specifying the maximum number of seconds to block) elapses.
180
+ # A timeout of zero can be used to block indefinitely.
181
+ # @params key [String, Array<String>] one or more keys with sorted sets
182
+ # @params modifier [String]
183
+ # - when `"MIN"` - the elements popped are those with lowest scores
184
+ # - when `"MAX"` - the elements popped are those with the highest scores
185
+ # @params count [Integer] a number of members to pop
186
+ #
187
+ # @return [Array<String, Array<String, Float>>] list of popped elements and scores
188
+ def bzmpop(timeout, *keys, modifier: "MIN", count: nil)
189
+ raise ArgumentError, "Pick either MIN or MAX" unless modifier == "MIN" || modifier == "MAX"
190
+
191
+ args = [:bzmpop, timeout, keys.size, *keys, modifier]
192
+ args << "COUNT" << Integer(count) if count
193
+
194
+ send_blocking_command(args, timeout) do |response|
195
+ response&.map do |entry|
196
+ case entry
197
+ when String then entry
198
+ when Array then entry.map { |pair| FloatifyPairs.call(pair) }.flatten(1)
199
+ end
200
+ end
201
+ end
202
+ end
203
+
204
+ # Removes and returns up to count members with scores in the sorted set stored at key.
205
+ #
206
+ # @example Popping a member
207
+ # redis.zmpop('zset')
208
+ # #=> ['zset', ['a', 1.0]]
209
+ # @example With count option
210
+ # redis.zmpop('zset', count: 2)
211
+ # #=> ['zset', [['a', 1.0], ['b', 2.0]]
212
+ #
213
+ # @params key [String, Array<String>] one or more keys with sorted sets
214
+ # @params modifier [String]
215
+ # - when `"MIN"` - the elements popped are those with lowest scores
216
+ # - when `"MAX"` - the elements popped are those with the highest scores
217
+ # @params count [Integer] a number of members to pop
218
+ #
219
+ # @return [Array<String, Array<String, Float>>] list of popped elements and scores
220
+ def zmpop(*keys, modifier: "MIN", count: nil)
221
+ raise ArgumentError, "Pick either MIN or MAX" unless modifier == "MIN" || modifier == "MAX"
222
+
223
+ args = [:zmpop, keys.size, *keys, modifier]
224
+ args << "COUNT" << Integer(count) if count
225
+
226
+ send_command(args) do |response|
227
+ response&.map do |entry|
228
+ case entry
229
+ when String then entry
230
+ when Array then entry.map { |pair| FloatifyPairs.call(pair) }.flatten(1)
231
+ end
232
+ end
233
+ end
234
+ end
235
+
170
236
  # Removes and returns up to count members with the highest scores in the sorted set stored at keys,
171
237
  # or block until one is available.
172
238
  #
@@ -542,6 +542,20 @@ class Redis
542
542
  node_for(key).ltrim(key, start, stop)
543
543
  end
544
544
 
545
+ # Iterate over keys, blocking and removing elements from the first non empty liist found.
546
+ def blmpop(timeout, *keys, modifier: "LEFT", count: nil)
547
+ ensure_same_node(:blmpop, keys) do |node|
548
+ node.blmpop(timeout, *keys, modifier: modifier, count: count)
549
+ end
550
+ end
551
+
552
+ # Iterate over keys, removing elements from the first non list found.
553
+ def lmpop(*keys, modifier: "LEFT", count: nil)
554
+ ensure_same_node(:lmpop, keys) do |node|
555
+ node.lmpop(*keys, modifier: modifier, count: count)
556
+ end
557
+ end
558
+
545
559
  # Get the number of members in a set.
546
560
  def scard(key)
547
561
  node_for(key).scard(key)
@@ -694,6 +708,20 @@ class Redis
694
708
  node_for(key).zmscore(key, *members)
695
709
  end
696
710
 
711
+ # Iterate over keys, blocking and removing members from the first non empty sorted set found.
712
+ def bzmpop(timeout, *keys, modifier: "MIN", count: nil)
713
+ ensure_same_node(:bzmpop, keys) do |node|
714
+ node.bzmpop(timeout, *keys, modifier: modifier, count: count)
715
+ end
716
+ end
717
+
718
+ # Iterate over keys, removing members from the first non empty sorted set found.
719
+ def zmpop(*keys, modifier: "MIN", count: nil)
720
+ ensure_same_node(:zmpop, keys) do |node|
721
+ node.zmpop(*keys, modifier: modifier, count: count)
722
+ end
723
+ end
724
+
697
725
  # Return a range of members in a sorted set, by index, score or lexicographical ordering.
698
726
  def zrange(key, start, stop, **options)
699
727
  node_for(key).zrange(key, start, stop, **options)
@@ -29,6 +29,14 @@ class Redis
29
29
  subscription("psubscribe", "punsubscribe", channels, block, timeout)
30
30
  end
31
31
 
32
+ def ssubscribe(*channels, &block)
33
+ subscription("ssubscribe", "sunsubscribe", channels, block)
34
+ end
35
+
36
+ def ssubscribe_with_timeout(timeout, *channels, &block)
37
+ subscription("ssubscribe", "sunsubscribe", channels, block, timeout)
38
+ end
39
+
32
40
  def unsubscribe(*channels)
33
41
  call_v([:unsubscribe, *channels])
34
42
  end
@@ -37,6 +45,10 @@ class Redis
37
45
  call_v([:punsubscribe, *channels])
38
46
  end
39
47
 
48
+ def sunsubscribe(*channels)
49
+ call_v([:sunsubscribe, *channels])
50
+ end
51
+
40
52
  def close
41
53
  @client.close
42
54
  end
@@ -46,7 +58,11 @@ class Redis
46
58
  def subscription(start, stop, channels, block, timeout = 0)
47
59
  sub = Subscription.new(&block)
48
60
 
49
- call_v([start, *channels])
61
+ case start
62
+ when "ssubscribe" then channels.each { |c| call_v([start, c]) } # avoid cross-slot keys
63
+ else call_v([start, *channels])
64
+ end
65
+
50
66
  while event = @client.next_event(timeout)
51
67
  if event.is_a?(::RedisClient::CommandError)
52
68
  raise Client::ERROR_MAPPING.fetch(event.class), event.message
@@ -94,5 +110,17 @@ class Redis
94
110
  def pmessage(&block)
95
111
  @callbacks["pmessage"] = block
96
112
  end
113
+
114
+ def ssubscribe(&block)
115
+ @callbacks["ssubscribe"] = block
116
+ end
117
+
118
+ def sunsubscribe(&block)
119
+ @callbacks["sunsubscribe"] = block
120
+ end
121
+
122
+ def smessage(&block)
123
+ @callbacks["smessage"] = block
124
+ end
97
125
  end
98
126
  end
data/lib/redis/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Redis
4
- VERSION = '5.0.6'
4
+ VERSION = '5.0.8'
5
5
  end
data/lib/redis.rb CHANGED
@@ -45,7 +45,7 @@ class Redis
45
45
  # @option options [String] :host ("127.0.0.1") server hostname
46
46
  # @option options [Integer] :port (6379) server port
47
47
  # @option options [String] :path path to server socket (overrides host and port)
48
- # @option options [Float] :timeout (5.0) timeout in seconds
48
+ # @option options [Float] :timeout (1.0) timeout in seconds
49
49
  # @option options [Float] :connect_timeout (same as timeout) timeout for initial connect in seconds
50
50
  # @option options [String] :username Username to authenticate against server
51
51
  # @option options [String] :password Password to authenticate against server
@@ -137,21 +137,6 @@ class Redis
137
137
  end
138
138
 
139
139
  if options.key?(:sentinels)
140
- if url = options.delete(:url)
141
- uri = URI.parse(url)
142
- if !options.key?(:name) && uri.host
143
- options[:name] = uri.host
144
- end
145
-
146
- if !options.key?(:password) && uri.password && !uri.password.empty?
147
- options[:password] = uri.password
148
- end
149
-
150
- if !options.key?(:username) && uri.user && !uri.user.empty?
151
- options[:username] = uri.user
152
- end
153
- end
154
-
155
140
  Client.sentinel(**options).new_client
156
141
  else
157
142
  Client.config(**options).new_client
@@ -166,6 +151,8 @@ class Redis
166
151
  @monitor.synchronize do
167
152
  @client.call_v(command, &block)
168
153
  end
154
+ rescue ::RedisClient::Error => error
155
+ Client.translate_error!(error)
169
156
  end
170
157
 
171
158
  def send_blocking_command(command, timeout, &block)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redis
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.6
4
+ version: 5.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ezra Zygmuntowicz
@@ -16,7 +16,7 @@ authors:
16
16
  autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
- date: 2023-01-16 00:00:00.000000000 Z
19
+ date: 2023-10-23 00:00:00.000000000 Z
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  name: redis-client
@@ -24,14 +24,14 @@ dependencies:
24
24
  requirements:
25
25
  - - ">="
26
26
  - !ruby/object:Gem::Version
27
- version: 0.9.0
27
+ version: 0.17.0
28
28
  type: :runtime
29
29
  prerelease: false
30
30
  version_requirements: !ruby/object:Gem::Requirement
31
31
  requirements:
32
32
  - - ">="
33
33
  - !ruby/object:Gem::Version
34
- version: 0.9.0
34
+ version: 0.17.0
35
35
  description: |2
36
36
  A Ruby client that tries to match Redis' API one-to-one, while still
37
37
  providing an idiomatic interface.
@@ -75,9 +75,9 @@ licenses:
75
75
  metadata:
76
76
  bug_tracker_uri: https://github.com/redis/redis-rb/issues
77
77
  changelog_uri: https://github.com/redis/redis-rb/blob/master/CHANGELOG.md
78
- documentation_uri: https://www.rubydoc.info/gems/redis/5.0.6
78
+ documentation_uri: https://www.rubydoc.info/gems/redis/5.0.8
79
79
  homepage_uri: https://github.com/redis/redis-rb
80
- source_code_uri: https://github.com/redis/redis-rb/tree/v5.0.6
80
+ source_code_uri: https://github.com/redis/redis-rb/tree/v5.0.8
81
81
  post_install_message:
82
82
  rdoc_options: []
83
83
  require_paths:
@@ -93,7 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
93
93
  - !ruby/object:Gem::Version
94
94
  version: '0'
95
95
  requirements: []
96
- rubygems_version: 3.1.2
96
+ rubygems_version: 3.3.7
97
97
  signing_key:
98
98
  specification_version: 4
99
99
  summary: A Ruby client library for Redis