refactor(rpc_client): const number of retries for send and confirm transaction (#18390) (#18427)

* refactor(rpc_client): simplfy send and confirm transaction flow

* chore: configurable num of retries for send and confirm

(cherry picked from commit 70234dfdf4)

Co-authored-by: hrls <viktor.kharitonovich@gmail.com>
This commit is contained in:
mergify[bot]
2021-07-13 06:28:11 +00:00
committed by GitHub
parent e5d60bc56d
commit 8dd5ec6fbd

View File

@ -1012,49 +1012,55 @@ impl RpcClient {
&self, &self,
transaction: &Transaction, transaction: &Transaction,
) -> ClientResult<Signature> { ) -> ClientResult<Signature> {
let signature = self.send_transaction(transaction)?; const SEND_RETRIES: usize = 1;
let recent_blockhash = if uses_durable_nonce(transaction).is_some() { const GET_STATUS_RETRIES: usize = usize::MAX;
self.get_recent_blockhash_with_commitment(CommitmentConfig::processed())?
.value 'sending: for _ in 0..SEND_RETRIES {
.0 let signature = self.send_transaction(transaction)?;
} else {
transaction.message.recent_blockhash let recent_blockhash = if uses_durable_nonce(transaction).is_some() {
}; let (recent_blockhash, ..) = self
let status = loop { .get_recent_blockhash_with_commitment(CommitmentConfig::processed())?
let status = self.get_signature_status(&signature)?; .value;
if status.is_none() { recent_blockhash
if self
.get_fee_calculator_for_blockhash_with_commitment(
&recent_blockhash,
CommitmentConfig::processed(),
)?
.value
.is_none()
{
break status;
}
} else { } else {
break status; transaction.message.recent_blockhash
};
for status_retry in 0..GET_STATUS_RETRIES {
match self.get_signature_status(&signature)? {
Some(Ok(_)) => return Ok(signature),
Some(Err(e)) => return Err(e.into()),
None => {
let fee_calculator = self
.get_fee_calculator_for_blockhash_with_commitment(
&recent_blockhash,
CommitmentConfig::processed(),
)?
.value;
if fee_calculator.is_none() {
// Block hash is not found by some reason
break 'sending;
} else if cfg!(not(test))
// Ignore sleep at last step.
&& status_retry < GET_STATUS_RETRIES
{
// Retry twice a second
sleep(Duration::from_millis(500));
continue;
}
}
}
} }
if cfg!(not(test)) {
// Retry twice a second
sleep(Duration::from_millis(500));
}
};
if let Some(result) = status {
match result {
Ok(_) => Ok(signature),
Err(err) => Err(err.into()),
}
} else {
Err(RpcError::ForUser(
"unable to confirm transaction. \
This can happen in situations such as transaction expiration \
and insufficient fee-payer funds"
.to_string(),
)
.into())
} }
Err(RpcError::ForUser(
"unable to confirm transaction. \
This can happen in situations such as transaction expiration \
and insufficient fee-payer funds"
.to_string(),
)
.into())
} }
/// Note that `get_account` returns `Err(..)` if the account does not exist whereas /// Note that `get_account` returns `Err(..)` if the account does not exist whereas