Skip to content

Commit 26ceb4d

Browse files
committed
Retry initial client connections
Previously, `corerpc-node` would try to establish a connection via the given `Auth` cookie, and would panic if it couldn't setup a initial connection. Only the rest of the initial setup steps would be retried with time-delay. This however was race-y, as the auth cookie might not already be synced to disk on first startup of a fresh `bitcoind` instance (with fresh data dir), when we try to connect for the first time. Here, we move the intial connection logic into the retry loop to simply also retry it instead of panicking.
1 parent 2b410f2 commit 26ceb4d

File tree

1 file changed

+46
-30
lines changed

1 file changed

+46
-30
lines changed

node/src/lib.rs

Lines changed: 46 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -383,45 +383,61 @@ impl Node {
383383
thread::sleep(Duration::from_millis(1000));
384384
assert!(process.stderr.is_none());
385385

386-
let mut i = 0;
386+
let mut tries = 0;
387387
let auth = Auth::CookieFile(cookie_file.clone());
388-
let client_base =
389-
Client::new_with_auth(&rpc_url, auth.clone()).expect("failed to create client");
390388

391389
let client = loop {
390+
tries += 1;
391+
392+
if tries > 10 {
393+
error!("failed to get a response from bitcoind");
394+
return Err(Error::NoBitcoindInstance.into());
395+
}
396+
397+
let client_base = match Client::new_with_auth(&rpc_url, auth.clone()) {
398+
Ok(client) => client,
399+
Err(e) => {
400+
error!("failed to create client: {}. Retrying!", e);
401+
thread::sleep(Duration::from_millis(1000));
402+
continue;
403+
}
404+
};
405+
392406
// Just use serde value because changes to the GetBlockchainInfo type make debugging hard.
393407
let client_result: Result<serde_json::Value, _> =
394408
client_base.call("getblockchaininfo", &[]);
395409

396-
if client_result.is_ok() {
397-
let url = match &conf.wallet {
398-
Some(wallet) => {
399-
debug!("trying to create/load wallet: {}", wallet);
400-
// Debugging logic here implicitly tests `into_model` for create/load wallet.
401-
match client_base.create_wallet(wallet) {
402-
Ok(json) => {
403-
debug!("created wallet: {}", json.name());
404-
}
405-
Err(e) => {
406-
debug!("initial create_wallet failed, try load instead: {:?}", e);
407-
let wallet = client_base.load_wallet(wallet)?.name();
408-
debug!("loaded wallet: {}", wallet);
410+
match client_result {
411+
Ok(_) => {
412+
let url = match &conf.wallet {
413+
Some(wallet) => {
414+
debug!("trying to create/load wallet: {}", wallet);
415+
// Debugging logic here implicitly tests `into_model` for create/load wallet.
416+
match client_base.create_wallet(wallet) {
417+
Ok(json) => {
418+
debug!("created wallet: {}", json.name());
419+
}
420+
Err(e) => {
421+
debug!(
422+
"initial create_wallet failed, try load instead: {:?}",
423+
e
424+
);
425+
let wallet = client_base.load_wallet(wallet)?.name();
426+
debug!("loaded wallet: {}", wallet);
427+
}
409428
}
429+
format!("{}/wallet/{}", rpc_url, wallet)
410430
}
411-
format!("{}/wallet/{}", rpc_url, wallet)
412-
}
413-
None => rpc_url,
414-
};
415-
debug!("creating client with url: {}", url);
416-
break Client::new_with_auth(&url, auth)?;
417-
}
418-
419-
thread::sleep(Duration::from_millis(1000));
420-
421-
i += 1;
422-
if i > 10 {
423-
error!("failed to get a response from bitcoind");
424-
return Err(Error::NoBitcoindInstance.into());
431+
None => rpc_url,
432+
};
433+
debug!("creating client with url: {}", url);
434+
break Client::new_with_auth(&url, auth)?;
435+
}
436+
Err(e) => {
437+
error!("failed to get a response from bitcoind: {}. Retrying!", e);
438+
thread::sleep(Duration::from_millis(1000));
439+
continue;
440+
}
425441
}
426442
};
427443

0 commit comments

Comments
 (0)