|
| 1 | +use std::sync::Arc; |
| 2 | + |
1 | 3 | use alloy::consensus::TxEnvelope;
|
2 | 4 | use eyre::Error;
|
3 | 5 | use reqwest::{Client, Url};
|
4 | 6 | use serde::{Deserialize, Serialize};
|
5 | 7 | use serde_json::from_slice;
|
| 8 | +use tokio::{sync::mpsc, task::JoinHandle}; |
6 | 9 |
|
7 | 10 | pub use crate::config::BuilderConfig;
|
8 | 11 |
|
9 |
| -/// Response from the tx-pool endpoint. |
| 12 | +/// Models a response from the transaction pool. |
10 | 13 | #[derive(Debug, Clone, Serialize, Deserialize)]
|
11 | 14 | pub struct TxPoolResponse {
|
| 15 | + /// Holds the transactions property as a list on the response. |
12 | 16 | transactions: Vec<TxEnvelope>,
|
13 | 17 | }
|
14 | 18 |
|
15 | 19 | /// Implements a poller for the block builder to pull transactions from the transaction pool.
|
16 |
| -#[derive(Debug)] |
| 20 | +#[derive(Debug, Clone)] |
17 | 21 | pub struct TxPoller {
|
18 |
| - /// config for the builder |
| 22 | + /// Config values from the Builder. |
19 | 23 | pub config: BuilderConfig,
|
20 |
| - /// Reqwest client for fetching transactions from the tx-pool |
| 24 | + /// Reqwest Client for fetching transactions from the tx-pool. |
21 | 25 | pub client: Client,
|
22 | 26 | }
|
23 | 27 |
|
24 |
| -/// TxPoller implements a poller that fetches unique transactions from the transaction pool. |
| 28 | +/// TxPoller implements a poller task that fetches unique transactions from the transaction pool. |
25 | 29 | impl TxPoller {
|
26 |
| - /// returns a new TxPoller with the given config. |
| 30 | + /// Returns a new TxPoller with the given config. |
27 | 31 | pub fn new(config: &BuilderConfig) -> Self {
|
28 | 32 | Self { config: config.clone(), client: Client::new() }
|
29 | 33 | }
|
30 | 34 |
|
31 |
| - /// polls the tx-pool for unique transactions and evicts expired transactions. |
| 35 | + /// Polls the tx-pool for unique transactions and evicts expired transactions. |
32 | 36 | /// unique transactions that haven't been seen before are sent into the builder pipeline.
|
33 | 37 | pub async fn check_tx_cache(&mut self) -> Result<Vec<TxEnvelope>, Error> {
|
34 | 38 | let url: Url = Url::parse(&self.config.tx_pool_url)?.join("transactions")?;
|
35 | 39 | let result = self.client.get(url).send().await?;
|
36 | 40 | let response: TxPoolResponse = from_slice(result.text().await?.as_bytes())?;
|
37 | 41 | Ok(response.transactions)
|
38 | 42 | }
|
| 43 | + |
| 44 | + /// Spawns a task that trawls the cache for transactions and sends along anything it finds |
| 45 | + pub fn spawn(mut self) -> (mpsc::UnboundedReceiver<Arc<TxEnvelope>>, JoinHandle<()>) { |
| 46 | + let (outbound, inbound) = mpsc::unbounded_channel(); |
| 47 | + let jh = tokio::spawn(async move { |
| 48 | + loop { |
| 49 | + if let Ok(transactions) = self.check_tx_cache().await { |
| 50 | + tracing::debug!(count = ?transactions.len(), "found transactions"); |
| 51 | + for tx in transactions.iter() { |
| 52 | + if let Err(err) = outbound.send(Arc::new(tx.clone())) { |
| 53 | + tracing::error!(err = ?err, "failed to send transaction outbound"); |
| 54 | + } |
| 55 | + } |
| 56 | + } |
| 57 | + tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; |
| 58 | + } |
| 59 | + }); |
| 60 | + (inbound, jh) |
| 61 | + } |
39 | 62 | }
|
0 commit comments