redis 4.4.0 → 4.6.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 +72 -0
- data/README.md +10 -10
- data/lib/redis/client.rb +26 -11
- data/lib/redis/cluster/command.rb +4 -6
- data/lib/redis/cluster/command_loader.rb +6 -7
- data/lib/redis/cluster/node.rb +12 -0
- data/lib/redis/cluster.rb +24 -0
- data/lib/redis/commands/bitmaps.rb +63 -0
- data/lib/redis/commands/cluster.rb +45 -0
- data/lib/redis/commands/connection.rb +58 -0
- data/lib/redis/commands/geo.rb +84 -0
- data/lib/redis/commands/hashes.rb +251 -0
- data/lib/redis/commands/hyper_log_log.rb +37 -0
- data/lib/redis/commands/keys.rb +411 -0
- data/lib/redis/commands/lists.rb +289 -0
- data/lib/redis/commands/pubsub.rb +72 -0
- data/lib/redis/commands/scripting.rb +114 -0
- data/lib/redis/commands/server.rb +188 -0
- data/lib/redis/commands/sets.rb +207 -0
- data/lib/redis/commands/sorted_sets.rb +804 -0
- data/lib/redis/commands/streams.rb +382 -0
- data/lib/redis/commands/strings.rb +313 -0
- data/lib/redis/commands/transactions.rb +92 -0
- data/lib/redis/commands.rb +242 -0
- data/lib/redis/connection/command_helper.rb +2 -0
- data/lib/redis/connection/hiredis.rb +3 -2
- data/lib/redis/connection/ruby.rb +13 -9
- data/lib/redis/connection/synchrony.rb +10 -8
- data/lib/redis/connection.rb +1 -1
- data/lib/redis/distributed.rb +86 -9
- data/lib/redis/pipeline.rb +95 -2
- data/lib/redis/version.rb +1 -1
- data/lib/redis.rb +133 -3484
- metadata +22 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e99f4e628112a227719d2000dc5b081893273cfbd51ae25bf00a8f6b6594061
|
4
|
+
data.tar.gz: 42a8e0cf75aebbc14cdf680b4bc1f7bbdec9e20b53f150c6443c01126960a959
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8bc57fe306c601f27d32df4940d5632e9e7d75529f6ac5d42732b21fe04452a4a1ab89567492c6fb7249ef4d69ebb2c0b7c985e18b0ef4f9ee6fb816c31bcbda
|
7
|
+
data.tar.gz: 42b2f8c584d6f96d0fc783d0b36af0fd9415d1dbd43ad8fe7a980688e52fbdb51645a07960d9cb3faacf6696c460cf38a013e290d0b58d4bbbb07626f18f15c7
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,77 @@
|
|
1
1
|
# Unreleased
|
2
2
|
|
3
|
+
# 4.6.0
|
4
|
+
|
5
|
+
* Deprecate `Redis.current`.
|
6
|
+
* Deprecate calling commands on `Redis` inside `Redis#pipelined`. See #1059.
|
7
|
+
```ruby
|
8
|
+
redis.pipelined do
|
9
|
+
redis.get("key")
|
10
|
+
end
|
11
|
+
```
|
12
|
+
|
13
|
+
should be replaced by:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
redis.pipelined do |pipeline|
|
17
|
+
pipeline.get("key")
|
18
|
+
end
|
19
|
+
```
|
20
|
+
* Deprecate calling commands on `Redis` inside `Redis#multi`. See #1059.
|
21
|
+
```ruby
|
22
|
+
redis.multi do
|
23
|
+
redis.get("key")
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
should be replaced by:
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
redis.multi do |transaction|
|
31
|
+
transaction.get("key")
|
32
|
+
end
|
33
|
+
```
|
34
|
+
* Deprecate `Redis#queue` and `Redis#commit`. See #1059.
|
35
|
+
|
36
|
+
* Fix `zpopmax` and `zpopmin` when called inside a pipeline. See #1055.
|
37
|
+
* `Redis#synchronize` is now private like it should always have been.
|
38
|
+
|
39
|
+
* Add `Redis.silence_deprecations=` to turn off deprecation warnings.
|
40
|
+
If you don't wish to see warnings yet, you can set `Redis.silence_deprecations = false`.
|
41
|
+
It is however heavily recommended to fix them instead when possible.
|
42
|
+
* Add `Redis.raise_deprecations=` to turn deprecation warnings into errors.
|
43
|
+
This makes it easier to identitify the source of deprecated APIs usage.
|
44
|
+
It is recommended to set `Redis.raise_deprecations = true` in development and test environments.
|
45
|
+
* Add new options to ZRANGE. See #1053.
|
46
|
+
* Add ZRANGESTORE command. See #1053.
|
47
|
+
* Add SCAN support for `Redis::Cluster`. See #1049.
|
48
|
+
* Add COPY command. See #1053. See #1048.
|
49
|
+
* Add ZDIFFSTORE command. See #1046.
|
50
|
+
* Add ZDIFF command. See #1044.
|
51
|
+
* Add ZUNION command. See #1042.
|
52
|
+
* Add HRANDFIELD command. See #1040.
|
53
|
+
|
54
|
+
# 4.5.1
|
55
|
+
|
56
|
+
* Restore the accidential auth behavior of redis-rb 4.3.0 with a warning. If provided with the `default` user's password, but a wrong username,
|
57
|
+
redis-rb will first try to connect as the provided user, but then will fallback to connect as the `default` user with the provided password.
|
58
|
+
This behavior is deprecated and will be removed in Redis 4.6.0. Fix #1038.
|
59
|
+
|
60
|
+
# 4.5.0
|
61
|
+
|
62
|
+
* Handle parts of the command using incompatible encodings. See #1037.
|
63
|
+
* Add GET option to SET command. See #1036.
|
64
|
+
* Add ZRANDMEMBER command. See #1035.
|
65
|
+
* Add LMOVE/BLMOVE commands. See #1034.
|
66
|
+
* Add ZMSCORE command. See #1032.
|
67
|
+
* Add LT/GT options to ZADD. See #1033.
|
68
|
+
* Add SMISMEMBER command. See #1031.
|
69
|
+
* Add EXAT/PXAT options to SET. See #1028.
|
70
|
+
* Add GETDEL/GETEX commands. See #1024.
|
71
|
+
* `Redis#exists` now returns an Integer by default, as warned since 4.2.0. The old behavior can be restored with `Redis.exists_returns_integer = false`.
|
72
|
+
* Fix Redis < 6 detection during connect. See #1025.
|
73
|
+
* Fix fetching command details in Redis cluster when the first node is unhealthy. See #1026.
|
74
|
+
|
3
75
|
# 4.4.0
|
4
76
|
|
5
77
|
* Redis cluster: fix cross-slot validation in pipelines. Fix ##1019.
|
data/README.md
CHANGED
@@ -184,9 +184,9 @@ commands to Redis and gathers their replies. These replies are returned
|
|
184
184
|
by the `#pipelined` method.
|
185
185
|
|
186
186
|
```ruby
|
187
|
-
redis.pipelined do
|
188
|
-
|
189
|
-
|
187
|
+
redis.pipelined do |pipeline|
|
188
|
+
pipeline.set "foo", "bar"
|
189
|
+
pipeline.incr "baz"
|
190
190
|
end
|
191
191
|
# => ["OK", 1]
|
192
192
|
```
|
@@ -200,9 +200,9 @@ the regular pipeline, the replies to the commands are returned by the
|
|
200
200
|
`#multi` method.
|
201
201
|
|
202
202
|
```ruby
|
203
|
-
redis.multi do
|
204
|
-
|
205
|
-
|
203
|
+
redis.multi do |transaction|
|
204
|
+
transaction.set "foo", "bar"
|
205
|
+
transaction.incr "baz"
|
206
206
|
end
|
207
207
|
# => ["OK", 1]
|
208
208
|
```
|
@@ -210,15 +210,15 @@ end
|
|
210
210
|
### Futures
|
211
211
|
|
212
212
|
Replies to commands in a pipeline can be accessed via the *futures* they
|
213
|
-
emit (since redis-rb 3.0). All calls
|
213
|
+
emit (since redis-rb 3.0). All calls on the pipeline object return a
|
214
214
|
`Future` object, which responds to the `#value` method. When the
|
215
215
|
pipeline has successfully executed, all futures are assigned their
|
216
216
|
respective replies and can be used.
|
217
217
|
|
218
218
|
```ruby
|
219
|
-
redis.pipelined do
|
220
|
-
@set =
|
221
|
-
@incr =
|
219
|
+
redis.pipelined do |pipeline|
|
220
|
+
@set = pipeline.set "foo", "bar"
|
221
|
+
@incr = pipeline.incr "baz"
|
222
222
|
end
|
223
223
|
|
224
224
|
@set.value
|
data/lib/redis/client.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "errors"
|
4
3
|
require "socket"
|
5
4
|
require "cgi"
|
5
|
+
require "redis/errors"
|
6
6
|
|
7
7
|
class Redis
|
8
8
|
class Client
|
@@ -32,7 +32,7 @@ class Redis
|
|
32
32
|
role: nil
|
33
33
|
}.freeze
|
34
34
|
|
35
|
-
attr_reader :options
|
35
|
+
attr_reader :options, :connection, :command_map
|
36
36
|
|
37
37
|
def scheme
|
38
38
|
@options[:scheme]
|
@@ -87,8 +87,6 @@ class Redis
|
|
87
87
|
end
|
88
88
|
|
89
89
|
attr_accessor :logger
|
90
|
-
attr_reader :connection
|
91
|
-
attr_reader :command_map
|
92
90
|
|
93
91
|
def initialize(options = {})
|
94
92
|
@options = _parse_options(options)
|
@@ -119,8 +117,23 @@ class Redis
|
|
119
117
|
if username
|
120
118
|
begin
|
121
119
|
call [:auth, username, password]
|
122
|
-
rescue CommandError # Likely on Redis < 6
|
123
|
-
|
120
|
+
rescue CommandError => err # Likely on Redis < 6
|
121
|
+
case err.message
|
122
|
+
when /ERR wrong number of arguments for 'auth' command/
|
123
|
+
call [:auth, password]
|
124
|
+
when /WRONGPASS invalid username-password pair/
|
125
|
+
begin
|
126
|
+
call [:auth, password]
|
127
|
+
rescue CommandError
|
128
|
+
raise err
|
129
|
+
end
|
130
|
+
::Redis.deprecate!(
|
131
|
+
"[redis-rb] The Redis connection was configured with username #{username.inspect}, but" \
|
132
|
+
" the provided password was for the default user. This will start failing in redis-rb 5.0.0."
|
133
|
+
)
|
134
|
+
else
|
135
|
+
raise
|
136
|
+
end
|
124
137
|
end
|
125
138
|
else
|
126
139
|
call [:auth, password]
|
@@ -238,7 +251,8 @@ class Redis
|
|
238
251
|
result
|
239
252
|
end
|
240
253
|
|
241
|
-
def call_with_timeout(command,
|
254
|
+
def call_with_timeout(command, extra_timeout, &blk)
|
255
|
+
timeout = extra_timeout == 0 ? 0 : self.timeout + extra_timeout
|
242
256
|
with_socket_timeout(timeout) do
|
243
257
|
call(command, &blk)
|
244
258
|
end
|
@@ -428,7 +442,7 @@ class Redis
|
|
428
442
|
defaults = DEFAULTS.dup
|
429
443
|
options = options.dup
|
430
444
|
|
431
|
-
defaults.
|
445
|
+
defaults.each_key do |key|
|
432
446
|
# Fill in defaults if needed
|
433
447
|
defaults[key] = defaults[key].call if defaults[key].respond_to?(:call)
|
434
448
|
|
@@ -445,9 +459,10 @@ class Redis
|
|
445
459
|
|
446
460
|
uri = URI(url)
|
447
461
|
|
448
|
-
|
462
|
+
case uri.scheme
|
463
|
+
when "unix"
|
449
464
|
defaults[:path] = uri.path
|
450
|
-
|
465
|
+
when "redis", "rediss"
|
451
466
|
defaults[:scheme] = uri.scheme
|
452
467
|
defaults[:host] = uri.host if uri.host
|
453
468
|
defaults[:port] = uri.port if uri.port
|
@@ -463,7 +478,7 @@ class Redis
|
|
463
478
|
end
|
464
479
|
|
465
480
|
# Use default when option is not specified or nil
|
466
|
-
defaults.
|
481
|
+
defaults.each_key do |key|
|
467
482
|
options[key] = defaults[key] if options[key].nil?
|
468
483
|
end
|
469
484
|
|
@@ -31,13 +31,13 @@ class Redis
|
|
31
31
|
private
|
32
32
|
|
33
33
|
def pick_details(details)
|
34
|
-
details.
|
35
|
-
|
34
|
+
details.transform_values do |detail|
|
35
|
+
{
|
36
36
|
first_key_position: detail[:first],
|
37
37
|
write: detail[:flags].include?('write'),
|
38
38
|
readonly: detail[:flags].include?('readonly')
|
39
|
-
}
|
40
|
-
end
|
39
|
+
}
|
40
|
+
end
|
41
41
|
end
|
42
42
|
|
43
43
|
def dig_details(command, key)
|
@@ -53,8 +53,6 @@ class Redis
|
|
53
53
|
when 'object' then 2
|
54
54
|
when 'memory'
|
55
55
|
command[1].to_s.casecmp('usage').zero? ? 2 : 0
|
56
|
-
when 'scan', 'sscan', 'hscan', 'zscan'
|
57
|
-
determine_optional_key_position(command, 'match')
|
58
56
|
when 'xread', 'xreadgroup'
|
59
57
|
determine_optional_key_position(command, 'streams')
|
60
58
|
else
|
@@ -10,22 +10,21 @@ class Redis
|
|
10
10
|
module_function
|
11
11
|
|
12
12
|
def load(nodes)
|
13
|
-
details = {}
|
14
|
-
|
15
13
|
nodes.each do |node|
|
16
|
-
|
17
|
-
|
14
|
+
begin
|
15
|
+
return fetch_command_details(node)
|
16
|
+
rescue CannotConnectError, ConnectionError, CommandError
|
17
|
+
next # can retry on another node
|
18
|
+
end
|
18
19
|
end
|
19
20
|
|
20
|
-
|
21
|
+
raise CannotConnectError, 'Redis client could not connect to any cluster nodes'
|
21
22
|
end
|
22
23
|
|
23
24
|
def fetch_command_details(node)
|
24
25
|
node.call(%i[command]).map do |reply|
|
25
26
|
[reply[0], { arity: reply[1], flags: reply[2], first: reply[3], last: reply[4], step: reply[5] }]
|
26
27
|
end.to_h
|
27
|
-
rescue CannotConnectError, ConnectionError, CommandError
|
28
|
-
{} # can retry on another node
|
29
28
|
end
|
30
29
|
|
31
30
|
private_class_method :fetch_command_details
|
data/lib/redis/cluster/node.rb
CHANGED
@@ -58,6 +58,18 @@ class Redis
|
|
58
58
|
try_map { |_, client| client.process(commands, &block) }.values
|
59
59
|
end
|
60
60
|
|
61
|
+
def scale_reading_clients
|
62
|
+
reading_clients = []
|
63
|
+
|
64
|
+
@clients.each do |node_key, client|
|
65
|
+
next unless replica_disabled? ? master?(node_key) : slave?(node_key)
|
66
|
+
|
67
|
+
reading_clients << client
|
68
|
+
end
|
69
|
+
|
70
|
+
reading_clients
|
71
|
+
end
|
72
|
+
|
61
73
|
private
|
62
74
|
|
63
75
|
def replica_disabled?
|
data/lib/redis/cluster.rb
CHANGED
@@ -137,6 +137,7 @@ class Redis
|
|
137
137
|
when 'wait' then @node.call_master(command, &block).reduce(:+)
|
138
138
|
when 'keys' then @node.call_slave(command, &block).flatten.sort
|
139
139
|
when 'dbsize' then @node.call_slave(command, &block).reduce(:+)
|
140
|
+
when 'scan' then _scan(command, &block)
|
140
141
|
when 'lastsave' then @node.call_all(command, &block).sort
|
141
142
|
when 'role' then @node.call_all(command, &block)
|
142
143
|
when 'config' then send_config_command(command, &block)
|
@@ -238,6 +239,29 @@ class Redis
|
|
238
239
|
raise
|
239
240
|
end
|
240
241
|
|
242
|
+
def _scan(command, &block)
|
243
|
+
input_cursor = Integer(command[1])
|
244
|
+
|
245
|
+
client_index = input_cursor % 256
|
246
|
+
raw_cursor = input_cursor >> 8
|
247
|
+
|
248
|
+
clients = @node.scale_reading_clients
|
249
|
+
|
250
|
+
client = clients[client_index]
|
251
|
+
return ['0', []] unless client
|
252
|
+
|
253
|
+
command[1] = raw_cursor.to_s
|
254
|
+
|
255
|
+
result_cursor, result_keys = client.call(command, &block)
|
256
|
+
result_cursor = Integer(result_cursor)
|
257
|
+
|
258
|
+
if result_cursor == 0
|
259
|
+
client_index += 1
|
260
|
+
end
|
261
|
+
|
262
|
+
[((result_cursor << 8) + client_index).to_s, result_keys]
|
263
|
+
end
|
264
|
+
|
241
265
|
def assign_redirection_node(err_msg)
|
242
266
|
_, slot, node_key = err_msg.split(' ')
|
243
267
|
slot = slot.to_i
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Redis
|
4
|
+
module Commands
|
5
|
+
module Bitmaps
|
6
|
+
# Sets or clears the bit at offset in the string value stored at key.
|
7
|
+
#
|
8
|
+
# @param [String] key
|
9
|
+
# @param [Integer] offset bit offset
|
10
|
+
# @param [Integer] value bit value `0` or `1`
|
11
|
+
# @return [Integer] the original bit value stored at `offset`
|
12
|
+
def setbit(key, offset, value)
|
13
|
+
send_command([:setbit, key, offset, value])
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns the bit value at offset in the string value stored at key.
|
17
|
+
#
|
18
|
+
# @param [String] key
|
19
|
+
# @param [Integer] offset bit offset
|
20
|
+
# @return [Integer] `0` or `1`
|
21
|
+
def getbit(key, offset)
|
22
|
+
send_command([:getbit, key, offset])
|
23
|
+
end
|
24
|
+
|
25
|
+
# Count the number of set bits in a range of the string value stored at key.
|
26
|
+
#
|
27
|
+
# @param [String] key
|
28
|
+
# @param [Integer] start start index
|
29
|
+
# @param [Integer] stop stop index
|
30
|
+
# @return [Integer] the number of bits set to 1
|
31
|
+
def bitcount(key, start = 0, stop = -1)
|
32
|
+
send_command([:bitcount, key, start, stop])
|
33
|
+
end
|
34
|
+
|
35
|
+
# Perform a bitwise operation between strings and store the resulting string in a key.
|
36
|
+
#
|
37
|
+
# @param [String] operation e.g. `and`, `or`, `xor`, `not`
|
38
|
+
# @param [String] destkey destination key
|
39
|
+
# @param [String, Array<String>] keys one or more source keys to perform `operation`
|
40
|
+
# @return [Integer] the length of the string stored in `destkey`
|
41
|
+
def bitop(operation, destkey, *keys)
|
42
|
+
send_command([:bitop, operation, destkey, *keys])
|
43
|
+
end
|
44
|
+
|
45
|
+
# Return the position of the first bit set to 1 or 0 in a string.
|
46
|
+
#
|
47
|
+
# @param [String] key
|
48
|
+
# @param [Integer] bit whether to look for the first 1 or 0 bit
|
49
|
+
# @param [Integer] start start index
|
50
|
+
# @param [Integer] stop stop index
|
51
|
+
# @return [Integer] the position of the first 1/0 bit.
|
52
|
+
# -1 if looking for 1 and it is not found or start and stop are given.
|
53
|
+
def bitpos(key, bit, start = nil, stop = nil)
|
54
|
+
raise(ArgumentError, 'stop parameter specified without start parameter') if stop && !start
|
55
|
+
|
56
|
+
command = [:bitpos, key, bit]
|
57
|
+
command << start if start
|
58
|
+
command << stop if stop
|
59
|
+
send_command(command)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Redis
|
4
|
+
module Commands
|
5
|
+
module Cluster
|
6
|
+
# Sends `CLUSTER *` command to random node and returns its reply.
|
7
|
+
#
|
8
|
+
# @see https://redis.io/commands#cluster Reference of cluster command
|
9
|
+
#
|
10
|
+
# @param subcommand [String, Symbol] the subcommand of cluster command
|
11
|
+
# e.g. `:slots`, `:nodes`, `:slaves`, `:info`
|
12
|
+
#
|
13
|
+
# @return [Object] depends on the subcommand
|
14
|
+
def cluster(subcommand, *args)
|
15
|
+
subcommand = subcommand.to_s.downcase
|
16
|
+
block = case subcommand
|
17
|
+
when 'slots'
|
18
|
+
HashifyClusterSlots
|
19
|
+
when 'nodes'
|
20
|
+
HashifyClusterNodes
|
21
|
+
when 'slaves'
|
22
|
+
HashifyClusterSlaves
|
23
|
+
when 'info'
|
24
|
+
HashifyInfo
|
25
|
+
else
|
26
|
+
Noop
|
27
|
+
end
|
28
|
+
|
29
|
+
# @see https://github.com/antirez/redis/blob/unstable/src/redis-trib.rb#L127 raw reply expected
|
30
|
+
block = Noop unless @cluster_mode
|
31
|
+
|
32
|
+
send_command([:cluster, subcommand] + args, &block)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Sends `ASKING` command to random node and returns its reply.
|
36
|
+
#
|
37
|
+
# @see https://redis.io/topics/cluster-spec#ask-redirection ASK redirection
|
38
|
+
#
|
39
|
+
# @return [String] `'OK'`
|
40
|
+
def asking
|
41
|
+
send_command(%i[asking])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Redis
|
4
|
+
module Commands
|
5
|
+
module Connection
|
6
|
+
# Authenticate to the server.
|
7
|
+
#
|
8
|
+
# @param [Array<String>] args includes both username and password
|
9
|
+
# or only password
|
10
|
+
# @return [String] `OK`
|
11
|
+
# @see https://redis.io/commands/auth AUTH command
|
12
|
+
def auth(*args)
|
13
|
+
send_command([:auth, *args])
|
14
|
+
end
|
15
|
+
|
16
|
+
# Ping the server.
|
17
|
+
#
|
18
|
+
# @param [optional, String] message
|
19
|
+
# @return [String] `PONG`
|
20
|
+
def ping(message = nil)
|
21
|
+
send_command([:ping, message].compact)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Echo the given string.
|
25
|
+
#
|
26
|
+
# @param [String] value
|
27
|
+
# @return [String]
|
28
|
+
def echo(value)
|
29
|
+
send_command([:echo, value])
|
30
|
+
end
|
31
|
+
|
32
|
+
# Change the selected database for the current connection.
|
33
|
+
#
|
34
|
+
# @param [Integer] db zero-based index of the DB to use (0 to 15)
|
35
|
+
# @return [String] `OK`
|
36
|
+
def select(db)
|
37
|
+
synchronize do |client|
|
38
|
+
client.db = db
|
39
|
+
client.call([:select, db])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Close the connection.
|
44
|
+
#
|
45
|
+
# @return [String] `OK`
|
46
|
+
def quit
|
47
|
+
synchronize do |client|
|
48
|
+
begin
|
49
|
+
client.call([:quit])
|
50
|
+
rescue ConnectionError
|
51
|
+
ensure
|
52
|
+
client.disconnect
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Redis
|
4
|
+
module Commands
|
5
|
+
module Geo
|
6
|
+
# Adds the specified geospatial items (latitude, longitude, name) to the specified key
|
7
|
+
#
|
8
|
+
# @param [String] key
|
9
|
+
# @param [Array] member arguemnts for member or members: longitude, latitude, name
|
10
|
+
# @return [Integer] number of elements added to the sorted set
|
11
|
+
def geoadd(key, *member)
|
12
|
+
send_command([:geoadd, key, *member])
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns geohash string representing position for specified members of the specified key.
|
16
|
+
#
|
17
|
+
# @param [String] key
|
18
|
+
# @param [String, Array<String>] member one member or array of members
|
19
|
+
# @return [Array<String, nil>] returns array containg geohash string if member is present, nil otherwise
|
20
|
+
def geohash(key, member)
|
21
|
+
send_command([:geohash, key, member])
|
22
|
+
end
|
23
|
+
|
24
|
+
# Query a sorted set representing a geospatial index to fetch members matching a
|
25
|
+
# given maximum distance from a point
|
26
|
+
#
|
27
|
+
# @param [Array] args key, longitude, latitude, radius, unit(m|km|ft|mi)
|
28
|
+
# @param ['asc', 'desc'] sort sort returned items from the nearest to the farthest
|
29
|
+
# or the farthest to the nearest relative to the center
|
30
|
+
# @param [Integer] count limit the results to the first N matching items
|
31
|
+
# @param ['WITHDIST', 'WITHCOORD', 'WITHHASH'] options to return additional information
|
32
|
+
# @return [Array<String>] may be changed with `options`
|
33
|
+
def georadius(*args, **geoptions)
|
34
|
+
geoarguments = _geoarguments(*args, **geoptions)
|
35
|
+
|
36
|
+
send_command([:georadius, *geoarguments])
|
37
|
+
end
|
38
|
+
|
39
|
+
# Query a sorted set representing a geospatial index to fetch members matching a
|
40
|
+
# given maximum distance from an already existing member
|
41
|
+
#
|
42
|
+
# @param [Array] args key, member, radius, unit(m|km|ft|mi)
|
43
|
+
# @param ['asc', 'desc'] sort sort returned items from the nearest to the farthest or the farthest
|
44
|
+
# to the nearest relative to the center
|
45
|
+
# @param [Integer] count limit the results to the first N matching items
|
46
|
+
# @param ['WITHDIST', 'WITHCOORD', 'WITHHASH'] options to return additional information
|
47
|
+
# @return [Array<String>] may be changed with `options`
|
48
|
+
def georadiusbymember(*args, **geoptions)
|
49
|
+
geoarguments = _geoarguments(*args, **geoptions)
|
50
|
+
|
51
|
+
send_command([:georadiusbymember, *geoarguments])
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns longitude and latitude of members of a geospatial index
|
55
|
+
#
|
56
|
+
# @param [String] key
|
57
|
+
# @param [String, Array<String>] member one member or array of members
|
58
|
+
# @return [Array<Array<String>, nil>] returns array of elements, where each
|
59
|
+
# element is either array of longitude and latitude or nil
|
60
|
+
def geopos(key, member)
|
61
|
+
send_command([:geopos, key, member])
|
62
|
+
end
|
63
|
+
|
64
|
+
# Returns the distance between two members of a geospatial index
|
65
|
+
#
|
66
|
+
# @param [String ]key
|
67
|
+
# @param [Array<String>] members
|
68
|
+
# @param ['m', 'km', 'mi', 'ft'] unit
|
69
|
+
# @return [String, nil] returns distance in spefied unit if both members present, nil otherwise.
|
70
|
+
def geodist(key, member1, member2, unit = 'm')
|
71
|
+
send_command([:geodist, key, member1, member2, unit])
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def _geoarguments(*args, options: nil, sort: nil, count: nil)
|
77
|
+
args.push sort if sort
|
78
|
+
args.push 'count', count if count
|
79
|
+
args.push options if options
|
80
|
+
args
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|