Skip to content

Commit 8964822

Browse files
committed
Try getting a new port if the current port isn't available.
1 parent 254332a commit 8964822

File tree

1 file changed

+68
-64
lines changed

1 file changed

+68
-64
lines changed

redis/tests/support/cluster.rs

Lines changed: 68 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
use std::convert::identity;
55
use std::env;
6-
use std::io::Read;
76
use std::process;
87
use std::thread::sleep;
98
use std::time::Duration;
@@ -125,20 +124,17 @@ impl RedisCluster {
125124
num_replicas: replicas,
126125
modules,
127126
mtls_enabled,
128-
mut ports,
127+
ports,
129128
} = configuration;
130129

131-
if ports.is_empty() {
132-
// We use a hashset in order to be sure that we have the right number
133-
// of unique ports.
134-
let mut hash = std::collections::HashSet::new();
135-
while hash.len() < nodes as usize {
136-
hash.insert(get_random_available_port());
137-
}
138-
ports = hash.into_iter().collect();
139-
}
130+
let optional_ports = if ports.is_empty() {
131+
vec![None; nodes as usize]
132+
} else {
133+
assert!(ports.len() == nodes as usize);
134+
ports.into_iter().map(Some).collect()
135+
};
136+
let mut chosen_ports = std::collections::HashSet::new();
140137

141-
let mut servers = vec![];
142138
let mut folders = vec![];
143139
let mut addrs = vec![];
144140
let mut tls_paths = None;
@@ -159,8 +155,8 @@ impl RedisCluster {
159155

160156
let max_attempts = 5;
161157

162-
for port in ports {
163-
servers.push(RedisServer::new_with_addr_tls_modules_and_spawner(
158+
let mut make_server = |port| {
159+
RedisServer::new_with_addr_tls_modules_and_spawner(
164160
ClusterType::build_addr(port),
165161
None,
166162
tls_paths.clone(),
@@ -194,65 +190,73 @@ impl RedisCluster {
194190
cmd.arg("--tls-replication").arg("yes");
195191
}
196192
}
197-
let addr = format!("127.0.0.1:{port}");
198193
cmd.current_dir(tempdir.path());
199194
folders.push(tempdir);
200-
addrs.push(addr.clone());
195+
cmd.spawn().unwrap()
196+
},
197+
)
198+
};
201199

200+
let verify_server = |server: &mut RedisServer| {
201+
let process = &mut server.process;
202+
match process.try_wait() {
203+
Ok(Some(status)) => {
204+
let log_file_contents = server.log_file_contents();
205+
let err =
206+
format!("redis server creation failed with status {status:?}.\nlog file: {log_file_contents}");
207+
eprintln!("Retrying: {err}");
208+
false
209+
}
210+
Ok(None) => {
211+
// wait for 10 seconds for the server to be available.
212+
let max_attempts = 200;
202213
let mut cur_attempts = 0;
203214
loop {
204-
let mut process = cmd.spawn().unwrap();
215+
if cur_attempts == max_attempts {
216+
let log_file_contents = server.log_file_contents();
217+
panic!("redis server creation failed: Address {} closed. {log_file_contents}", server.addr)
218+
}
219+
if port_in_use(&server.addr.to_string()) {
220+
break true;
221+
}
222+
eprintln!("Waiting for redis process to initialize");
205223
sleep(Duration::from_millis(50));
224+
cur_attempts += 1;
225+
}
226+
}
227+
Err(e) => {
228+
panic!("Unexpected error in redis server creation {e}");
229+
}
230+
}
231+
};
206232

207-
let log_file_index = cmd.get_args().position(|arg|arg == "--logfile").unwrap() + 1;
208-
let log_file_path = cmd.get_args().nth(log_file_index).unwrap();
209-
match process.try_wait() {
210-
Ok(Some(status)) => {
211-
let stdout = process.stdout.map_or(String::new(), |mut out|{
212-
let mut str = String::new();
213-
out.read_to_string(&mut str).unwrap();
214-
str
215-
});
216-
let stderr = process.stderr.map_or(String::new(), |mut out|{
217-
let mut str = String::new();
218-
out.read_to_string(&mut str).unwrap();
219-
str
220-
});
221-
222-
let log_file_contents = std::fs::read_to_string(log_file_path).unwrap();
223-
let err =
224-
format!("redis server creation failed with status {status:?}.\nstdout: `{stdout}`.\nstderr: `{stderr}`\nlog file: {log_file_contents}");
225-
if cur_attempts == max_attempts {
226-
panic!("{err}");
227-
}
228-
eprintln!("Retrying: {err}");
229-
cur_attempts += 1;
230-
}
231-
Ok(None) => {
232-
// wait for 10 seconds for the server to be available.
233-
let max_attempts = 200;
234-
let mut cur_attempts = 0;
235-
loop {
236-
if cur_attempts == max_attempts {
237-
let log_file_contents = std::fs::read_to_string(log_file_path).unwrap();
238-
panic!("redis server creation failed: Port {port} closed. {log_file_contents}")
239-
}
240-
if port_in_use(&addr) {
241-
return process;
242-
}
243-
eprintln!("Waiting for redis process to initialize");
244-
sleep(Duration::from_millis(50));
245-
cur_attempts += 1;
246-
}
247-
}
248-
Err(e) => {
249-
panic!("Unexpected error in redis server creation {e}");
233+
let servers = optional_ports
234+
.into_iter()
235+
.map(|port_option| {
236+
for _ in 0..5 {
237+
let port = match port_option {
238+
Some(port) => port,
239+
None => loop {
240+
let port = get_random_available_port();
241+
if chosen_ports.contains(&port) {
242+
continue;
250243
}
251-
}
244+
chosen_ports.insert(port);
245+
break port;
246+
},
247+
};
248+
let mut server = make_server(port);
249+
sleep(Duration::from_millis(50));
250+
251+
if verify_server(&mut server) {
252+
let addr = format!("127.0.0.1:{port}");
253+
addrs.push(addr.clone());
254+
return server;
252255
}
253-
},
254-
));
255-
}
256+
}
257+
panic!("Exhausted retries");
258+
})
259+
.collect();
256260

257261
let mut cmd = process::Command::new("redis-cli");
258262
cmd.stdout(process::Stdio::piped())

0 commit comments

Comments
 (0)