From 6bb2dab202ea7ae467a5f181065dc99543cf96f3 Mon Sep 17 00:00:00 2001 From: julio4 <30329843+julio4@users.noreply.github.com> Date: Wed, 8 Jul 2026 23:42:33 +0900 Subject: [PATCH] fix: supervise flashblock scheduler task --- crates/op-rbuilder/src/builder/payload.rs | 25 +++++++++++++++++++---- crates/op-rbuilder/src/metrics.rs | 3 +++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/crates/op-rbuilder/src/builder/payload.rs b/crates/op-rbuilder/src/builder/payload.rs index 48e6b51f..35a40d2b 100644 --- a/crates/op-rbuilder/src/builder/payload.rs +++ b/crates/op-rbuilder/src/builder/payload.rs @@ -20,6 +20,7 @@ use crate::{ }; use alloy_primitives::B256; use eyre::WrapErr as _; +use futures::FutureExt; use op_alloy_rpc_types_engine::OpFlashblockPayload; use reth_chainspec::EthChainSpec; use reth_node_api::PayloadBuilderError; @@ -796,16 +797,32 @@ where .map_err(|e| PayloadBuilderError::Other(e.into()))?; let (tx, rx) = mpsc::channel((expected_flashblocks + 1) as usize); - tokio::spawn( + let scheduler_payload_id = fb_payload.payload_id; + let scheduler_task = self.task_metrics .flashblock_timer .instrument(flashblock_scheduler.run( tx, payload_cancel.clone(), fb_cancel, - fb_payload.payload_id, - )), - ); + scheduler_payload_id, + )); + let scheduler_metrics = self.builder_ctx.metrics.clone(); + + self.executor.spawn_task(async move { + if std::panic::AssertUnwindSafe(scheduler_task) + .catch_unwind() + .await + .is_err() + { + scheduler_metrics.flashblock_scheduler_death.increment(1); + error!( + target: "payload_builder", + id = %scheduler_payload_id, + "Flashblock scheduler task panicked, no further flashblocks will be triggered for this payload", + ); + } + }); // State data was extracted in Phase 1 block scope above. // We carry (CacheState, Option) between iterations diff --git a/crates/op-rbuilder/src/metrics.rs b/crates/op-rbuilder/src/metrics.rs index 1aa9f251..1c2835d6 100644 --- a/crates/op-rbuilder/src/metrics.rs +++ b/crates/op-rbuilder/src/metrics.rs @@ -200,6 +200,9 @@ pub struct OpRBuilderMetrics { pub continuous_fee_improvement: Histogram, /// Builds completed but not published due to resolved gate pub flashblock_publish_suppressed_total: Counter, + /// Flashblock scheduler task ended abnormally (panicked) instead of + /// completing or being cancelled normally + pub flashblock_scheduler_death: Counter, /// TODO: Use labels for these /// Payload job ended because getPayload resolved pub payload_job_cancellation_resolved: Counter,