feature: pending transaction retries repeatedly before assuming dropped (#1221)

This commit is contained in:
James Prestwich 2022-05-05 07:22:47 -07:00 committed by GitHub
parent bc958792af
commit c70cd81de0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 21 additions and 3 deletions

View File

@ -153,6 +153,8 @@
### Unreleased ### Unreleased
- Add retries to the pending transaction future
[1221](https://github.com/gakonst/ethers-rs/pull/1221)
- Add support for basic and bearer authentication in http and non-wasm websockets. - Add support for basic and bearer authentication in http and non-wasm websockets.
[829](https://github.com/gakonst/ethers-rs/pull/829) [829](https://github.com/gakonst/ethers-rs/pull/829)
- Export `ethers_providers::IpcError` and `ethers_providers::QuorumError` - Export `ethers_providers::IpcError` and `ethers_providers::QuorumError`

View File

@ -62,8 +62,11 @@ pub struct PendingTransaction<'a, P> {
provider: &'a Provider<P>, provider: &'a Provider<P>,
state: PendingTxState<'a>, state: PendingTxState<'a>,
interval: Box<dyn Stream<Item = ()> + Send + Unpin>, interval: Box<dyn Stream<Item = ()> + Send + Unpin>,
retries_remaining: usize,
} }
const DEFAULT_RETRIES: usize = 3;
impl<'a, P: JsonRpcClient> PendingTransaction<'a, P> { impl<'a, P: JsonRpcClient> PendingTransaction<'a, P> {
/// Creates a new pending transaction poller from a hash and a provider /// Creates a new pending transaction poller from a hash and a provider
pub fn new(tx_hash: TxHash, provider: &'a Provider<P>) -> Self { pub fn new(tx_hash: TxHash, provider: &'a Provider<P>) -> Self {
@ -74,6 +77,7 @@ impl<'a, P: JsonRpcClient> PendingTransaction<'a, P> {
provider, provider,
state: PendingTxState::InitialDelay(delay), state: PendingTxState::InitialDelay(delay),
interval: Box::new(interval(DEFAULT_POLL_INTERVAL)), interval: Box::new(interval(DEFAULT_POLL_INTERVAL)),
retries_remaining: DEFAULT_RETRIES,
} }
} }
@ -111,6 +115,13 @@ impl<'a, P: JsonRpcClient> PendingTransaction<'a, P> {
self self
} }
/// Set retries
#[must_use]
pub fn retries(mut self, retries: usize) -> Self {
self.retries_remaining = retries;
self
}
} }
impl<'a, P> PendingTransaction<'a, P> { impl<'a, P> PendingTransaction<'a, P> {
@ -188,11 +199,16 @@ impl<'a, P: JsonRpcClient> Future for PendingTransaction<'a, P> {
let tx_opt = tx_res.unwrap(); let tx_opt = tx_res.unwrap();
// If the tx is no longer in the mempool, return Ok(None) // If the tx is no longer in the mempool, return Ok(None)
if tx_opt.is_none() { if tx_opt.is_none() {
if *this.retries_remaining == 0 {
tracing::debug!("Dropped from mempool, pending tx {:?}", *this.tx_hash); tracing::debug!("Dropped from mempool, pending tx {:?}", *this.tx_hash);
*this.state = PendingTxState::Completed; *this.state = PendingTxState::Completed;
return Poll::Ready(Ok(None)) return Poll::Ready(Ok(None))
} }
*this.retries_remaining -= 1;
rewake_with_new_state!(ctx, this, PendingTxState::PausedGettingTx);
}
// If it hasn't confirmed yet, poll again later // If it hasn't confirmed yet, poll again later
let tx = tx_opt.unwrap(); let tx = tx_opt.unwrap();
rewake_with_new_state_if!( rewake_with_new_state_if!(