redis-cluster-client 0.16.4 → 0.16.5
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/lib/redis_client/cluster/command.rb +1 -1
- data/lib/redis_client/cluster/node.rb +5 -11
- data/lib/redis_client/cluster/optimistic_locking.rb +2 -1
- data/lib/redis_client/cluster/pipeline.rb +1 -4
- data/lib/redis_client/cluster/pub_sub.rb +35 -44
- data/lib/redis_client/cluster/router.rb +12 -11
- data/lib/redis_client/cluster/transaction.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ee5d5f4c7bb89d0899ef2c3aec48503580d01a1e84a369f1e9ee0c1f60011f15
|
|
4
|
+
data.tar.gz: b17966f3f4c74ce89005b49188d769c4e8b6e399d6d65e0c4d68e14868cee9c7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 580dbda062e93296be5869169a3f8f4d389f7bc7aba34cb473cc1a1877cd8a552a29617bf6e09cc2bea8e372cbf895f28ffd086bf75ce986a2dd448bd7170dae
|
|
7
|
+
data.tar.gz: d3abefad63034a97613319637fe617b66f64b2053f67ed8c6de7d81350976645c0eec250037fd100b0a4d5e518c3674c96e07fb043c56ffd327a8e918626405d
|
|
@@ -53,15 +53,10 @@ class RedisClient
|
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
class CharArray
|
|
56
|
-
BASE = ''
|
|
57
|
-
PADDING = '0'
|
|
58
|
-
|
|
59
|
-
private_constant :BASE, :PADDING
|
|
60
|
-
|
|
61
56
|
def initialize(size, elements)
|
|
62
57
|
@elements = elements
|
|
63
|
-
@string = String.new(
|
|
64
|
-
size.times { @string <<
|
|
58
|
+
@string = String.new('', encoding: Encoding::BINARY, capacity: size)
|
|
59
|
+
size.times { @string << 0xff }
|
|
65
60
|
end
|
|
66
61
|
|
|
67
62
|
def [](index)
|
|
@@ -314,7 +309,6 @@ class RedisClient
|
|
|
314
309
|
e
|
|
315
310
|
ensure
|
|
316
311
|
client.read_timeout = regular_timeout
|
|
317
|
-
client&.close
|
|
318
312
|
end
|
|
319
313
|
end
|
|
320
314
|
|
|
@@ -378,7 +372,7 @@ class RedisClient
|
|
|
378
372
|
config_epoch: fields[6],
|
|
379
373
|
link_state: fields[7],
|
|
380
374
|
slots: slots
|
|
381
|
-
)
|
|
375
|
+
).freeze
|
|
382
376
|
end
|
|
383
377
|
end
|
|
384
378
|
|
|
@@ -398,7 +392,7 @@ class RedisClient
|
|
|
398
392
|
role: role,
|
|
399
393
|
primary_id: role == 'master' ? EMPTY_STRING : primary_id,
|
|
400
394
|
slots: role == 'master' ? slots : EMPTY_ARRAY
|
|
401
|
-
)
|
|
395
|
+
).freeze
|
|
402
396
|
end
|
|
403
397
|
end
|
|
404
398
|
end
|
|
@@ -422,7 +416,7 @@ class RedisClient
|
|
|
422
416
|
role: role == 'master' ? role : 'slave',
|
|
423
417
|
primary_id: role == 'master' ? EMPTY_STRING : primary_id,
|
|
424
418
|
slots: role == 'master' ? shard.fetch('slots').each_slice(2).to_a.freeze : EMPTY_ARRAY
|
|
425
|
-
)
|
|
419
|
+
).freeze
|
|
426
420
|
end
|
|
427
421
|
end
|
|
428
422
|
end
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'redis_client'
|
|
4
4
|
require 'redis_client/cluster/transaction'
|
|
5
|
+
require 'redis_client/cluster/error_identification'
|
|
5
6
|
|
|
6
7
|
class RedisClient
|
|
7
8
|
class Cluster
|
|
@@ -54,7 +55,7 @@ class RedisClient
|
|
|
54
55
|
rescue ::RedisClient::ConnectionError
|
|
55
56
|
# Deduct the number of retries that happened _inside_ router#handle_redirection from our remaining
|
|
56
57
|
# _external_ retries. Always deduct at least one in case handle_redirection raises without trying the block.
|
|
57
|
-
retry_count -= times_block_executed
|
|
58
|
+
retry_count -= times_block_executed > 1 ? times_block_executed : 1
|
|
58
59
|
raise if retry_count < 0
|
|
59
60
|
|
|
60
61
|
retry
|
|
@@ -23,10 +23,6 @@ class RedisClient
|
|
|
23
23
|
@outer_indices << index
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
def get_inner_index(outer_index)
|
|
27
|
-
@outer_indices&.find_index(outer_index)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
26
|
def get_callee_method(inner_index)
|
|
31
27
|
if @timeouts.is_a?(Array) && !@timeouts[inner_index].nil?
|
|
32
28
|
:blocking_call_v
|
|
@@ -66,6 +62,7 @@ class RedisClient
|
|
|
66
62
|
if result.is_a?(::RedisClient::Error)
|
|
67
63
|
result._set_command(commands[index])
|
|
68
64
|
result._set_config(config)
|
|
65
|
+
result._set_retry_attempt(@retry_attempt)
|
|
69
66
|
|
|
70
67
|
if result.is_a?(::RedisClient::CommandError) && result.message.start_with?('MOVED', 'ASK')
|
|
71
68
|
redirection_indices ||= []
|
|
@@ -61,17 +61,7 @@ class RedisClient
|
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
BUF_SIZE = Integer(ENV.fetch('REDIS_CLIENT_PUBSUB_BUF_SIZE', 1024))
|
|
64
|
-
|
|
65
|
-
RECOVERY_MAX_INTERVAL = Float(ENV.fetch('REDIS_CLIENT_PUBSUB_RECOVERY_MAX_INTERVAL_SEC', 30.0))
|
|
66
|
-
RECOVERY_MAX_ATTEMPTS = Integer(ENV.fetch('REDIS_CLIENT_PUBSUB_RECOVERY_MAX_ATTEMPTS', 10))
|
|
67
|
-
SUBSCRIBE_COMMANDS = %w[subscribe psubscribe ssubscribe].freeze
|
|
68
|
-
UNSUBSCRIBE_TO_SUBSCRIBE = {
|
|
69
|
-
'unsubscribe' => 'subscribe',
|
|
70
|
-
'punsubscribe' => 'psubscribe',
|
|
71
|
-
'sunsubscribe' => 'ssubscribe'
|
|
72
|
-
}.freeze
|
|
73
|
-
private_constant :BUF_SIZE, :RECOVERY_BASE_INTERVAL, :RECOVERY_MAX_INTERVAL, :RECOVERY_MAX_ATTEMPTS,
|
|
74
|
-
:SUBSCRIBE_COMMANDS, :UNSUBSCRIBE_TO_SUBSCRIBE
|
|
64
|
+
private_constant :BUF_SIZE
|
|
75
65
|
|
|
76
66
|
def initialize(router, command_builder)
|
|
77
67
|
@router = router
|
|
@@ -84,14 +74,14 @@ class RedisClient
|
|
|
84
74
|
def call(*args, **kwargs)
|
|
85
75
|
command = @command_builder.generate(args, kwargs)
|
|
86
76
|
_call(command)
|
|
87
|
-
|
|
77
|
+
remember_subscription(command)
|
|
88
78
|
nil
|
|
89
79
|
end
|
|
90
80
|
|
|
91
81
|
def call_v(command)
|
|
92
82
|
command = @command_builder.generate(command)
|
|
93
83
|
_call(command)
|
|
94
|
-
|
|
84
|
+
remember_subscription(command)
|
|
95
85
|
nil
|
|
96
86
|
end
|
|
97
87
|
|
|
@@ -128,35 +118,6 @@ class RedisClient
|
|
|
128
118
|
|
|
129
119
|
private
|
|
130
120
|
|
|
131
|
-
def remember(command)
|
|
132
|
-
cmd = command.first.to_s.downcase
|
|
133
|
-
if SUBSCRIBE_COMMANDS.include?(cmd)
|
|
134
|
-
@commands << command
|
|
135
|
-
elsif (subscribe_cmd = UNSUBSCRIBE_TO_SUBSCRIBE[cmd])
|
|
136
|
-
forget_subscriptions(subscribe_cmd, command[1..])
|
|
137
|
-
else
|
|
138
|
-
@commands << command
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
def forget_subscriptions(subscribe_cmd, channels)
|
|
143
|
-
if channels.nil? || channels.empty?
|
|
144
|
-
@commands.reject! { |c| c.first.to_s.casecmp(subscribe_cmd).zero? }
|
|
145
|
-
else
|
|
146
|
-
@commands.reject! { |c| prune_entry(c, subscribe_cmd, channels) }
|
|
147
|
-
end
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
def prune_entry(entry, subscribe_cmd, channels)
|
|
151
|
-
return false unless entry.first.to_s.casecmp(subscribe_cmd).zero?
|
|
152
|
-
|
|
153
|
-
remaining = entry[1..] - channels
|
|
154
|
-
return true if remaining.empty?
|
|
155
|
-
|
|
156
|
-
entry.replace([entry.first, *remaining])
|
|
157
|
-
false
|
|
158
|
-
end
|
|
159
|
-
|
|
160
121
|
def _call(command) # rubocop:disable Metrics/AbcSize
|
|
161
122
|
if command.first.casecmp('subscribe').zero?
|
|
162
123
|
call_to_single_state(command)
|
|
@@ -227,14 +188,44 @@ class RedisClient
|
|
|
227
188
|
break
|
|
228
189
|
rescue ::RedisClient::ConnectionError, ::RedisClient::Cluster::NodeMightBeDown
|
|
229
190
|
attempt += 1
|
|
230
|
-
raise if attempt >=
|
|
191
|
+
raise if attempt >= 10
|
|
231
192
|
|
|
232
193
|
sleep recovery_interval(attempt)
|
|
233
194
|
end
|
|
234
195
|
end
|
|
235
196
|
|
|
236
197
|
def recovery_interval(attempt)
|
|
237
|
-
[
|
|
198
|
+
[1.0 * (2**(attempt - 1)), 30.0].min
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def remember_subscription(command) # rubocop:disable Metrics/AbcSize
|
|
202
|
+
if command.first.casecmp('subscribe').zero?
|
|
203
|
+
@commands << command
|
|
204
|
+
elsif command.first.casecmp('psubscribe').zero?
|
|
205
|
+
@commands << command
|
|
206
|
+
elsif command.first.casecmp('ssubscribe').zero?
|
|
207
|
+
@commands << command
|
|
208
|
+
elsif command.first.casecmp('unsubscribe').zero?
|
|
209
|
+
forget_subscriptions('subscribe', command[1, command.size])
|
|
210
|
+
elsif command.first.casecmp('punsubscribe').zero?
|
|
211
|
+
forget_subscriptions('psubscribe', command[1, command.size])
|
|
212
|
+
elsif command.first.casecmp('sunsubscribe').zero?
|
|
213
|
+
forget_subscriptions('ssubscribe', command[1, command.size])
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def forget_subscriptions(subscribe_cmd, channels)
|
|
218
|
+
@commands.map! do |command|
|
|
219
|
+
next command unless command.first.casecmp(subscribe_cmd).zero?
|
|
220
|
+
next if channels.nil? || channels.empty?
|
|
221
|
+
|
|
222
|
+
remaining = command[1, command.size] - channels
|
|
223
|
+
next if remaining.empty?
|
|
224
|
+
|
|
225
|
+
[command.first, *remaining]
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
@commands.compact!
|
|
238
229
|
end
|
|
239
230
|
end
|
|
240
231
|
end
|
|
@@ -167,19 +167,20 @@ class RedisClient
|
|
|
167
167
|
raise unless ::RedisClient::Cluster::ErrorIdentification.client_owns_error?(e, node)
|
|
168
168
|
|
|
169
169
|
renew_cluster_state
|
|
170
|
-
|
|
170
|
+
raise if command.nil? || command.empty?
|
|
171
171
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
172
|
+
retry_count -= 1
|
|
173
|
+
raise if retry_count < 0
|
|
174
|
+
|
|
175
|
+
# Find the node to use for this command - if this fails for some reason, though, re-use
|
|
176
|
+
# the old node.
|
|
177
|
+
begin
|
|
178
|
+
node = find_node(find_node_key(command))
|
|
179
|
+
rescue StandardError
|
|
180
|
+
raise e
|
|
180
181
|
end
|
|
181
182
|
|
|
182
|
-
|
|
183
|
+
retry
|
|
183
184
|
end
|
|
184
185
|
|
|
185
186
|
def scan(command, seed: nil) # rubocop:disable Metrics/AbcSize
|
|
@@ -227,7 +228,7 @@ class RedisClient
|
|
|
227
228
|
def find_node_key_by_key(key, seed: nil, primary: false)
|
|
228
229
|
if key && !key.empty?
|
|
229
230
|
slot = ::RedisClient::Cluster::KeySlotConverter.convert(key)
|
|
230
|
-
node_key = primary ? @node.find_node_key_of_primary(slot) : @node.find_node_key_of_replica(slot)
|
|
231
|
+
node_key = primary ? @node.find_node_key_of_primary(slot) : @node.find_node_key_of_replica(slot, seed: seed)
|
|
231
232
|
if node_key.nil?
|
|
232
233
|
renew_cluster_state
|
|
233
234
|
raise ::RedisClient::Cluster::NodeMightBeDown.new.with_config(@config)
|
|
@@ -171,7 +171,7 @@ class RedisClient
|
|
|
171
171
|
send_transaction(node, redirect: redirect - 1)
|
|
172
172
|
elsif err.message.start_with?('ASK')
|
|
173
173
|
node = @router.assign_asking_node(err.message)
|
|
174
|
-
try_asking(node) ? send_transaction(node, redirect: redirect - 1) : err
|
|
174
|
+
try_asking(node) ? send_transaction(node, redirect: redirect - 1) : raise(err)
|
|
175
175
|
elsif err.message.start_with?('CLUSTERDOWN')
|
|
176
176
|
@router.renew_cluster_state if @watching_slot.nil?
|
|
177
177
|
raise err
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: redis-cluster-client
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.16.
|
|
4
|
+
version: 0.16.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Taishi Kasuga
|
|
@@ -74,7 +74,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
74
74
|
- !ruby/object:Gem::Version
|
|
75
75
|
version: '0'
|
|
76
76
|
requirements: []
|
|
77
|
-
rubygems_version: 4.0.
|
|
77
|
+
rubygems_version: 4.0.10
|
|
78
78
|
specification_version: 4
|
|
79
79
|
summary: Redis cluster-aware client for Ruby
|
|
80
80
|
test_files: []
|