Subscribe to notifications about new blocks and 1) remove all included transactions from the caches 2) broadcast buffered out-of-order transactions when they are unblocked Re-subscribe in the event of a subscription failure.
(
client: C,
chain_id: ChainID,
tx_cache: TransactionCache,
tx_buffer: TransactionBuffer,
)
| 96 | /// |
| 97 | /// Re-subscribe in the event of a subscription failure. |
| 98 | async fn tx_cache_clearing_loop<C>( |
| 99 | client: C, |
| 100 | chain_id: ChainID, |
| 101 | tx_cache: TransactionCache, |
| 102 | tx_buffer: TransactionBuffer, |
| 103 | ) where |
| 104 | C: Client + SubscriptionClient + Send + Sync, |
| 105 | { |
| 106 | loop { |
| 107 | let query = Query::from(EventType::NewBlock); |
| 108 | |
| 109 | match client.subscribe(query).await { |
| 110 | Err(e) => { |
| 111 | tracing::warn!(error=?e, "failed to subscribe to NewBlocks; retrying later..."); |
| 112 | tokio::time::sleep(Duration::from_secs(RETRY_SLEEP_SECS)).await; |
| 113 | } |
| 114 | Ok(mut subscription) => { |
| 115 | while let Some(result) = subscription.next().await { |
| 116 | match result { |
| 117 | Err(e) => { |
| 118 | tracing::warn!(error=?e, "NewBlocks subscription failed; resubscribing..."); |
| 119 | break; |
| 120 | } |
| 121 | Ok(event) => { |
| 122 | if let EventData::NewBlock { |
| 123 | block: Some(block), .. |
| 124 | } = event.data |
| 125 | { |
| 126 | let txs = collect_txs(&block, &chain_id); |
| 127 | |
| 128 | if txs.is_empty() { |
| 129 | continue; |
| 130 | } |
| 131 | |
| 132 | let tx_hashes = txs.iter().map(|(h, _, _)| h); |
| 133 | let tx_nonces = || txs.iter().map(|(_, s, n)| (s, *n)); |
| 134 | |
| 135 | tx_cache.remove_many(tx_hashes); |
| 136 | // First remove all transactions which have been in the block (could be multiple from the same sender). |
| 137 | tx_buffer.remove_many(tx_nonces()); |
| 138 | // Then collect whatever is unblocked on top of those, ie. anything that hasn't been included, but now can. |
| 139 | let unblocked_msgs = tx_buffer.remove_unblocked(tx_nonces()); |
| 140 | // Send them all with best-effort. |
| 141 | send_msgs(&client, unblocked_msgs).await; |
| 142 | } |
| 143 | } |
| 144 | } |
| 145 | } |
| 146 | } |
| 147 | } |
| 148 | } |
| 149 | } |
| 150 | |
| 151 | /// Collect the identifiers of the transactions in the block. |
| 152 | fn collect_txs(block: &Block, chain_id: &ChainID) -> Vec<(et::TxHash, Address, Nonce)> { |
no test coverage detected