Skip to content

refactor(l2): use spawned for monitor #3635

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

Open
wants to merge 26 commits into
base: main
Choose a base branch
from
Open

Conversation

gianbelinche
Copy link
Contributor

@gianbelinche gianbelinche commented Jul 14, 2025

Motivation
Refactor monitor so that it uses spawned crate

Description
Currently the monitor is a tokio task, refactor it to use spawned

How to test

  • Add --monitor to the init-l2-no-metrics target in crates/l2/Makefile.
  • Run a Sequencer (I suggest make restart in crates/l2).
  • Run the prover with make init-prover in crates/l2.
  • Run make test in crates/l2.

Depends on #3622

Closes #3515

Copy link

github-actions bot commented Jul 14, 2025

Lines of code report

Total lines added: 111
Total lines removed: 15
Total lines changed: 126

Detailed view
+------------------------------------------------+-------+------+
| File                                           | Lines | Diff |
+------------------------------------------------+-------+------+
| ethrex/crates/l2/monitor/app.rs                | 419   | +90  |
+------------------------------------------------+-------+------+
| ethrex/crates/l2/monitor/mod.rs                | 5     | -15  |
+------------------------------------------------+-------+------+
| ethrex/crates/l2/monitor/widget/node_status.rs | 75    | +1   |
+------------------------------------------------+-------+------+
| ethrex/crates/l2/sequencer/errors.rs           | 324   | +2   |
+------------------------------------------------+-------+------+
| ethrex/crates/l2/sequencer/mod.rs              | 191   | +18  |
+------------------------------------------------+-------+------+

@gianbelinche gianbelinche changed the base branch from main to monitor-quit July 15, 2025 20:09
@gianbelinche gianbelinche moved this to In Progress in ethrex_l2 Jul 15, 2025
@gianbelinche gianbelinche marked this pull request as ready for review July 15, 2025 20:42
@gianbelinche gianbelinche requested a review from a team as a code owner July 15, 2025 20:42
@gianbelinche gianbelinche moved this from In Progress to In Review in ethrex_l2 Jul 15, 2025
Comment on lines +174 to +189
task_set.spawn(async move {
let mut finished = false;
while !finished {
let message = ethrex_monitor
.call(monitor::app::CallInMessage::Finished)
.await
.map_err(MonitorError::GenServerError)?;
if let monitor::app::OutMessage::ShouldQuit(should_quit) = message {
finished = should_quit;
}

tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
}

Ok(())
});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this part? If so, we should consider moving to wait on the CancellationToken of the GenServer, like this:

https://github.com/lambdaclass/spawned/blob/f4ddd843501165bf8aefef004ffb49ac04b2ef48/concurrency/src/tasks/stream.rs#L26

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is, that after the genserver stops (the user pressed Shift + Q) we want to finish the whole process.
I'll try to implement it with a cancellation token, ideally we should have a way to check if a genserver is running, instead of having the custom ShouldQuit message

.inspect_err(|err| error!("Monitor Error: {err}"));
if !state.widget.should_quit {
send_after(
Duration::from_millis(1),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should use the tick_rate, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the monitor function we do this event poll

Duration::from_millis(widget.tick_rate).saturating_sub(widget.last_tick.elapsed());
if !event::poll(timeout)?

So that we are able to both render the widget and process events, so if a long time has passed since the last render, we prioritize rendering over events.
If we sent a message only after tick_rate ms, the timeout will always be near 0, and so no events would be processed


let timeout =
Duration::from_millis(widget.tick_rate).saturating_sub(widget.last_tick.elapsed());
if !event::poll(timeout)? {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This event::poll is blocking. This breaks with the current runtime's requirement for cooperative multitasking. We should either 1) use an async event poll 2) change the genserver to be start_blocking or 3) change the structure so we poll outside the genserver (recommended if possible)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the time being i start the genserver with start_blocking

Base automatically changed from monitor-quit to main July 16, 2025 20:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
L2 Rollup client
Projects
Status: In Review
Development

Successfully merging this pull request may close these issues.

3 participants