-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
docs(book): tracking state in ExExes #8804
Conversation
Co-authored-by: Dan Cline <[email protected]>
Co-authored-by: Dan Cline <[email protected]>
Co-authored-by: Oliver <[email protected]>
Co-authored-by: Oliver <[email protected]>
Co-authored-by: Oliver <[email protected]>
Co-authored-by: Oliver <[email protected]>
Co-authored-by: Oliver <[email protected]>
```rust,norun,noplayground,ignore | ||
use std::{ | ||
future::Future, | ||
pin::Pin, | ||
task::{ready, Context, Poll}, | ||
}; | ||
|
||
use reth::{api::FullNodeComponents, primitives::BlockNumber}; | ||
use reth_exex::{ExExContext, ExExEvent}; | ||
use reth_node_ethereum::EthereumNode; | ||
use reth_tracing::tracing::info; | ||
|
||
struct MyExEx<Node: FullNodeComponents> { | ||
ctx: ExExContext<Node>, | ||
/// First block that was committed since the start of the ExEx. | ||
first_block: Option<BlockNumber>, | ||
/// Total number of transactions committed. | ||
transactions: u64, | ||
} | ||
|
||
impl<Node: FullNodeComponents> MyExEx<Node> { | ||
fn new(ctx: ExExContext<Node>) -> Self { | ||
Self { | ||
ctx, | ||
first_block: None, | ||
transactions: 0, | ||
} | ||
} | ||
} | ||
|
||
impl<Node: FullNodeComponents> Future for MyExEx<Node> { | ||
type Output = eyre::Result<()>; | ||
|
||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
let this = self.get_mut(); | ||
|
||
while let Some(notification) = ready!(this.ctx.notifications.poll_recv(cx)) { | ||
if let Some(reverted_chain) = notification.reverted_chain() { | ||
this.transactions = this.transactions.saturating_sub( | ||
reverted_chain | ||
.blocks_iter() | ||
.map(|b| b.body.len() as u64) | ||
.sum(), | ||
); | ||
} | ||
|
||
if let Some(committed_chain) = notification.committed_chain() { | ||
this.first_block.get_or_insert(committed_chain.first().number); | ||
|
||
this.transactions += committed_chain | ||
.blocks_iter() | ||
.map(|b| b.body.len() as u64) | ||
.sum::<u64>(); | ||
|
||
this.ctx | ||
.events | ||
.send(ExExEvent::FinishedHeight(committed_chain.tip().number))?; | ||
} | ||
|
||
if let Some(first_block) = this.first_block { | ||
info!(%first_block, transactions = %this.transactions, "Total number of transactions"); | ||
} | ||
} | ||
|
||
Poll::Ready(Ok(())) | ||
} | ||
} | ||
|
||
fn main() -> eyre::Result<()> { | ||
reth::cli::Cli::parse_args().run(|builder, _| async move { | ||
let handle = builder | ||
.node(EthereumNode::default()) | ||
.install_exex("my-exex", |ctx| async move { Ok(MyExEx::new(ctx)) }) | ||
.launch() | ||
.await?; | ||
|
||
handle.wait_for_node_exit().await | ||
}) | ||
} | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't like that we basically repeat the whole snippet twice. How can we do it better?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't fully repeat the snippet but rather change some parts of it. I meant how we can do better at showing what changed in the code without repeating it all over again, but we can solve it later.
impl<Node: FullNodeComponents> Future for MyExEx<Node> { | ||
type Output = eyre::Result<()>; | ||
|
||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should also explain how you'd call out to other functions?
Prob we'd save most of the logic in async functions on the exex that the future loop calls?
```rust,norun,noplayground,ignore | ||
use std::{ | ||
future::Future, | ||
pin::Pin, | ||
task::{ready, Context, Poll}, | ||
}; | ||
|
||
use reth::{api::FullNodeComponents, primitives::BlockNumber}; | ||
use reth_exex::{ExExContext, ExExEvent}; | ||
use reth_node_ethereum::EthereumNode; | ||
use reth_tracing::tracing::info; | ||
|
||
struct MyExEx<Node: FullNodeComponents> { | ||
ctx: ExExContext<Node>, | ||
/// First block that was committed since the start of the ExEx. | ||
first_block: Option<BlockNumber>, | ||
/// Total number of transactions committed. | ||
transactions: u64, | ||
} | ||
|
||
impl<Node: FullNodeComponents> MyExEx<Node> { | ||
fn new(ctx: ExExContext<Node>) -> Self { | ||
Self { | ||
ctx, | ||
first_block: None, | ||
transactions: 0, | ||
} | ||
} | ||
} | ||
|
||
impl<Node: FullNodeComponents> Future for MyExEx<Node> { | ||
type Output = eyre::Result<()>; | ||
|
||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { | ||
let this = self.get_mut(); | ||
|
||
while let Some(notification) = ready!(this.ctx.notifications.poll_recv(cx)) { | ||
if let Some(reverted_chain) = notification.reverted_chain() { | ||
this.transactions = this.transactions.saturating_sub( | ||
reverted_chain | ||
.blocks_iter() | ||
.map(|b| b.body.len() as u64) | ||
.sum(), | ||
); | ||
} | ||
|
||
if let Some(committed_chain) = notification.committed_chain() { | ||
this.first_block.get_or_insert(committed_chain.first().number); | ||
|
||
this.transactions += committed_chain | ||
.blocks_iter() | ||
.map(|b| b.body.len() as u64) | ||
.sum::<u64>(); | ||
|
||
this.ctx | ||
.events | ||
.send(ExExEvent::FinishedHeight(committed_chain.tip().number))?; | ||
} | ||
|
||
if let Some(first_block) = this.first_block { | ||
info!(%first_block, transactions = %this.transactions, "Total number of transactions"); | ||
} | ||
} | ||
|
||
Poll::Ready(Ok(())) | ||
} | ||
} | ||
|
||
fn main() -> eyre::Result<()> { | ||
reth::cli::Cli::parse_args().run(|builder, _| async move { | ||
let handle = builder | ||
.node(EthereumNode::default()) | ||
.install_exex("my-exex", |ctx| async move { Ok(MyExEx::new(ctx)) }) | ||
.launch() | ||
.await?; | ||
|
||
handle.wait_for_node_exit().await | ||
}) | ||
} | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No description provided.