redis 5.1.0 → 5.4.1
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 +4 -4
- data/CHANGELOG.md +21 -0
- data/README.md +27 -4
- data/lib/redis/client.rb +10 -3
- data/lib/redis/commands/hashes.rb +4 -0
- data/lib/redis/commands/keys.rb +6 -0
- data/lib/redis/commands/lists.rb +1 -1
- data/lib/redis/commands/pubsub.rb +6 -0
- data/lib/redis/commands/sets.rb +4 -0
- data/lib/redis/commands/sorted_sets.rb +44 -6
- data/lib/redis/commands/streams.rb +10 -3
- data/lib/redis/commands.rb +7 -5
- data/lib/redis/distributed.rb +8 -4
- data/lib/redis/errors.rb +5 -0
- data/lib/redis/pipeline.rb +13 -9
- data/lib/redis/version.rb +1 -1
- data/lib/redis.rb +6 -3
- metadata +8 -11
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5d76a0d8a8a0361f991dc110219ffc77c12503148f9ece9586dd274321283265
|
|
4
|
+
data.tar.gz: fab1b1d4d3a5e22d2d952c98648a1412239f117a2c53bcbdf20ea7c43f456faa
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 042f0aa785647bb0e6f73ff50722ba5dcf440e3f5e817c7eec030b876b7d34ca8be42a7a5a5a1767eba66b7424a8d2e74fe8e7b9e0362eedefe4fb58878cdb57
|
|
7
|
+
data.tar.gz: 5bc22d99f3a77929f35c02072be18d663ca127c77055afadd55455d3f571f61bbd70853d6fd4414e0e11f601c20d68872e8f097fce109341e5bda39f6aadb9fe
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Unreleased
|
|
2
2
|
|
|
3
|
+
# 5.4.1
|
|
4
|
+
|
|
5
|
+
- Properly handle NOSCRIPT errors.
|
|
6
|
+
|
|
7
|
+
# 5.4.0
|
|
8
|
+
|
|
9
|
+
- Fix `blmpop` method to actually use `BLMPOP`, it was mistakenly issuing `LMPOP` commands.
|
|
10
|
+
- `xadd` now accepts a `minid:` argument.
|
|
11
|
+
- `zrank` and `zrevrank` now accepts `with_score:` argument.
|
|
12
|
+
- `Redis#call` now accept a block, allowing to use `Redis` instances where `RedisClient` is expected.
|
|
13
|
+
|
|
14
|
+
# 5.3.0
|
|
15
|
+
|
|
16
|
+
- Fix the return type of `hgetall` when used inside a `multi` transaction which is itself inside a pipeline.
|
|
17
|
+
|
|
18
|
+
# 5.2.0
|
|
19
|
+
|
|
20
|
+
- Now require Ruby 2.6 because `redis-client` does.
|
|
21
|
+
- Eagerly close subscribed connection when using `subscribe_with_timeout`. See #1259.
|
|
22
|
+
- Add `exception` flag in `pipelined` allowing failed commands to be returned in the result array when set to `false`.
|
|
23
|
+
|
|
3
24
|
# 5.1.0
|
|
4
25
|
|
|
5
26
|
- `multi` now accept a `watch` keyword argument like `redis-client`. See #1236.
|
data/README.md
CHANGED
|
@@ -34,7 +34,7 @@ You can also specify connection options as a [`redis://` URL][redis-url]:
|
|
|
34
34
|
redis = Redis.new(url: "redis://:p4ssw0rd@10.0.1.1:6380/15")
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
The client expects passwords with special
|
|
37
|
+
The client expects passwords with special characters to be URL-encoded (i.e.
|
|
38
38
|
`CGI.escape(password)`).
|
|
39
39
|
|
|
40
40
|
To connect to Redis listening on a Unix socket, try:
|
|
@@ -77,7 +77,7 @@ The client does not provide connection pooling. Each `Redis` instance
|
|
|
77
77
|
has one and only one connection to the server, and use of this connection
|
|
78
78
|
is protected by a mutex.
|
|
79
79
|
|
|
80
|
-
As such it is
|
|
80
|
+
As such it is heavily recommended to use the [`connection_pool` gem](https://github.com/mperham/connection_pool), e.g.:
|
|
81
81
|
|
|
82
82
|
```ruby
|
|
83
83
|
module MyApp
|
|
@@ -139,7 +139,7 @@ SENTINELS = [{ host: '127.0.0.1', port: 26380 },
|
|
|
139
139
|
redis = Redis.new(name: 'mymaster', sentinels: SENTINELS, role: :master, password: 'mysecret')
|
|
140
140
|
```
|
|
141
141
|
|
|
142
|
-
So you have to provide Sentinel credential and Redis
|
|
142
|
+
So you have to provide Sentinel credential and Redis explicitly even they are the same
|
|
143
143
|
|
|
144
144
|
```ruby
|
|
145
145
|
# Use 'mysecret' to authenticate against the mymaster instance and sentinel
|
|
@@ -191,6 +191,28 @@ end
|
|
|
191
191
|
# => ["OK"]
|
|
192
192
|
```
|
|
193
193
|
|
|
194
|
+
### Exception management
|
|
195
|
+
|
|
196
|
+
The `exception` flag in the `#pipelined` is a feature that modifies the pipeline execution behavior. When set
|
|
197
|
+
to `false`, it doesn't raise an exception when a command error occurs. Instead, it allows the pipeline to execute all
|
|
198
|
+
commands, and any failed command will be available in the returned array. (Defaults to `true`)
|
|
199
|
+
|
|
200
|
+
```ruby
|
|
201
|
+
results = redis.pipelined(exception: false) do |pipeline|
|
|
202
|
+
pipeline.set('key1', 'value1')
|
|
203
|
+
pipeline.lpush('key1', 'something') # This will fail
|
|
204
|
+
pipeline.set('key2', 'value2')
|
|
205
|
+
end
|
|
206
|
+
# results => ["OK", #<RedisClient::WrongTypeError: WRONGTYPE Operation against a key holding the wrong kind of value>, "OK"]
|
|
207
|
+
|
|
208
|
+
results.each do |result|
|
|
209
|
+
if result.is_a?(Redis::CommandError)
|
|
210
|
+
# Do something with the failed result
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
|
|
194
216
|
### Executing commands atomically
|
|
195
217
|
|
|
196
218
|
You can use `MULTI/EXEC` to run a number of commands in an atomic
|
|
@@ -251,6 +273,7 @@ See lib/redis/errors.rb for information about what exceptions are possible.
|
|
|
251
273
|
## Timeouts
|
|
252
274
|
|
|
253
275
|
The client allows you to configure connect, read, and write timeouts.
|
|
276
|
+
Starting in version 5.0, the default for each is 1. Before that, it was 5.
|
|
254
277
|
Passing a single `timeout` option will set all three values:
|
|
255
278
|
|
|
256
279
|
```ruby
|
|
@@ -383,7 +406,7 @@ gem "hiredis-client"
|
|
|
383
406
|
```
|
|
384
407
|
|
|
385
408
|
If your application doesn't call `Bundler.require`, you may have
|
|
386
|
-
to require it
|
|
409
|
+
to require it explicitly:
|
|
387
410
|
|
|
388
411
|
```ruby
|
|
389
412
|
require "hiredis-client"
|
data/lib/redis/client.rb
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'redis-client'
|
|
4
|
-
|
|
5
3
|
class Redis
|
|
6
4
|
class Client < ::RedisClient
|
|
7
5
|
ERROR_MAPPING = {
|
|
@@ -17,6 +15,9 @@ class Redis
|
|
|
17
15
|
RedisClient::ProtocolError => Redis::ProtocolError,
|
|
18
16
|
RedisClient::OutOfMemoryError => Redis::OutOfMemoryError,
|
|
19
17
|
}
|
|
18
|
+
if defined?(RedisClient::NoScriptError)
|
|
19
|
+
ERROR_MAPPING[RedisClient::NoScriptError] = Redis::NoScriptError
|
|
20
|
+
end
|
|
20
21
|
|
|
21
22
|
class << self
|
|
22
23
|
def config(**kwargs)
|
|
@@ -86,6 +87,12 @@ class Redis
|
|
|
86
87
|
undef_method :call_once_v
|
|
87
88
|
undef_method :blocking_call
|
|
88
89
|
|
|
90
|
+
def ensure_connected(retryable: true, &block)
|
|
91
|
+
super(retryable: retryable, &block)
|
|
92
|
+
rescue ::RedisClient::Error => error
|
|
93
|
+
Client.translate_error!(error)
|
|
94
|
+
end
|
|
95
|
+
|
|
89
96
|
def call_v(command, &block)
|
|
90
97
|
super(command, &block)
|
|
91
98
|
rescue ::RedisClient::Error => error
|
|
@@ -105,7 +112,7 @@ class Redis
|
|
|
105
112
|
Client.translate_error!(error)
|
|
106
113
|
end
|
|
107
114
|
|
|
108
|
-
def pipelined
|
|
115
|
+
def pipelined(exception: true)
|
|
109
116
|
super
|
|
110
117
|
rescue ::RedisClient::Error => error
|
|
111
118
|
Client.translate_error!(error)
|
|
@@ -222,6 +222,8 @@ class Redis
|
|
|
222
222
|
# - `:count => Integer`: return count keys at most per iteration
|
|
223
223
|
#
|
|
224
224
|
# @return [String, Array<[String, String]>] the next cursor and all found keys
|
|
225
|
+
#
|
|
226
|
+
# See the [Redis Server HSCAN documentation](https://redis.io/docs/latest/commands/hscan/) for further details
|
|
225
227
|
def hscan(key, cursor, **options)
|
|
226
228
|
_scan(:hscan, cursor, [key], **options) do |reply|
|
|
227
229
|
[reply[0], reply[1].each_slice(2).to_a]
|
|
@@ -239,6 +241,8 @@ class Redis
|
|
|
239
241
|
# - `:count => Integer`: return count keys at most per iteration
|
|
240
242
|
#
|
|
241
243
|
# @return [Enumerator] an enumerator for all found keys
|
|
244
|
+
#
|
|
245
|
+
# See the [Redis Server HSCAN documentation](https://redis.io/docs/latest/commands/hscan/) for further details
|
|
242
246
|
def hscan_each(key, **options, &block)
|
|
243
247
|
return to_enum(:hscan_each, key, **options) unless block_given?
|
|
244
248
|
|
data/lib/redis/commands/keys.rb
CHANGED
|
@@ -22,6 +22,8 @@ class Redis
|
|
|
22
22
|
# - `:type => String`: return keys only of the given type
|
|
23
23
|
#
|
|
24
24
|
# @return [String, Array<String>] the next cursor and all found keys
|
|
25
|
+
#
|
|
26
|
+
# See the [Redis Server SCAN documentation](https://redis.io/docs/latest/commands/scan/) for further details
|
|
25
27
|
def scan(cursor, **options)
|
|
26
28
|
_scan(:scan, cursor, [], **options)
|
|
27
29
|
end
|
|
@@ -46,6 +48,8 @@ class Redis
|
|
|
46
48
|
# - `:type => String`: return keys only of the given type
|
|
47
49
|
#
|
|
48
50
|
# @return [Enumerator] an enumerator for all found keys
|
|
51
|
+
#
|
|
52
|
+
# See the [Redis Server SCAN documentation](https://redis.io/docs/latest/commands/scan/) for further details
|
|
49
53
|
def scan_each(**options, &block)
|
|
50
54
|
return to_enum(:scan_each, **options) unless block_given?
|
|
51
55
|
|
|
@@ -282,6 +286,8 @@ class Redis
|
|
|
282
286
|
#
|
|
283
287
|
# @param [String] pattern
|
|
284
288
|
# @return [Array<String>]
|
|
289
|
+
#
|
|
290
|
+
# See the [Redis Server KEYS documentation](https://redis.io/docs/latest/commands/keys/) for further details
|
|
285
291
|
def keys(pattern = "*")
|
|
286
292
|
send_command([:keys, pattern]) do |reply|
|
|
287
293
|
if reply.is_a?(String)
|
data/lib/redis/commands/lists.rb
CHANGED
|
@@ -205,7 +205,7 @@ class Redis
|
|
|
205
205
|
def blmpop(timeout, *keys, modifier: "LEFT", count: nil)
|
|
206
206
|
raise ArgumentError, "Pick either LEFT or RIGHT" unless modifier == "LEFT" || modifier == "RIGHT"
|
|
207
207
|
|
|
208
|
-
args = [:
|
|
208
|
+
args = [:blmpop, timeout, keys.size, *keys, modifier]
|
|
209
209
|
args << "COUNT" << Integer(count) if count
|
|
210
210
|
|
|
211
211
|
send_blocking_command(args, timeout)
|
|
@@ -29,17 +29,23 @@ class Redis
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
# Listen for messages published to channels matching the given patterns.
|
|
32
|
+
# See the [Redis Server PSUBSCRIBE documentation](https://redis.io/docs/latest/commands/psubscribe/)
|
|
33
|
+
# for further details
|
|
32
34
|
def psubscribe(*channels, &block)
|
|
33
35
|
_subscription(:psubscribe, 0, channels, block)
|
|
34
36
|
end
|
|
35
37
|
|
|
36
38
|
# Listen for messages published to channels matching the given patterns.
|
|
37
39
|
# Throw a timeout error if there is no messages for a timeout period.
|
|
40
|
+
# See the [Redis Server PSUBSCRIBE documentation](https://redis.io/docs/latest/commands/psubscribe/)
|
|
41
|
+
# for further details
|
|
38
42
|
def psubscribe_with_timeout(timeout, *channels, &block)
|
|
39
43
|
_subscription(:psubscribe_with_timeout, timeout, channels, block)
|
|
40
44
|
end
|
|
41
45
|
|
|
42
46
|
# Stop listening for messages posted to channels matching the given patterns.
|
|
47
|
+
# See the [Redis Server PUNSUBSCRIBE documentation](https://redis.io/docs/latest/commands/punsubscribe/)
|
|
48
|
+
# for further details
|
|
43
49
|
def punsubscribe(*channels)
|
|
44
50
|
_subscription(:punsubscribe, 0, channels, nil)
|
|
45
51
|
end
|
data/lib/redis/commands/sets.rb
CHANGED
|
@@ -184,6 +184,8 @@ class Redis
|
|
|
184
184
|
# - `:count => Integer`: return count keys at most per iteration
|
|
185
185
|
#
|
|
186
186
|
# @return [String, Array<String>] the next cursor and all found members
|
|
187
|
+
#
|
|
188
|
+
# See the [Redis Server SSCAN documentation](https://redis.io/docs/latest/commands/sscan/) for further details
|
|
187
189
|
def sscan(key, cursor, **options)
|
|
188
190
|
_scan(:sscan, cursor, [key], **options)
|
|
189
191
|
end
|
|
@@ -199,6 +201,8 @@ class Redis
|
|
|
199
201
|
# - `:count => Integer`: return count keys at most per iteration
|
|
200
202
|
#
|
|
201
203
|
# @return [Enumerator] an enumerator for all keys in the set
|
|
204
|
+
#
|
|
205
|
+
# See the [Redis Server SSCAN documentation](https://redis.io/docs/latest/commands/sscan/) for further details
|
|
202
206
|
def sscan_each(key, **options, &block)
|
|
203
207
|
return to_enum(:sscan_each, key, **options) unless block_given?
|
|
204
208
|
|
|
@@ -454,21 +454,55 @@ class Redis
|
|
|
454
454
|
|
|
455
455
|
# Determine the index of a member in a sorted set.
|
|
456
456
|
#
|
|
457
|
+
# @example Retrieve member rank
|
|
458
|
+
# redis.zrank("zset", "a")
|
|
459
|
+
# # => 3
|
|
460
|
+
# @example Retrieve member rank with their score
|
|
461
|
+
# redis.zrank("zset", "a", :with_score => true)
|
|
462
|
+
# # => [3, 32.0]
|
|
463
|
+
#
|
|
457
464
|
# @param [String] key
|
|
458
465
|
# @param [String] member
|
|
459
|
-
#
|
|
460
|
-
|
|
461
|
-
|
|
466
|
+
#
|
|
467
|
+
# @return [Integer, [Integer, Float]]
|
|
468
|
+
# - when `:with_score` is not specified, an Integer
|
|
469
|
+
# - when `:with_score` is specified, a `[rank, score]` pair
|
|
470
|
+
def zrank(key, member, withscore: false, with_score: withscore)
|
|
471
|
+
args = [:zrank, key, member]
|
|
472
|
+
|
|
473
|
+
if with_score
|
|
474
|
+
args << "WITHSCORE"
|
|
475
|
+
block = FloatifyPair
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
send_command(args, &block)
|
|
462
479
|
end
|
|
463
480
|
|
|
464
481
|
# Determine the index of a member in a sorted set, with scores ordered from
|
|
465
482
|
# high to low.
|
|
466
483
|
#
|
|
484
|
+
# @example Retrieve member rank
|
|
485
|
+
# redis.zrevrank("zset", "a")
|
|
486
|
+
# # => 3
|
|
487
|
+
# @example Retrieve member rank with their score
|
|
488
|
+
# redis.zrevrank("zset", "a", :with_score => true)
|
|
489
|
+
# # => [3, 32.0]
|
|
490
|
+
#
|
|
467
491
|
# @param [String] key
|
|
468
492
|
# @param [String] member
|
|
469
|
-
#
|
|
470
|
-
|
|
471
|
-
|
|
493
|
+
#
|
|
494
|
+
# @return [Integer, [Integer, Float]]
|
|
495
|
+
# - when `:with_score` is not specified, an Integer
|
|
496
|
+
# - when `:with_score` is specified, a `[rank, score]` pair
|
|
497
|
+
def zrevrank(key, member, withscore: false, with_score: withscore)
|
|
498
|
+
args = [:zrevrank, key, member]
|
|
499
|
+
|
|
500
|
+
if with_score
|
|
501
|
+
args << "WITHSCORE"
|
|
502
|
+
block = FloatifyPair
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
send_command(args, &block)
|
|
472
506
|
end
|
|
473
507
|
|
|
474
508
|
# Remove all members in a sorted set within the given indexes.
|
|
@@ -817,6 +851,8 @@ class Redis
|
|
|
817
851
|
#
|
|
818
852
|
# @return [String, Array<[String, Float]>] the next cursor and all found
|
|
819
853
|
# members and scores
|
|
854
|
+
#
|
|
855
|
+
# See the [Redis Server ZSCAN documentation](https://redis.io/docs/latest/commands/zscan/) for further details
|
|
820
856
|
def zscan(key, cursor, **options)
|
|
821
857
|
_scan(:zscan, cursor, [key], **options) do |reply|
|
|
822
858
|
[reply[0], FloatifyPairs.call(reply[1])]
|
|
@@ -834,6 +870,8 @@ class Redis
|
|
|
834
870
|
# - `:count => Integer`: return count keys at most per iteration
|
|
835
871
|
#
|
|
836
872
|
# @return [Enumerator] an enumerator for all found scores and members
|
|
873
|
+
#
|
|
874
|
+
# See the [Redis Server ZSCAN documentation](https://redis.io/docs/latest/commands/zscan/) for further details
|
|
837
875
|
def zscan_each(key, **options, &block)
|
|
838
876
|
return to_enum(:zscan_each, key, **options) unless block_given?
|
|
839
877
|
|
|
@@ -41,18 +41,25 @@ class Redis
|
|
|
41
41
|
# @param opts [Hash] several options for `XADD` command
|
|
42
42
|
#
|
|
43
43
|
# @option opts [String] :id the entry id, default value is `*`, it means auto generation
|
|
44
|
-
# @option opts [Integer] :maxlen max length of entries
|
|
45
|
-
# @option opts [
|
|
44
|
+
# @option opts [Integer] :maxlen max length of entries to keep
|
|
45
|
+
# @option opts [Integer] :minid min id of entries to keep
|
|
46
|
+
# @option opts [Boolean] :approximate whether to add `~` modifier of maxlen/minid or not
|
|
46
47
|
# @option opts [Boolean] :nomkstream whether to add NOMKSTREAM, default is not to add
|
|
47
48
|
#
|
|
48
49
|
# @return [String] the entry id
|
|
49
|
-
def xadd(key, entry, approximate: nil, maxlen: nil, nomkstream: nil, id: '*')
|
|
50
|
+
def xadd(key, entry, approximate: nil, maxlen: nil, minid: nil, nomkstream: nil, id: '*')
|
|
50
51
|
args = [:xadd, key]
|
|
51
52
|
args << 'NOMKSTREAM' if nomkstream
|
|
52
53
|
if maxlen
|
|
54
|
+
raise ArgumentError, "can't supply both maxlen and minid" if minid
|
|
55
|
+
|
|
53
56
|
args << "MAXLEN"
|
|
54
57
|
args << "~" if approximate
|
|
55
58
|
args << maxlen
|
|
59
|
+
elsif minid
|
|
60
|
+
args << "MINID"
|
|
61
|
+
args << "~" if approximate
|
|
62
|
+
args << minid
|
|
56
63
|
end
|
|
57
64
|
args << id
|
|
58
65
|
args.concat(entry.flatten)
|
data/lib/redis/commands.rb
CHANGED
|
@@ -83,12 +83,14 @@ class Redis
|
|
|
83
83
|
end
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
FloatifyPair = lambda { |(first, score)|
|
|
87
|
+
[first, Floatify.call(score)]
|
|
88
|
+
}
|
|
89
|
+
|
|
86
90
|
FloatifyPairs = lambda { |value|
|
|
87
91
|
return value unless value.respond_to?(:each_slice)
|
|
88
92
|
|
|
89
|
-
value.each_slice(2).map
|
|
90
|
-
[member, Floatify.call(score)]
|
|
91
|
-
end
|
|
93
|
+
value.each_slice(2).map(&FloatifyPair)
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
HashifyInfo = lambda { |reply|
|
|
@@ -199,8 +201,8 @@ class Redis
|
|
|
199
201
|
# hash, are up to consumers.
|
|
200
202
|
#
|
|
201
203
|
# Redis error replies are raised as Ruby exceptions.
|
|
202
|
-
def call(*command)
|
|
203
|
-
send_command(command)
|
|
204
|
+
def call(*command, &block)
|
|
205
|
+
send_command(command, &block)
|
|
204
206
|
end
|
|
205
207
|
|
|
206
208
|
# Interact with the sentinel command (masters, master, slaves, failover)
|
data/lib/redis/distributed.rb
CHANGED
|
@@ -752,14 +752,14 @@ class Redis
|
|
|
752
752
|
end
|
|
753
753
|
|
|
754
754
|
# Determine the index of a member in a sorted set.
|
|
755
|
-
def zrank(key, member)
|
|
756
|
-
node_for(key).zrank(key, member)
|
|
755
|
+
def zrank(key, member, **options)
|
|
756
|
+
node_for(key).zrank(key, member, **options)
|
|
757
757
|
end
|
|
758
758
|
|
|
759
759
|
# Determine the index of a member in a sorted set, with scores ordered from
|
|
760
760
|
# high to low.
|
|
761
|
-
def zrevrank(key, member)
|
|
762
|
-
node_for(key).zrevrank(key, member)
|
|
761
|
+
def zrevrank(key, member, **options)
|
|
762
|
+
node_for(key).zrevrank(key, member, **options)
|
|
763
763
|
end
|
|
764
764
|
|
|
765
765
|
# Remove all members in a sorted set within the given indexes.
|
|
@@ -948,12 +948,16 @@ class Redis
|
|
|
948
948
|
end
|
|
949
949
|
|
|
950
950
|
# Listen for messages published to channels matching the given patterns.
|
|
951
|
+
# See the [Redis Server PSUBSCRIBE documentation](https://redis.io/docs/latest/commands/psubscribe/)
|
|
952
|
+
# for further details
|
|
951
953
|
def psubscribe(*channels, &block)
|
|
952
954
|
raise NotImplementedError
|
|
953
955
|
end
|
|
954
956
|
|
|
955
957
|
# Stop listening for messages posted to channels matching the given
|
|
956
958
|
# patterns.
|
|
959
|
+
# See the [Redis Server PUNSUBSCRIBE documentation](https://redis.io/docs/latest/commands/punsubscribe/)
|
|
960
|
+
# for further details
|
|
957
961
|
def punsubscribe(*channels)
|
|
958
962
|
raise NotImplementedError
|
|
959
963
|
end
|
data/lib/redis/errors.rb
CHANGED
|
@@ -29,6 +29,11 @@ class Redis
|
|
|
29
29
|
class OutOfMemoryError < CommandError
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
if defined?(RedisClient::NoScriptError)
|
|
33
|
+
class NoScriptError < CommandError
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
32
37
|
# Base error for connection related errors.
|
|
33
38
|
class BaseConnectionError < BaseError
|
|
34
39
|
end
|
data/lib/redis/pipeline.rb
CHANGED
|
@@ -6,9 +6,10 @@ class Redis
|
|
|
6
6
|
class PipelinedConnection
|
|
7
7
|
attr_accessor :db
|
|
8
8
|
|
|
9
|
-
def initialize(pipeline, futures = [])
|
|
9
|
+
def initialize(pipeline, futures = [], exception: true)
|
|
10
10
|
@pipeline = pipeline
|
|
11
11
|
@futures = futures
|
|
12
|
+
@exception = exception
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
include Commands
|
|
@@ -37,7 +38,7 @@ class Redis
|
|
|
37
38
|
end
|
|
38
39
|
|
|
39
40
|
def send_command(command, &block)
|
|
40
|
-
future = Future.new(command, block)
|
|
41
|
+
future = Future.new(command, block, @exception)
|
|
41
42
|
@pipeline.call_v(command) do |result|
|
|
42
43
|
future._set(result)
|
|
43
44
|
end
|
|
@@ -46,7 +47,7 @@ class Redis
|
|
|
46
47
|
end
|
|
47
48
|
|
|
48
49
|
def send_blocking_command(command, timeout, &block)
|
|
49
|
-
future = Future.new(command, block)
|
|
50
|
+
future = Future.new(command, block, @exception)
|
|
50
51
|
@pipeline.blocking_call_v(timeout, command) do |result|
|
|
51
52
|
future._set(result)
|
|
52
53
|
end
|
|
@@ -57,7 +58,7 @@ class Redis
|
|
|
57
58
|
|
|
58
59
|
class MultiConnection < PipelinedConnection
|
|
59
60
|
def multi
|
|
60
|
-
raise Redis::
|
|
61
|
+
raise Redis::BaseError, "Can't nest multi transaction"
|
|
61
62
|
end
|
|
62
63
|
|
|
63
64
|
private
|
|
@@ -79,10 +80,11 @@ class Redis
|
|
|
79
80
|
class Future < BasicObject
|
|
80
81
|
FutureNotReady = ::Redis::FutureNotReady.new
|
|
81
82
|
|
|
82
|
-
def initialize(command, coerce)
|
|
83
|
+
def initialize(command, coerce, exception)
|
|
83
84
|
@command = command
|
|
84
85
|
@object = FutureNotReady
|
|
85
86
|
@coerce = coerce
|
|
87
|
+
@exception = exception
|
|
86
88
|
end
|
|
87
89
|
|
|
88
90
|
def inspect
|
|
@@ -95,7 +97,7 @@ class Redis
|
|
|
95
97
|
end
|
|
96
98
|
|
|
97
99
|
def value
|
|
98
|
-
::Kernel.raise(@object) if @object.is_a?(::StandardError)
|
|
100
|
+
::Kernel.raise(@object) if @exception && @object.is_a?(::StandardError)
|
|
99
101
|
@object
|
|
100
102
|
end
|
|
101
103
|
|
|
@@ -116,12 +118,14 @@ class Redis
|
|
|
116
118
|
end
|
|
117
119
|
|
|
118
120
|
def _set(replies)
|
|
119
|
-
if replies
|
|
120
|
-
@futures.
|
|
121
|
+
@object = if replies
|
|
122
|
+
@futures.map.with_index do |future, index|
|
|
121
123
|
future._set(replies[index])
|
|
124
|
+
future.value
|
|
122
125
|
end
|
|
126
|
+
else
|
|
127
|
+
replies
|
|
123
128
|
end
|
|
124
|
-
@object = replies
|
|
125
129
|
end
|
|
126
130
|
end
|
|
127
131
|
end
|
data/lib/redis/version.rb
CHANGED
data/lib/redis.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "redis-client"
|
|
4
|
+
|
|
3
5
|
require "monitor"
|
|
4
6
|
require "redis/errors"
|
|
5
7
|
require "redis/commands"
|
|
@@ -99,10 +101,10 @@ class Redis
|
|
|
99
101
|
@client
|
|
100
102
|
end
|
|
101
103
|
|
|
102
|
-
def pipelined
|
|
104
|
+
def pipelined(exception: true)
|
|
103
105
|
synchronize do |client|
|
|
104
|
-
client.pipelined do |raw_pipeline|
|
|
105
|
-
yield PipelinedConnection.new(raw_pipeline)
|
|
106
|
+
client.pipelined(exception: exception) do |raw_pipeline|
|
|
107
|
+
yield PipelinedConnection.new(raw_pipeline, exception: exception)
|
|
106
108
|
end
|
|
107
109
|
end
|
|
108
110
|
end
|
|
@@ -175,6 +177,7 @@ class Redis
|
|
|
175
177
|
@subscription_client.send(method, *channels, &block)
|
|
176
178
|
end
|
|
177
179
|
ensure
|
|
180
|
+
@subscription_client&.close
|
|
178
181
|
@subscription_client = nil
|
|
179
182
|
end
|
|
180
183
|
else
|
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.1
|
|
4
|
+
version: 5.4.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ezra Zygmuntowicz
|
|
@@ -13,10 +13,9 @@ authors:
|
|
|
13
13
|
- Michel Martens
|
|
14
14
|
- Damian Janowski
|
|
15
15
|
- Pieter Noordhuis
|
|
16
|
-
autorequire:
|
|
17
16
|
bindir: bin
|
|
18
17
|
cert_chain: []
|
|
19
|
-
date:
|
|
18
|
+
date: 2025-07-17 00:00:00.000000000 Z
|
|
20
19
|
dependencies:
|
|
21
20
|
- !ruby/object:Gem::Dependency
|
|
22
21
|
name: redis-client
|
|
@@ -24,14 +23,14 @@ dependencies:
|
|
|
24
23
|
requirements:
|
|
25
24
|
- - ">="
|
|
26
25
|
- !ruby/object:Gem::Version
|
|
27
|
-
version: 0.
|
|
26
|
+
version: 0.22.0
|
|
28
27
|
type: :runtime
|
|
29
28
|
prerelease: false
|
|
30
29
|
version_requirements: !ruby/object:Gem::Requirement
|
|
31
30
|
requirements:
|
|
32
31
|
- - ">="
|
|
33
32
|
- !ruby/object:Gem::Version
|
|
34
|
-
version: 0.
|
|
33
|
+
version: 0.22.0
|
|
35
34
|
description: |2
|
|
36
35
|
A Ruby client that tries to match Redis' API one-to-one, while still
|
|
37
36
|
providing an idiomatic interface.
|
|
@@ -75,10 +74,9 @@ licenses:
|
|
|
75
74
|
metadata:
|
|
76
75
|
bug_tracker_uri: https://github.com/redis/redis-rb/issues
|
|
77
76
|
changelog_uri: https://github.com/redis/redis-rb/blob/master/CHANGELOG.md
|
|
78
|
-
documentation_uri: https://www.rubydoc.info/gems/redis/5.1
|
|
77
|
+
documentation_uri: https://www.rubydoc.info/gems/redis/5.4.1
|
|
79
78
|
homepage_uri: https://github.com/redis/redis-rb
|
|
80
|
-
source_code_uri: https://github.com/redis/redis-rb/tree/v5.1
|
|
81
|
-
post_install_message:
|
|
79
|
+
source_code_uri: https://github.com/redis/redis-rb/tree/v5.4.1
|
|
82
80
|
rdoc_options: []
|
|
83
81
|
require_paths:
|
|
84
82
|
- lib
|
|
@@ -86,15 +84,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
86
84
|
requirements:
|
|
87
85
|
- - ">="
|
|
88
86
|
- !ruby/object:Gem::Version
|
|
89
|
-
version: 2.
|
|
87
|
+
version: 2.6.0
|
|
90
88
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
91
89
|
requirements:
|
|
92
90
|
- - ">="
|
|
93
91
|
- !ruby/object:Gem::Version
|
|
94
92
|
version: '0'
|
|
95
93
|
requirements: []
|
|
96
|
-
rubygems_version: 3.
|
|
97
|
-
signing_key:
|
|
94
|
+
rubygems_version: 3.6.2
|
|
98
95
|
specification_version: 4
|
|
99
96
|
summary: A Ruby client library for Redis
|
|
100
97
|
test_files: []
|