Skip to content

Commit fceec41

Browse files
authored
fix: a bug to parse reply of cluster nodes command (#69)
1 parent 37fa91f commit fceec41

File tree

11 files changed

+340
-71
lines changed

11 files changed

+340
-71
lines changed

.github/workflows/test.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,34 @@ jobs:
158158
run: bundle exec rake test_cluster_broken
159159
- name: Stop containers
160160
run: docker compose -f $DOCKER_COMPOSE_FILE down
161+
cluster-scale:
162+
name: Cluster Scale
163+
timeout-minutes: 15
164+
strategy:
165+
fail-fast: false
166+
matrix:
167+
redis: ['7.0.1', '6.2.7']
168+
runs-on: ubuntu-latest
169+
env:
170+
REDIS_VERSION: ${{ matrix.redis }}
171+
DOCKER_COMPOSE_FILE: 'docker-compose.scale.yaml'
172+
steps:
173+
- name: Check out code
174+
uses: actions/checkout@v3
175+
- name: Set up Ruby
176+
uses: ruby/setup-ruby@v1
177+
with:
178+
ruby-version: '3.1'
179+
bundler-cache: true
180+
- name: Pull Docker images
181+
run: docker pull redis:$REDIS_VERSION
182+
- name: Run containers
183+
run: docker compose -f $DOCKER_COMPOSE_FILE up -d
184+
- name: Wait for Redis cluster to be ready
185+
run: bundle exec rake wait
186+
- name: Print containers
187+
run: docker compose -f $DOCKER_COMPOSE_FILE ps
188+
- name: Run minitest
189+
run: bundle exec rake test_cluster_scale
190+
- name: Stop containers
191+
run: docker compose -f $DOCKER_COMPOSE_FILE down

Rakefile

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,28 @@
22

33
require 'rake/testtask'
44

5+
FREAKY_TEST_TYPES = %w[broken scale state].freeze
6+
57
task default: :test
68

7-
Rake::TestTask.new :test do |t|
8-
t.libs << :test
9+
Rake::TestTask.new(:test) do |t|
910
t.libs << :lib
10-
files = Dir['test/**/test_*.rb'].grep_v(/test_against_cluster_(state|broken)/)
11-
files = ARGV[1..] if ARGV.size > 1
12-
t.test_files = files
13-
t.options = '-v'
14-
end
15-
16-
Rake::TestTask.new :test_cluster_state do |t|
1711
t.libs << :test
18-
t.libs << :lib
19-
t.test_files = %w[test/test_against_cluster_state.rb]
2012
t.options = '-v'
13+
t.test_files = if ARGV.size > 1
14+
ARGV[1..]
15+
else
16+
Dir['test/**/test_*.rb'].grep_v(/test_against_cluster_(#{FREAKY_TEST_TYPES.join('|')})/)
17+
end
2118
end
2219

23-
Rake::TestTask.new :test_cluster_broken do |t|
24-
t.libs << :test
25-
t.libs << :lib
26-
t.test_files = %w[test/test_against_cluster_broken.rb]
27-
t.options = '-v'
20+
FREAKY_TEST_TYPES.each do |type|
21+
Rake::TestTask.new("test_cluster_#{type}".to_sym) do |t|
22+
t.libs << :lib
23+
t.libs << :test
24+
t.options = '-v'
25+
t.test_files = ["test/test_against_cluster_#{type}.rb"]
26+
end
2827
end
2928

3029
desc 'Wait for cluster to be ready'

docker-compose.scale.yaml

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
---
2+
services:
3+
node1: &node
4+
image: "redis:${REDIS_VERSION:-7}"
5+
command: >
6+
redis-server
7+
--maxmemory 64mb
8+
--maxmemory-policy allkeys-lru
9+
--appendonly yes
10+
--cluster-enabled yes
11+
--cluster-config-file nodes.conf
12+
--cluster-node-timeout 5000
13+
restart: "${RESTART_POLICY:-always}"
14+
healthcheck:
15+
test: ["CMD", "redis-cli", "ping"]
16+
interval: "7s"
17+
timeout: "5s"
18+
retries: 10
19+
ports:
20+
- "6379:6379"
21+
node2:
22+
<<: *node
23+
ports:
24+
- "6380:6379"
25+
node3:
26+
<<: *node
27+
ports:
28+
- "6381:6379"
29+
node4:
30+
<<: *node
31+
ports:
32+
- "6382:6379"
33+
node5:
34+
<<: *node
35+
ports:
36+
- "6383:6379"
37+
node6:
38+
<<: *node
39+
ports:
40+
- "6384:6379"
41+
node7:
42+
<<: *node
43+
ports:
44+
- "6385:6379"
45+
node8:
46+
<<: *node
47+
ports:
48+
- "6386:6379"
49+
clustering:
50+
image: "redis:${REDIS_VERSION:-7}"
51+
command: >
52+
bash -c "apt-get update > /dev/null
53+
&& apt-get install --no-install-recommends --no-install-suggests -y dnsutils > /dev/null
54+
&& rm -rf /var/lib/apt/lists/*
55+
&& yes yes | redis-cli --cluster create
56+
$$(dig node1 +short):6379
57+
$$(dig node2 +short):6379
58+
$$(dig node3 +short):6379
59+
$$(dig node4 +short):6379
60+
$$(dig node5 +short):6379
61+
$$(dig node6 +short):6379
62+
--cluster-replicas 1"
63+
depends_on:
64+
node1:
65+
condition: service_healthy
66+
node2:
67+
condition: service_healthy
68+
node3:
69+
condition: service_healthy
70+
node4:
71+
condition: service_healthy
72+
node5:
73+
condition: service_healthy
74+
node6:
75+
condition: service_healthy
76+
node7:
77+
condition: service_healthy
78+
node8:
79+
condition: service_healthy

lib/redis_client/cluster/command.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ def determine_first_key_position(command) # rubocop:disable Metrics/CyclomaticCo
8181
when 'memory'
8282
command[1].to_s.casecmp('usage').zero? ? 2 : 0
8383
when 'migrate'
84-
command[3] == '""' ? determine_optional_key_position(command, 'keys') : 3
84+
command[3].empty? ? determine_optional_key_position(command, 'keys') : 3
8585
when 'xread', 'xreadgroup'
8686
determine_optional_key_position(command, 'streams')
8787
else

lib/redis_client/cluster/errors.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ def initialize(errors)
1616
class OrchestrationCommandNotSupported < ::RedisClient::Error
1717
def initialize(command)
1818
str = ERR_ARG_NORMALIZATION.call(command).map(&:to_s).join(' ').upcase
19-
msg = "#{str} command should be used with care "\
20-
'only by applications orchestrating Redis Cluster, like redis-cli, '\
21-
'and the command if used out of the right context can leave the cluster '\
19+
msg = "#{str} command should be used with care " \
20+
'only by applications orchestrating Redis Cluster, like redis-cli, ' \
21+
'and the command if used out of the right context can leave the cluster ' \
2222
'in a wrong state or cause data loss.'
2323
super(msg)
2424
end
@@ -49,8 +49,8 @@ def initialize(command)
4949
class NodeMightBeDown < ::RedisClient::Error
5050
def initialize(_ = '')
5151
super(
52-
'The client is trying to fetch the latest cluster state '\
53-
'because a subset of nodes might be down. '\
52+
'The client is trying to fetch the latest cluster state ' \
53+
'because a subset of nodes might be down. ' \
5454
'It might continue to raise errors for a while.'
5555
)
5656
end

lib/redis_client/cluster/node.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,8 @@ def parse_node_info(info) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticC
7777
arr[8] = []
7878
next
7979
end
80-
81-
arr[8] = arr[8].split(',').map { |r| r.split('-').map { |s| Integer(s) } }
82-
arr[8] = arr[8].map { |a| a.size == 1 ? a << a.first : a }.map(&:sort)
80+
arr[8] = arr[8..].filter_map { |str| str.start_with?('[') ? nil : str.split('-').map { |s| Integer(s) } }
81+
.map { |a| a.size == 1 ? a << a.first : a }.map(&:sort)
8382
end
8483

8584
rows.map do |arr|

0 commit comments

Comments
 (0)