redis 5.0.8 → 5.4.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 +4 -4
- data/CHANGELOG.md +23 -0
- data/README.md +27 -4
- data/lib/redis/client.rb +8 -8
- data/lib/redis/commands/bitmaps.rb +10 -3
- data/lib/redis/commands/hashes.rb +4 -0
- data/lib/redis/commands/keys.rb +22 -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 +22 -8
- data/lib/redis/pipeline.rb +13 -9
- data/lib/redis/version.rb +1 -1
- data/lib/redis.rb +4 -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: 485e29928983863d4725f47cf52718493c36724b1b736951603fb81648fd1ffb
|
4
|
+
data.tar.gz: 17663d08f23fe1106e89f3b06805402f5f1ff7b5bcee2e4bb9593cc3329646f7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 71bed198d46e435677b3ebf725ba65a55af5d5d7a73ff1593d2ac7044972d2898f7c5503fc69d3aa202d8a00781174e0c7348cefa06102c948b9df19cd22d81c
|
7
|
+
data.tar.gz: 607288d9a58459346db9c6e79041d35c98cc2c3268c74ffceecd395799833b9ba8e0f1c29c236d6c5afdc917bd66089721fdf5977efcab0799f46cfedb18e826
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,28 @@
|
|
1
1
|
# Unreleased
|
2
2
|
|
3
|
+
# 5.4.0
|
4
|
+
|
5
|
+
- Fix `blmpop` method to actually use `BLMPOP`, it was mistakenly issuing `LMPOP` commands.
|
6
|
+
- `xadd` now accepts a `minid:` argument.
|
7
|
+
- `zrank` and `zrevrank` now accepts `with_score:` argument.
|
8
|
+
- `Redis#call` now accept a block, allowing to use `Redis` instances where `RedisClient` is expected.
|
9
|
+
|
10
|
+
# 5.3.0
|
11
|
+
|
12
|
+
- Fix the return type of `hgetall` when used inside a `multi` transaction which is itself inside a pipeline.
|
13
|
+
|
14
|
+
# 5.2.0
|
15
|
+
|
16
|
+
- Now require Ruby 2.6 because `redis-client` does.
|
17
|
+
- Eagerly close subscribed connection when using `subscribe_with_timeout`. See #1259.
|
18
|
+
- Add `exception` flag in `pipelined` allowing failed commands to be returned in the result array when set to `false`.
|
19
|
+
|
20
|
+
# 5.1.0
|
21
|
+
|
22
|
+
- `multi` now accept a `watch` keyword argument like `redis-client`. See #1236.
|
23
|
+
- `bitcount` and `bitpos` now accept a `scale:` argument on Redis 7+. See #1242
|
24
|
+
- Added `expiretime` and `pexpiretime`. See #1248.
|
25
|
+
|
3
26
|
# 5.0.8
|
4
27
|
|
5
28
|
- Fix `Redis#without_reconnect` for sentinel clients. Fix #1212.
|
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
@@ -27,18 +27,18 @@ class Redis
|
|
27
27
|
super(protocol: 2, **kwargs, client_implementation: ::RedisClient)
|
28
28
|
end
|
29
29
|
|
30
|
-
def translate_error!(error)
|
31
|
-
redis_error = translate_error_class(error.class)
|
30
|
+
def translate_error!(error, mapping: ERROR_MAPPING)
|
31
|
+
redis_error = translate_error_class(error.class, mapping: mapping)
|
32
32
|
raise redis_error, error.message, error.backtrace
|
33
33
|
end
|
34
34
|
|
35
35
|
private
|
36
36
|
|
37
|
-
def translate_error_class(error_class)
|
38
|
-
|
37
|
+
def translate_error_class(error_class, mapping: ERROR_MAPPING)
|
38
|
+
mapping.fetch(error_class)
|
39
39
|
rescue IndexError
|
40
|
-
if (client_error = error_class.ancestors.find { |a|
|
41
|
-
|
40
|
+
if (client_error = error_class.ancestors.find { |a| mapping[a] })
|
41
|
+
mapping[error_class] = mapping[client_error]
|
42
42
|
else
|
43
43
|
raise
|
44
44
|
end
|
@@ -105,13 +105,13 @@ class Redis
|
|
105
105
|
Client.translate_error!(error)
|
106
106
|
end
|
107
107
|
|
108
|
-
def pipelined
|
108
|
+
def pipelined(exception: true)
|
109
109
|
super
|
110
110
|
rescue ::RedisClient::Error => error
|
111
111
|
Client.translate_error!(error)
|
112
112
|
end
|
113
113
|
|
114
|
-
def multi
|
114
|
+
def multi(watch: nil)
|
115
115
|
super
|
116
116
|
rescue ::RedisClient::Error => error
|
117
117
|
Client.translate_error!(error)
|
@@ -27,9 +27,13 @@ class Redis
|
|
27
27
|
# @param [String] key
|
28
28
|
# @param [Integer] start start index
|
29
29
|
# @param [Integer] stop stop index
|
30
|
+
# @param [String, Symbol] scale the scale of the offset range
|
31
|
+
# e.g. 'BYTE' - interpreted as a range of bytes, 'BIT' - interpreted as a range of bits
|
30
32
|
# @return [Integer] the number of bits set to 1
|
31
|
-
def bitcount(key, start = 0, stop = -1)
|
32
|
-
|
33
|
+
def bitcount(key, start = 0, stop = -1, scale: nil)
|
34
|
+
command = [:bitcount, key, start, stop]
|
35
|
+
command << scale if scale
|
36
|
+
send_command(command)
|
33
37
|
end
|
34
38
|
|
35
39
|
# Perform a bitwise operation between strings and store the resulting string in a key.
|
@@ -51,14 +55,17 @@ class Redis
|
|
51
55
|
# @param [Integer] bit whether to look for the first 1 or 0 bit
|
52
56
|
# @param [Integer] start start index
|
53
57
|
# @param [Integer] stop stop index
|
58
|
+
# @param [String, Symbol] scale the scale of the offset range
|
59
|
+
# e.g. 'BYTE' - interpreted as a range of bytes, 'BIT' - interpreted as a range of bits
|
54
60
|
# @return [Integer] the position of the first 1/0 bit.
|
55
61
|
# -1 if looking for 1 and it is not found or start and stop are given.
|
56
|
-
def bitpos(key, bit, start = nil, stop = nil)
|
62
|
+
def bitpos(key, bit, start = nil, stop = nil, scale: nil)
|
57
63
|
raise(ArgumentError, 'stop parameter specified without start parameter') if stop && !start
|
58
64
|
|
59
65
|
command = [:bitpos, key, bit]
|
60
66
|
command << start if start
|
61
67
|
command << stop if stop
|
68
|
+
command << scale if scale
|
62
69
|
send_command(command)
|
63
70
|
end
|
64
71
|
end
|
@@ -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
|
|
@@ -105,6 +109,14 @@ class Redis
|
|
105
109
|
send_command(args, &Boolify)
|
106
110
|
end
|
107
111
|
|
112
|
+
# Get a key's expiry time specified as number of seconds from UNIX Epoch
|
113
|
+
#
|
114
|
+
# @param [String] key
|
115
|
+
# @return [Integer] expiry time specified as number of seconds from UNIX Epoch
|
116
|
+
def expiretime(key)
|
117
|
+
send_command([:expiretime, key])
|
118
|
+
end
|
119
|
+
|
108
120
|
# Get the time to live (in seconds) for a key.
|
109
121
|
#
|
110
122
|
# @param [String] key
|
@@ -161,6 +173,14 @@ class Redis
|
|
161
173
|
send_command(args, &Boolify)
|
162
174
|
end
|
163
175
|
|
176
|
+
# Get a key's expiry time specified as number of milliseconds from UNIX Epoch
|
177
|
+
#
|
178
|
+
# @param [String] key
|
179
|
+
# @return [Integer] expiry time specified as number of milliseconds from UNIX Epoch
|
180
|
+
def pexpiretime(key)
|
181
|
+
send_command([:pexpiretime, key])
|
182
|
+
end
|
183
|
+
|
164
184
|
# Get the time to live (in milliseconds) for a key.
|
165
185
|
#
|
166
186
|
# @param [String] key
|
@@ -266,6 +286,8 @@ class Redis
|
|
266
286
|
#
|
267
287
|
# @param [String] pattern
|
268
288
|
# @return [Array<String>]
|
289
|
+
#
|
290
|
+
# See the [Redis Server KEYS documentation](https://redis.io/docs/latest/commands/keys/) for further details
|
269
291
|
def keys(pattern = "*")
|
270
292
|
send_command([:keys, pattern]) do |reply|
|
271
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
@@ -130,6 +130,11 @@ class Redis
|
|
130
130
|
node_for(key).expireat(key, unix_time, **kwargs)
|
131
131
|
end
|
132
132
|
|
133
|
+
# Get the expiration for a key as a UNIX timestamp.
|
134
|
+
def expiretime(key)
|
135
|
+
node_for(key).expiretime(key)
|
136
|
+
end
|
137
|
+
|
133
138
|
# Get the time to live (in seconds) for a key.
|
134
139
|
def ttl(key)
|
135
140
|
node_for(key).ttl(key)
|
@@ -145,6 +150,11 @@ class Redis
|
|
145
150
|
node_for(key).pexpireat(key, ms_unix_time, **kwarg)
|
146
151
|
end
|
147
152
|
|
153
|
+
# Get the expiration for a key as number of milliseconds from UNIX Epoch.
|
154
|
+
def pexpiretime(key)
|
155
|
+
node_for(key).pexpiretime(key)
|
156
|
+
end
|
157
|
+
|
148
158
|
# Get the time to live (in milliseconds) for a key.
|
149
159
|
def pttl(key)
|
150
160
|
node_for(key).pttl(key)
|
@@ -370,8 +380,8 @@ class Redis
|
|
370
380
|
end
|
371
381
|
|
372
382
|
# Count the number of set bits in a range of the string value stored at key.
|
373
|
-
def bitcount(key, start = 0, stop = -1)
|
374
|
-
node_for(key).bitcount(key, start, stop)
|
383
|
+
def bitcount(key, start = 0, stop = -1, scale: nil)
|
384
|
+
node_for(key).bitcount(key, start, stop, scale: scale)
|
375
385
|
end
|
376
386
|
|
377
387
|
# Perform a bitwise operation between strings and store the resulting string in a key.
|
@@ -383,8 +393,8 @@ class Redis
|
|
383
393
|
end
|
384
394
|
|
385
395
|
# Return the position of the first bit set to 1 or 0 in a string.
|
386
|
-
def bitpos(key, bit, start = nil, stop = nil)
|
387
|
-
node_for(key).bitpos(key, bit, start, stop)
|
396
|
+
def bitpos(key, bit, start = nil, stop = nil, scale: nil)
|
397
|
+
node_for(key).bitpos(key, bit, start, stop, scale: scale)
|
388
398
|
end
|
389
399
|
|
390
400
|
# Set the string value of a key and return its old value.
|
@@ -742,14 +752,14 @@ class Redis
|
|
742
752
|
end
|
743
753
|
|
744
754
|
# Determine the index of a member in a sorted set.
|
745
|
-
def zrank(key, member)
|
746
|
-
node_for(key).zrank(key, member)
|
755
|
+
def zrank(key, member, **options)
|
756
|
+
node_for(key).zrank(key, member, **options)
|
747
757
|
end
|
748
758
|
|
749
759
|
# Determine the index of a member in a sorted set, with scores ordered from
|
750
760
|
# high to low.
|
751
|
-
def zrevrank(key, member)
|
752
|
-
node_for(key).zrevrank(key, member)
|
761
|
+
def zrevrank(key, member, **options)
|
762
|
+
node_for(key).zrevrank(key, member, **options)
|
753
763
|
end
|
754
764
|
|
755
765
|
# Remove all members in a sorted set within the given indexes.
|
@@ -938,12 +948,16 @@ class Redis
|
|
938
948
|
end
|
939
949
|
|
940
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
|
941
953
|
def psubscribe(*channels, &block)
|
942
954
|
raise NotImplementedError
|
943
955
|
end
|
944
956
|
|
945
957
|
# Stop listening for messages posted to channels matching the given
|
946
958
|
# patterns.
|
959
|
+
# See the [Redis Server PUNSUBSCRIBE documentation](https://redis.io/docs/latest/commands/punsubscribe/)
|
960
|
+
# for further details
|
947
961
|
def punsubscribe(*channels)
|
948
962
|
raise NotImplementedError
|
949
963
|
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
@@ -99,10 +99,10 @@ class Redis
|
|
99
99
|
@client
|
100
100
|
end
|
101
101
|
|
102
|
-
def pipelined
|
102
|
+
def pipelined(exception: true)
|
103
103
|
synchronize do |client|
|
104
|
-
client.pipelined do |raw_pipeline|
|
105
|
-
yield PipelinedConnection.new(raw_pipeline)
|
104
|
+
client.pipelined(exception: exception) do |raw_pipeline|
|
105
|
+
yield PipelinedConnection.new(raw_pipeline, exception: exception)
|
106
106
|
end
|
107
107
|
end
|
108
108
|
end
|
@@ -175,6 +175,7 @@ class Redis
|
|
175
175
|
@subscription_client.send(method, *channels, &block)
|
176
176
|
end
|
177
177
|
ensure
|
178
|
+
@subscription_client&.close
|
178
179
|
@subscription_client = nil
|
179
180
|
end
|
180
181
|
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.0
|
4
|
+
version: 5.4.0
|
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-02-20 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.0
|
77
|
+
documentation_uri: https://www.rubydoc.info/gems/redis/5.4.0
|
79
78
|
homepage_uri: https://github.com/redis/redis-rb
|
80
|
-
source_code_uri: https://github.com/redis/redis-rb/tree/v5.0
|
81
|
-
post_install_message:
|
79
|
+
source_code_uri: https://github.com/redis/redis-rb/tree/v5.4.0
|
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: []
|