Skip to content

Commit 87a1e15

Browse files
committed
Fix #17 - Add TCP connection timeout
1 parent cbf4c58 commit 87a1e15

File tree

5 files changed

+55
-31
lines changed

5 files changed

+55
-31
lines changed

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ authors = ["ufoscout <[email protected]>"]
55
edition = "2018"
66

77
[dependencies]
8-
port_check = "0.1"
8+
port_check = "0.1.3"
99

1010
[dev-dependencies]
1111
atomic-counter = "1.0"

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ This is discussed further [here](https://stackoverflow.com/questions/30063907/us
7474
# Additional configuration options
7575
The behaviour of the wait utility can be configured with the following environment variables:
7676
- *WAIT_HOSTS*: comma separated list of pairs host:port for which you want to wait.
77-
- *WAIT_HOSTS_TIMEOUT*: max number of seconds to wait for the hosts to be available before failure. The default is 30 seconds.
77+
- *WAIT_HOSTS_TIMEOUT*: max number of seconds to wait for all the hosts to be available before failure. The default is 30 seconds.
78+
- *WAIT_HOST_CONNECT_TIMEOUT*: The timeout of a single TCP connection to a remote host before attempting a new connection. The default is 5 seconds.
7879
- *WAIT_BEFORE_HOSTS*: number of seconds to wait (sleep) before start checking for the hosts availability
7980
- *WAIT_AFTER_HOSTS*: number of seconds to wait (sleep) once all the hosts are available
8081
- *WAIT_SLEEP_INTERVAL*: number of seconds to sleep between retries. The default is 1 second.

src/lib.rs

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
use std::time::Duration;
2+
13
pub mod env_reader;
24
pub mod sleeper;
35

46
pub struct Config {
57
pub hosts: String,
6-
pub timeout: u64,
8+
pub global_timeout: u64,
9+
pub tcp_connection_timeout: u64,
710
pub wait_before: u64,
811
pub wait_after: u64,
912
pub wait_sleep_interval: u64,
@@ -19,7 +22,8 @@ pub fn wait(
1922
println!("{}", LINE_SEPARATOR);
2023
println!("docker-compose-wait - starting with configuration:");
2124
println!(" - Hosts to be waiting for: [{}]", config.hosts);
22-
println!(" - Timeout before failure: {} seconds ", config.timeout);
25+
println!(" - Timeout before failure: {} seconds ", config.global_timeout);
26+
println!(" - TCP connection timeout before retry: {} seconds ", config.tcp_connection_timeout);
2327
println!(
2428
" - Sleeping time before checking for hosts availability: {} seconds",
2529
config.wait_before
@@ -43,12 +47,12 @@ pub fn wait(
4347
sleep.reset();
4448
for host in config.hosts.trim().split(',') {
4549
println!("Checking availability of {}", host);
46-
while !port_check::is_port_reachable(&host.trim().to_string()) {
50+
while !port_check::is_port_reachable_with_timeout(&host.trim().to_string().parse().expect("The host IP should be valid"), Duration::from_secs(config.tcp_connection_timeout)) {
4751
println!("Host {} not yet available...", host);
48-
if sleep.elapsed(config.timeout) {
52+
if sleep.elapsed(config.global_timeout) {
4953
println!(
5054
"Timeout! After {} seconds some hosts are still not reachable",
51-
config.timeout
55+
config.global_timeout
5256
);
5357
on_timeout();
5458
return;
@@ -76,10 +80,14 @@ pub fn wait(
7680
pub fn config_from_env() -> Config {
7781
Config {
7882
hosts: crate::env_reader::env_var(&"WAIT_HOSTS".to_string(), "".to_string()),
79-
timeout: to_int(
83+
global_timeout: to_int(
8084
&crate::env_reader::env_var(&"WAIT_HOSTS_TIMEOUT".to_string(), "".to_string()),
8185
30,
8286
),
87+
tcp_connection_timeout: to_int(
88+
&crate::env_reader::env_var(&"WAIT_HOST_CONNECT_TIMEOUT".to_string(), "".to_string()),
89+
5,
90+
),
8391
wait_before: to_int(
8492
&crate::env_reader::env_var(&"WAIT_BEFORE_HOSTS".to_string(), "".to_string()),
8593
0,
@@ -139,23 +147,25 @@ mod test {
139147
}
140148

141149
#[test]
142-
fn default_timeout_should_be_30() {
150+
fn config_should_use_default_values() {
143151
let _guard = TEST_MUTEX.lock().unwrap();
144-
set_env("", "", "10o", "10", "");
152+
set_env("", "", "10o", "10", "", "abc");
145153
let config = config_from_env();
146154
assert_eq!("".to_string(), config.hosts);
147-
assert_eq!(30, config.timeout);
155+
assert_eq!(30, config.global_timeout);
156+
assert_eq!(5, config.tcp_connection_timeout);
148157
assert_eq!(0, config.wait_before);
149158
assert_eq!(10, config.wait_after);
150159
}
151160

152161
#[test]
153162
fn should_get_config_values_from_env() {
154163
let _guard = TEST_MUTEX.lock().unwrap();
155-
set_env("localhost:1234", "20", "2", "3", "4");
164+
set_env("localhost:1234", "20", "2", "3", "4", "23");
156165
let config = config_from_env();
157166
assert_eq!("localhost:1234".to_string(), config.hosts);
158-
assert_eq!(20, config.timeout);
167+
assert_eq!(20, config.global_timeout);
168+
assert_eq!(23, config.tcp_connection_timeout);
159169
assert_eq!(2, config.wait_before);
160170
assert_eq!(3, config.wait_after);
161171
assert_eq!(4, config.wait_sleep_interval);
@@ -164,19 +174,21 @@ mod test {
164174
#[test]
165175
fn should_get_default_config_values() {
166176
let _guard = TEST_MUTEX.lock().unwrap();
167-
set_env("localhost:1234", "", "", "", "");
177+
set_env("localhost:1234", "", "", "", "", "");
168178
let config = config_from_env();
169179
assert_eq!("localhost:1234".to_string(), config.hosts);
170-
assert_eq!(30, config.timeout);
180+
assert_eq!(30, config.global_timeout);
181+
assert_eq!(5, config.tcp_connection_timeout);
171182
assert_eq!(0, config.wait_before);
172183
assert_eq!(0, config.wait_after);
173184
assert_eq!(1, config.wait_sleep_interval);
174185
}
175186

176-
fn set_env(hosts: &str, timeout: &str, before: &str, after: &str, sleep: &str) {
187+
fn set_env(hosts: &str, timeout: &str, before: &str, after: &str, sleep: &str, tcp_timeout: &str) {
177188
env::set_var("WAIT_BEFORE_HOSTS", before.to_string());
178189
env::set_var("WAIT_AFTER_HOSTS", after.to_string());
179190
env::set_var("WAIT_HOSTS_TIMEOUT", timeout.to_string());
191+
env::set_var("WAIT_HOST_CONNECT_TIMEOUT", tcp_timeout.to_string());
180192
env::set_var("WAIT_HOSTS", hosts.to_string());
181193
env::set_var("WAIT_SLEEP_INTERVAL", sleep.to_string());
182194
}

tests/integration_test.rs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ fn should_wait_5_seconds_before() {
1111
let mut sleeper = MillisSleeper::default();
1212
wait::wait(
1313
&mut sleeper,
14-
&new_config("", 1, wait_for, 0, 1),
14+
&new_config("", 1, wait_for, 0, 1, 1),
1515
&mut on_timeout,
1616
);
1717
assert!(millis_elapsed(start) >= wait_for)
@@ -24,7 +24,7 @@ fn should_wait_10_seconds_after() {
2424
let mut sleeper = MillisSleeper::default();
2525
wait::wait(
2626
&mut sleeper,
27-
&new_config("", 1, 0, wait_for, 1),
27+
&new_config("", 1, 0, wait_for, 1, 1),
2828
&mut on_timeout,
2929
);
3030
assert!(millis_elapsed(start) >= wait_for)
@@ -37,7 +37,7 @@ fn should_wait_before_and_after() {
3737
let mut sleeper = MillisSleeper::default();
3838
wait::wait(
3939
&mut sleeper,
40-
&new_config("", 1, wait_for, wait_for, 1),
40+
&new_config("", 1, wait_for, wait_for, 1, 1),
4141
&mut on_timeout,
4242
);
4343
assert!(millis_elapsed(start) >= (wait_for + wait_for))
@@ -47,16 +47,26 @@ fn should_wait_before_and_after() {
4747
fn should_execute_without_wait() {
4848
let start = Instant::now();
4949
let mut sleeper = MillisSleeper::default();
50-
wait::wait(&mut sleeper, &new_config("", 1, 0, 0, 1), &mut on_timeout);
50+
wait::wait(&mut sleeper, &new_config("", 1, 0, 0, 1, 1), &mut on_timeout);
5151
assert!(millis_elapsed(start) <= 5)
5252
}
5353

54+
#[test]
55+
fn should_sleep_the_specified_time_between_checks() {
56+
let start = Instant::now();
57+
let mut sleeper = MillisSleeper::default();
58+
wait::wait(&mut sleeper, &new_config("198.19.255.255:1", 2_000, 0, 0, 10, 1), &mut on_timeout);
59+
let elapsed = millis_elapsed(start);
60+
assert!(elapsed >= 2010);
61+
assert!(elapsed < 3000);
62+
}
63+
5464
#[test]
5565
fn should_exit_on_timeout() {
5666
let timeout = 25;
5767
let wait_before = 30;
5868
let wait_after = 300;
59-
let hosts = "localhost:".to_string() + &free_port().to_string();
69+
let hosts = format!("127.0.0.1:{}", free_port());
6070
let start = Instant::now();
6171
let mut sleeper = MillisSleeper::default();
6272

@@ -68,7 +78,7 @@ fn should_exit_on_timeout() {
6878

6979
wait::wait(
7080
&mut sleeper,
71-
&new_config(&hosts, timeout, wait_before, wait_after, 1),
81+
&new_config(&hosts, timeout, wait_before, wait_after, 1, 1),
7282
&mut fun,
7383
);
7484

@@ -101,7 +111,7 @@ fn should_identify_the_open_port() {
101111
thread::sleep(time::Duration::from_millis(250));
102112
wait::wait(
103113
&mut sleeper,
104-
&new_config(&hosts, timeout, wait_before, wait_after, 1),
114+
&new_config(&hosts, timeout, wait_before, wait_after, 1, 1),
105115
&mut fun,
106116
);
107117

@@ -137,7 +147,7 @@ fn should_wait_multiple_hosts() {
137147
thread::sleep(time::Duration::from_millis(250));
138148
wait::wait(
139149
&mut sleeper,
140-
&new_config(&hosts, timeout, wait_before, wait_after, 1),
150+
&new_config(&hosts, timeout, wait_before, wait_after, 1, 1),
141151
&mut fun,
142152
);
143153

@@ -170,7 +180,7 @@ fn should_fail_if_not_all_hosts_are_available() {
170180
thread::sleep(time::Duration::from_millis(250));
171181
wait::wait(
172182
&mut sleeper,
173-
&new_config(&hosts, timeout, wait_before, wait_after, 1),
183+
&new_config(&hosts, timeout, wait_before, wait_after, 1, 1),
174184
&mut fun,
175185
);
176186

@@ -182,10 +192,11 @@ fn should_fail_if_not_all_hosts_are_available() {
182192

183193
fn on_timeout() {}
184194

185-
fn new_config(hosts: &str, timeout: u64, before: u64, after: u64, sleep: u64) -> wait::Config {
195+
fn new_config(hosts: &str, timeout: u64, before: u64, after: u64, sleep: u64, tcp_connection_timeout: u64) -> wait::Config {
186196
wait::Config {
187197
hosts: hosts.to_string(),
188-
timeout: timeout,
198+
global_timeout: timeout,
199+
tcp_connection_timeout,
189200
wait_before: before,
190201
wait_after: after,
191202
wait_sleep_interval: sleep,
@@ -216,7 +227,7 @@ fn free_port() -> u16 {
216227
}
217228

218229
fn millis_elapsed(start: Instant) -> u64 {
219-
let elapsed = start.elapsed().subsec_nanos() / 1000000;
230+
let elapsed = start.elapsed().as_millis();
220231
println!("Millis elapsed {}", elapsed);
221232
elapsed as u64
222233
}

0 commit comments

Comments
 (0)