Skip to content

Commit 90f178b

Browse files
authored
perf: lessen wasting memory allocation for Pub/Sub (#234)
1 parent 1285c1f commit 90f178b

File tree

2 files changed

+22
-12
lines changed

2 files changed

+22
-12
lines changed

lib/redis_client/cluster/pub_sub.rb

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ def subscribe(client, timeout)
4343
def initialize(router, command_builder)
4444
@router = router
4545
@command_builder = command_builder
46-
@states = {}
46+
@state_list = []
47+
@state_dict = {}
4748
end
4849

4950
def call(*args, **kwargs)
@@ -55,21 +56,21 @@ def call_v(command)
5556
end
5657

5758
def close
58-
@states.each_value(&:close)
59-
@states.clear
59+
@state_list.each(&:close)
60+
@state_list.clear
61+
@state_dict.clear
6062
end
6163

6264
def next_event(timeout = nil)
63-
return if @states.empty?
65+
return if @state_list.empty?
6466

6567
max_duration = calc_max_duration(timeout)
6668
starting = obtain_current_time
67-
clients = @states.values
6869
loop do
6970
break if max_duration > 0 && obtain_current_time - starting > max_duration
7071

71-
clients.shuffle!
72-
clients.each do |pubsub|
72+
@state_list.shuffle!
73+
@state_list.each do |pubsub|
7374
message = pubsub.take_message(timeout)
7475
return message if message
7576
end
@@ -80,26 +81,26 @@ def next_event(timeout = nil)
8081

8182
def _call(command)
8283
node_key = @router.find_node_key(command)
83-
add_state(node_key)
8484
try_call(node_key, command)
8585
end
8686

8787
def try_call(node_key, command, retry_count: 1)
88-
@states[node_key].call(command)
88+
add_state(node_key).call(command)
8989
rescue ::RedisClient::CommandError => e
9090
raise if !e.message.start_with?('MOVED') || retry_count <= 0
9191

9292
# for sharded pub/sub
9393
node_key = e.message.split[2]
94-
add_state(node_key)
9594
retry_count -= 1
9695
retry
9796
end
9897

9998
def add_state(node_key)
100-
return @states[node_key] if @states.key?(node_key)
99+
return @state_dict[node_key] if @state_dict.key?(node_key)
101100

102-
@states[node_key] = State.new(@router.find_node(node_key).pubsub)
101+
state = State.new(@router.find_node(node_key).pubsub)
102+
@state_list << state
103+
@state_dict[node_key] = state
103104
end
104105

105106
def obtain_current_time

test/redis_client/test_cluster.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,15 @@ def test_pubsub_without_subscription
187187
pubsub.close
188188
end
189189

190+
def test_pubsub_with_wrong_command
191+
pubsub = @client.pubsub
192+
assert_nil(pubsub.call('SUBWAY'))
193+
assert_nil(pubsub.call_v(%w[SUBSCRIBE]))
194+
assert_instance_of(::RedisClient::CommandError, pubsub.next_event, 'unknown command')
195+
assert_instance_of(::RedisClient::CommandError, pubsub.next_event, 'wrong number of arguments')
196+
pubsub.close
197+
end
198+
190199
def test_global_pubsub
191200
sub = Fiber.new do |pubsub|
192201
channel = 'my-global-channel'

0 commit comments

Comments
 (0)