From 97460d239b90b51b38b1b27c10420a75b3c41c88 Mon Sep 17 00:00:00 2001 From: Kaze Date: Mon, 1 Dec 2025 14:16:28 +0900 Subject: [PATCH 01/12] feat(autopilot): reduce excessive looping of main loop --- crates/autopilot/src/infra/persistence/mod.rs | 5 ++ crates/autopilot/src/run_loop.rs | 70 +++++++++++++++++++ .../V094__add_order_notification_trigger.sql | 14 ++++ 3 files changed, 89 insertions(+) create mode 100644 database/sql/V094__add_order_notification_trigger.sql diff --git a/crates/autopilot/src/infra/persistence/mod.rs b/crates/autopilot/src/infra/persistence/mod.rs index 4153b2029c..2ab9e65ecd 100644 --- a/crates/autopilot/src/infra/persistence/mod.rs +++ b/crates/autopilot/src/infra/persistence/mod.rs @@ -95,6 +95,11 @@ impl Persistence { LeaderLock::new(self.postgres.pool.clone(), key, Duration::from_millis(200)) } + /// Returns a reference to the Postgres instance for direct database access. + pub fn postgres(&self) -> &Arc { + &self.postgres + } + /// Fetches the ID that should be used for the next auction. pub async fn get_next_auction_id(&self) -> Result { let _timer = Metrics::get() diff --git a/crates/autopilot/src/run_loop.rs b/crates/autopilot/src/run_loop.rs index 2a1232cb1d..24869e3d38 100644 --- a/crates/autopilot/src/run_loop.rs +++ b/crates/autopilot/src/run_loop.rs @@ -92,6 +92,8 @@ pub struct RunLoop { maintenance: Arc, competition_updates_sender: tokio::sync::mpsc::UnboundedSender<()>, winner_selection: winner_selection::Arbitrator, + /// Receiver for new order notifications from the database + new_order_receiver: Arc>>, } impl RunLoop { @@ -111,6 +113,12 @@ impl RunLoop { let max_winners = config.max_winners_per_auction.get(); let weth = eth.contracts().wrapped_native_token(); + // Create channel for new order notifications + let (new_order_sender, new_order_receiver) = tokio::sync::mpsc::unbounded_channel(); + + // Spawn background task to listen for database notifications + Self::spawn_order_listener(persistence.clone(), new_order_sender); + Self { config, eth, @@ -124,6 +132,7 @@ impl RunLoop { maintenance, competition_updates_sender, winner_selection: winner_selection::Arbitrator { max_winners, weth }, + new_order_receiver: Arc::new(Mutex::new(new_order_receiver)), } } @@ -150,6 +159,9 @@ impl RunLoop { let mut leader_lock_tracker = LeaderLockTracker::new(leader); while !control.should_shutdown() { + // Wait for either a new block or a new order before proceeding + self_arc.wait_for_block_or_order().await; + leader_lock_tracker.try_acquire().await; let start_block = self_arc @@ -181,6 +193,64 @@ impl RunLoop { leader_lock_tracker.release().await; } + /// Spawns a background task that listens for new order notifications from PostgreSQL. + fn spawn_order_listener( + persistence: infra::Persistence, + sender: tokio::sync::mpsc::UnboundedSender<()>, + ) { + tokio::spawn(async move { + // Get a dedicated connection from the pool for listening + let pool = persistence.postgres().pool.clone(); + + loop { + match sqlx::postgres::PgListener::connect_with(&pool).await { + Ok(mut listener) => { + tracing::info!("connected to PostgreSQL for order notifications"); + + if let Err(err) = listener.listen("new_order").await { + tracing::error!(?err, "failed to listen on 'new_order' channel"); + tokio::time::sleep(Duration::from_secs(5)).await; + continue; + } + + loop { + match listener.recv().await { + Ok(_notification) => { + tracing::trace!("received new order notification"); + // Ignore send errors - the receiver might have been dropped + let _ = sender.send(()); + } + Err(err) => { + tracing::error!(?err, "error receiving notification"); + break; + } + } + } + } + Err(err) => { + tracing::error!(?err, "failed to create PostgreSQL listener"); + tokio::time::sleep(Duration::from_secs(5)).await; + } + } + } + }); + } + + /// Waits for either a new block to be mined or a new order to arrive in the database. + async fn wait_for_block_or_order(&self) { + let next_block = ethrpc::block_stream::next_block(self.eth.current_block()); + let mut receiver = self.new_order_receiver.lock().await; + + tokio::select! { + _ = next_block => { + tracing::trace!("new block detected"); + } + _ = receiver.recv() => { + tracing::trace!("new order notification received"); + } + } + } + async fn update_caches(&self, prev_block: &mut Option, is_leader: bool) -> BlockInfo { let current_block = *self.eth.current_block().borrow(); let time_since_last_block = current_block.observed_at.elapsed(); diff --git a/database/sql/V094__add_order_notification_trigger.sql b/database/sql/V094__add_order_notification_trigger.sql new file mode 100644 index 0000000000..f6193dca1b --- /dev/null +++ b/database/sql/V094__add_order_notification_trigger.sql @@ -0,0 +1,14 @@ +-- Create a trigger function that notifies on new orders +CREATE OR REPLACE FUNCTION notify_new_order() +RETURNS trigger AS $$ +BEGIN + PERFORM pg_notify('new_order', ''); + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +-- Create a trigger that fires after each insert on the orders table +CREATE TRIGGER order_insert_notify +AFTER INSERT ON orders +FOR EACH ROW +EXECUTE FUNCTION notify_new_order(); From aea34d25e1696c9a64c240f6fc6f8307425eb3fb Mon Sep 17 00:00:00 2001 From: Kaze Date: Mon, 1 Dec 2025 17:25:25 +0900 Subject: [PATCH 02/12] improve logging and ensure the message is delivered --- crates/autopilot/src/run_loop.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/crates/autopilot/src/run_loop.rs b/crates/autopilot/src/run_loop.rs index 24869e3d38..0b3916fa65 100644 --- a/crates/autopilot/src/run_loop.rs +++ b/crates/autopilot/src/run_loop.rs @@ -216,12 +216,16 @@ impl RunLoop { loop { match listener.recv().await { Ok(_notification) => { - tracing::trace!("received new order notification"); - // Ignore send errors - the receiver might have been dropped - let _ = sender.send(()); + tracing::debug!("received order notification from postgres"); + match sender.send(()) { + Ok(_) => {} + Err(err) => { + tracing::error!(?err, "failed to send order notification signal to main loop - channel closed"); + } + } } Err(err) => { - tracing::error!(?err, "error receiving notification"); + tracing::error!(?err, "error receiving notification from postgres"); break; } } @@ -243,10 +247,14 @@ impl RunLoop { tokio::select! { _ = next_block => { - tracing::trace!("new block detected"); + tracing::debug!("received new block") } - _ = receiver.recv() => { - tracing::trace!("new order notification received"); + result = receiver.recv() => { + if result.is_some() { + tracing::debug!("received new order"); + } else { + tracing::error!("order notification channel closed"); + } } } } From bd670e1dde8d99950610f1aa77a974fef5dbbd10 Mon Sep 17 00:00:00 2001 From: Kaze Date: Mon, 1 Dec 2025 17:35:56 +0900 Subject: [PATCH 03/12] increase playground log verbosity (from other branch) --- playground/docker-compose.fork.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playground/docker-compose.fork.yml b/playground/docker-compose.fork.yml index 6b68b9bef7..17f401cfb2 100644 --- a/playground/docker-compose.fork.yml +++ b/playground/docker-compose.fork.yml @@ -110,7 +110,7 @@ services: environment: - DB_WRITE_URL=postgres://db:5432/?user=${POSTGRES_USER}&password=${POSTGRES_PASSWORD} - DB_READ_URL=postgres://db:5432/?user=${POSTGRES_USER}&password=${POSTGRES_PASSWORD} - - LOG_FILTER=warn,autopilot=info,shared=info,shared::price_estimation=info + - LOG_FILTER=warn,autopilot=debug,shared=info,shared::price_estimation=info - NODE_URL=http://chain:8545 - SIMULATION_NODE_URL=http://chain:8545 - SETTLE_INTERVAL=15s From 36871d28fc798efbf0201a816f015a45ddff9b08 Mon Sep 17 00:00:00 2001 From: Kaze Date: Mon, 1 Dec 2025 17:36:39 +0900 Subject: [PATCH 04/12] just fmt --- crates/autopilot/src/run_loop.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/crates/autopilot/src/run_loop.rs b/crates/autopilot/src/run_loop.rs index 0b3916fa65..9667068876 100644 --- a/crates/autopilot/src/run_loop.rs +++ b/crates/autopilot/src/run_loop.rs @@ -193,7 +193,8 @@ impl RunLoop { leader_lock_tracker.release().await; } - /// Spawns a background task that listens for new order notifications from PostgreSQL. + /// Spawns a background task that listens for new order notifications from + /// PostgreSQL. fn spawn_order_listener( persistence: infra::Persistence, sender: tokio::sync::mpsc::UnboundedSender<()>, @@ -220,12 +221,19 @@ impl RunLoop { match sender.send(()) { Ok(_) => {} Err(err) => { - tracing::error!(?err, "failed to send order notification signal to main loop - channel closed"); + tracing::error!( + ?err, + "failed to send order notification signal to main \ + loop - channel closed" + ); } } } Err(err) => { - tracing::error!(?err, "error receiving notification from postgres"); + tracing::error!( + ?err, + "error receiving notification from postgres" + ); break; } } @@ -240,7 +248,8 @@ impl RunLoop { }); } - /// Waits for either a new block to be mined or a new order to arrive in the database. + /// Waits for either a new block to be mined or a new order to arrive in the + /// database. async fn wait_for_block_or_order(&self) { let next_block = ethrpc::block_stream::next_block(self.eth.current_block()); let mut receiver = self.new_order_receiver.lock().await; From b8626cef761fadd310a6501c0212e41f48e295c9 Mon Sep 17 00:00:00 2001 From: Kaze Date: Tue, 2 Dec 2025 23:17:30 +0900 Subject: [PATCH 05/12] changes from feedback * use Notify from tokio instead of channel * move the notification function into the persistence module * update the trigger to return the newly created order ID so that it can be immediately accessed/updated into a cache --- crates/autopilot/src/infra/persistence/mod.rs | 46 ++++++++- crates/autopilot/src/run_loop.rs | 95 ++++--------------- .../V094__add_order_notification_trigger.sql | 3 +- 3 files changed, 63 insertions(+), 81 deletions(-) diff --git a/crates/autopilot/src/infra/persistence/mod.rs b/crates/autopilot/src/infra/persistence/mod.rs index 2ab9e65ecd..468e9f617e 100644 --- a/crates/autopilot/src/infra/persistence/mod.rs +++ b/crates/autopilot/src/infra/persistence/mod.rs @@ -95,9 +95,49 @@ impl Persistence { LeaderLock::new(self.postgres.pool.clone(), key, Duration::from_millis(200)) } - /// Returns a reference to the Postgres instance for direct database access. - pub fn postgres(&self) -> &Arc { - &self.postgres + /// Spawns a background task that listens for new order notifications from + /// PostgreSQL and notifies via the provided Notify. + pub fn spawn_order_listener(&self, notify: Arc) { + let pool = self.postgres.pool.clone(); + tokio::spawn(async move { + loop { + match sqlx::postgres::PgListener::connect_with(&pool).await { + Ok(mut listener) => { + tracing::info!("connected to PostgreSQL for order notifications"); + + if let Err(err) = listener.listen("new_order").await { + tracing::error!(?err, "failed to listen on 'new_order' channel"); + tokio::time::sleep(Duration::from_secs(5)).await; + continue; + } + + loop { + match listener.recv().await { + Ok(notification) => { + let order_uid = notification.payload(); + tracing::debug!( + order_uid, + "received order notification from postgres" + ); + notify.notify_one(); + } + Err(err) => { + tracing::error!( + ?err, + "error receiving notification from postgres" + ); + break; + } + } + } + } + Err(err) => { + tracing::error!(?err, "failed to create PostgreSQL listener"); + tokio::time::sleep(Duration::from_secs(5)).await; + } + } + } + }); } /// Fetches the ID that should be used for the next auction. diff --git a/crates/autopilot/src/run_loop.rs b/crates/autopilot/src/run_loop.rs index 9667068876..042160a750 100644 --- a/crates/autopilot/src/run_loop.rs +++ b/crates/autopilot/src/run_loop.rs @@ -92,8 +92,8 @@ pub struct RunLoop { maintenance: Arc, competition_updates_sender: tokio::sync::mpsc::UnboundedSender<()>, winner_selection: winner_selection::Arbitrator, - /// Receiver for new order notifications from the database - new_order_receiver: Arc>>, + /// Notifier that wakes the main loop on new blocks or orders + wake_notify: Arc, } impl RunLoop { @@ -113,11 +113,12 @@ impl RunLoop { let max_winners = config.max_winners_per_auction.get(); let weth = eth.contracts().wrapped_native_token(); - // Create channel for new order notifications - let (new_order_sender, new_order_receiver) = tokio::sync::mpsc::unbounded_channel(); + // Create notifier that wakes the main loop on new blocks or orders + let wake_notify = Arc::new(tokio::sync::Notify::new()); - // Spawn background task to listen for database notifications - Self::spawn_order_listener(persistence.clone(), new_order_sender); + // Spawn background tasks to listen for events + persistence.spawn_order_listener(wake_notify.clone()); + Self::spawn_block_listener(eth.current_block().clone(), wake_notify.clone()); Self { config, @@ -132,7 +133,7 @@ impl RunLoop { maintenance, competition_updates_sender, winner_selection: winner_selection::Arbitrator { max_winners, weth }, - new_order_receiver: Arc::new(Mutex::new(new_order_receiver)), + wake_notify, } } @@ -159,8 +160,8 @@ impl RunLoop { let mut leader_lock_tracker = LeaderLockTracker::new(leader); while !control.should_shutdown() { - // Wait for either a new block or a new order before proceeding - self_arc.wait_for_block_or_order().await; + // Wait for a new block or order before proceeding + self_arc.wake_notify.notified().await; leader_lock_tracker.try_acquire().await; @@ -193,81 +194,21 @@ impl RunLoop { leader_lock_tracker.release().await; } - /// Spawns a background task that listens for new order notifications from - /// PostgreSQL. - fn spawn_order_listener( - persistence: infra::Persistence, - sender: tokio::sync::mpsc::UnboundedSender<()>, + /// Spawns a background task that listens for new blocks from the + /// blockchain. + fn spawn_block_listener( + current_block: ethrpc::block_stream::CurrentBlockWatcher, + notify: Arc, ) { tokio::spawn(async move { - // Get a dedicated connection from the pool for listening - let pool = persistence.postgres().pool.clone(); - loop { - match sqlx::postgres::PgListener::connect_with(&pool).await { - Ok(mut listener) => { - tracing::info!("connected to PostgreSQL for order notifications"); - - if let Err(err) = listener.listen("new_order").await { - tracing::error!(?err, "failed to listen on 'new_order' channel"); - tokio::time::sleep(Duration::from_secs(5)).await; - continue; - } - - loop { - match listener.recv().await { - Ok(_notification) => { - tracing::debug!("received order notification from postgres"); - match sender.send(()) { - Ok(_) => {} - Err(err) => { - tracing::error!( - ?err, - "failed to send order notification signal to main \ - loop - channel closed" - ); - } - } - } - Err(err) => { - tracing::error!( - ?err, - "error receiving notification from postgres" - ); - break; - } - } - } - } - Err(err) => { - tracing::error!(?err, "failed to create PostgreSQL listener"); - tokio::time::sleep(Duration::from_secs(5)).await; - } - } + ethrpc::block_stream::next_block(¤t_block).await; + tracing::debug!("received new block"); + notify.notify_one(); } }); } - /// Waits for either a new block to be mined or a new order to arrive in the - /// database. - async fn wait_for_block_or_order(&self) { - let next_block = ethrpc::block_stream::next_block(self.eth.current_block()); - let mut receiver = self.new_order_receiver.lock().await; - - tokio::select! { - _ = next_block => { - tracing::debug!("received new block") - } - result = receiver.recv() => { - if result.is_some() { - tracing::debug!("received new order"); - } else { - tracing::error!("order notification channel closed"); - } - } - } - } - async fn update_caches(&self, prev_block: &mut Option, is_leader: bool) -> BlockInfo { let current_block = *self.eth.current_block().borrow(); let time_since_last_block = current_block.observed_at.elapsed(); diff --git a/database/sql/V094__add_order_notification_trigger.sql b/database/sql/V094__add_order_notification_trigger.sql index f6193dca1b..ca721454ce 100644 --- a/database/sql/V094__add_order_notification_trigger.sql +++ b/database/sql/V094__add_order_notification_trigger.sql @@ -1,8 +1,9 @@ -- Create a trigger function that notifies on new orders +-- The notification payload contains the hex-encoded order UID CREATE OR REPLACE FUNCTION notify_new_order() RETURNS trigger AS $$ BEGIN - PERFORM pg_notify('new_order', ''); + PERFORM pg_notify('new_order', encode(NEW.uid, 'hex')); RETURN NEW; END; $$ LANGUAGE plpgsql; From 1316c2b0c34f2a4e55d70f74c4dd7ffe0fe07667 Mon Sep 17 00:00:00 2001 From: Kaze Date: Tue, 2 Dec 2025 23:33:45 +0900 Subject: [PATCH 06/12] add notification for onchain-orders table and try to make the notify loop more beautiful with an early return --- crates/autopilot/src/infra/persistence/mod.rs | 55 +++++++++---------- .../V094__add_order_notification_trigger.sql | 6 ++ 2 files changed, 31 insertions(+), 30 deletions(-) diff --git a/crates/autopilot/src/infra/persistence/mod.rs b/crates/autopilot/src/infra/persistence/mod.rs index 468e9f617e..80c0b25a1b 100644 --- a/crates/autopilot/src/infra/persistence/mod.rs +++ b/crates/autopilot/src/infra/persistence/mod.rs @@ -101,39 +101,34 @@ impl Persistence { let pool = self.postgres.pool.clone(); tokio::spawn(async move { loop { - match sqlx::postgres::PgListener::connect_with(&pool).await { - Ok(mut listener) => { - tracing::info!("connected to PostgreSQL for order notifications"); - - if let Err(err) = listener.listen("new_order").await { - tracing::error!(?err, "failed to listen on 'new_order' channel"); - tokio::time::sleep(Duration::from_secs(5)).await; - continue; - } - - loop { - match listener.recv().await { - Ok(notification) => { - let order_uid = notification.payload(); - tracing::debug!( - order_uid, - "received order notification from postgres" - ); - notify.notify_one(); - } - Err(err) => { - tracing::error!( - ?err, - "error receiving notification from postgres" - ); - break; - } - } - } - } + let mut listener = match sqlx::postgres::PgListener::connect_with(&pool).await { + Ok(listener) => listener, Err(err) => { tracing::error!(?err, "failed to create PostgreSQL listener"); tokio::time::sleep(Duration::from_secs(5)).await; + continue; + } + }; + + tracing::info!("connected to PostgreSQL for order notifications"); + + if let Err(err) = listener.listen("new_order").await { + tracing::error!(?err, "failed to listen on 'new_order' channel"); + tokio::time::sleep(Duration::from_secs(5)).await; + continue; + } + + loop { + match listener.recv().await { + Ok(notification) => { + let order_uid = notification.payload(); + tracing::debug!(order_uid, "received order notification from postgres"); + notify.notify_one(); + } + Err(err) => { + tracing::error!(?err, "error receiving notification from postgres"); + break; + } } } } diff --git a/database/sql/V094__add_order_notification_trigger.sql b/database/sql/V094__add_order_notification_trigger.sql index ca721454ce..9f322d1e4f 100644 --- a/database/sql/V094__add_order_notification_trigger.sql +++ b/database/sql/V094__add_order_notification_trigger.sql @@ -13,3 +13,9 @@ CREATE TRIGGER order_insert_notify AFTER INSERT ON orders FOR EACH ROW EXECUTE FUNCTION notify_new_order(); + +-- Create a trigger that fires after each insert on the orders table +CREATE TRIGGER onchain_order_insert_notify +AFTER INSERT ON onchain_orders +FOR EACH ROW +EXECUTE FUNCTION notify_new_order(); From 43d084708e297aae39b2301efa1a769ce3245878 Mon Sep 17 00:00:00 2001 From: Kaze Date: Wed, 3 Dec 2025 16:19:16 +0900 Subject: [PATCH 07/12] undo sql change --- database/sql/V094__add_order_notification_trigger.sql | 6 ------ 1 file changed, 6 deletions(-) diff --git a/database/sql/V094__add_order_notification_trigger.sql b/database/sql/V094__add_order_notification_trigger.sql index 9f322d1e4f..ca721454ce 100644 --- a/database/sql/V094__add_order_notification_trigger.sql +++ b/database/sql/V094__add_order_notification_trigger.sql @@ -13,9 +13,3 @@ CREATE TRIGGER order_insert_notify AFTER INSERT ON orders FOR EACH ROW EXECUTE FUNCTION notify_new_order(); - --- Create a trigger that fires after each insert on the orders table -CREATE TRIGGER onchain_order_insert_notify -AFTER INSERT ON onchain_orders -FOR EACH ROW -EXECUTE FUNCTION notify_new_order(); From 3f7b7d2d18e0bc3863eeac2a16247cac8dc4ac18 Mon Sep 17 00:00:00 2001 From: Kaze Date: Fri, 5 Dec 2025 22:33:58 +0900 Subject: [PATCH 08/12] move the notify wait to after the cache population as suggested by comment --- crates/autopilot/src/run_loop.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/autopilot/src/run_loop.rs b/crates/autopilot/src/run_loop.rs index 54a08d65b3..dafe902d63 100644 --- a/crates/autopilot/src/run_loop.rs +++ b/crates/autopilot/src/run_loop.rs @@ -160,15 +160,16 @@ impl RunLoop { let mut leader_lock_tracker = LeaderLockTracker::new(leader); while !control.should_shutdown() { - // Wait for a new block or order before proceeding - self_arc.wake_notify.notified().await; - leader_lock_tracker.try_acquire().await; let start_block = self_arc .update_caches(&mut last_block, leader_lock_tracker.is_leader()) .await; + // Wait for a new block or order before proceeding (we do this *after* caches + // are loaded to reduce auction start time) + self_arc.wake_notify.notified().await; + // caches are warmed up, we're ready to do leader work if let Some(startup) = self_arc.probes.startup.as_ref() { startup.store(true, Ordering::Release); From 5712c3628416505444e90161e1391e4fc561190c Mon Sep 17 00:00:00 2001 From: Kaze Date: Mon, 8 Dec 2025 13:46:25 +0900 Subject: [PATCH 09/12] add an additional block mint and extra time to ensure the autopilot picks up the cancelled order for the next auction --- crates/e2e/tests/e2e/order_cancellation.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/e2e/tests/e2e/order_cancellation.rs b/crates/e2e/tests/e2e/order_cancellation.rs index 774c12d59b..b42118b8dc 100644 --- a/crates/e2e/tests/e2e/order_cancellation.rs +++ b/crates/e2e/tests/e2e/order_cancellation.rs @@ -214,6 +214,10 @@ async fn order_cancellation(web3: Web3) { // Cancel one of them. cancel_order(order_uids[0]).await; + // Mint a couple blocks (the autopilot might not pick it up immediately) + tokio::time::sleep(std::time::Duration::from_millis(200)).await; + onchain.mint_block().await; + tokio::time::sleep(std::time::Duration::from_millis(200)).await; onchain.mint_block().await; wait_for_condition(TIMEOUT, || async { services.get_auction().await.auction.orders.len() == 2 From a945efc3b140c56fd85bfb3c125df9c9805c68cc Mon Sep 17 00:00:00 2001 From: Kaze Date: Mon, 8 Dec 2025 14:01:20 +0900 Subject: [PATCH 10/12] try creating a block every loop --- crates/e2e/tests/e2e/order_cancellation.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/crates/e2e/tests/e2e/order_cancellation.rs b/crates/e2e/tests/e2e/order_cancellation.rs index b42118b8dc..0d3d7a1af8 100644 --- a/crates/e2e/tests/e2e/order_cancellation.rs +++ b/crates/e2e/tests/e2e/order_cancellation.rs @@ -214,12 +214,10 @@ async fn order_cancellation(web3: Web3) { // Cancel one of them. cancel_order(order_uids[0]).await; - // Mint a couple blocks (the autopilot might not pick it up immediately) - tokio::time::sleep(std::time::Duration::from_millis(200)).await; - onchain.mint_block().await; - tokio::time::sleep(std::time::Duration::from_millis(200)).await; - onchain.mint_block().await; wait_for_condition(TIMEOUT, || async { + // continue minting another block to make sure the autopilot eventually + // refreshes its cache + onchain.mint_block().await; services.get_auction().await.auction.orders.len() == 2 }) .await From 3fd8a9ff0b1b007ce25f6b78753bee517cfe3e1c Mon Sep 17 00:00:00 2001 From: Kaze Date: Mon, 8 Dec 2025 14:09:32 +0900 Subject: [PATCH 11/12] its working, just need to apply to the second cancellation set --- crates/e2e/tests/e2e/order_cancellation.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/e2e/tests/e2e/order_cancellation.rs b/crates/e2e/tests/e2e/order_cancellation.rs index 0d3d7a1af8..98bc7b89ae 100644 --- a/crates/e2e/tests/e2e/order_cancellation.rs +++ b/crates/e2e/tests/e2e/order_cancellation.rs @@ -240,8 +240,10 @@ async fn order_cancellation(web3: Web3) { // Cancel the other two. cancel_orders(vec![order_uids[1], order_uids[2]]).await; - onchain.mint_block().await; wait_for_condition(TIMEOUT, || async { + // continue minting another block to make sure the autopilot eventually + // refreshes its cache + onchain.mint_block().await; services.get_auction().await.auction.orders.is_empty() }) .await From 3d073d79717624d4ac36265c8ae0d211fc0a6ced Mon Sep 17 00:00:00 2001 From: Kaze Date: Mon, 8 Dec 2025 15:53:12 +0900 Subject: [PATCH 12/12] try to fix another test with similar looking issue --- crates/e2e/tests/e2e/tracking_insufficient_funds.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/e2e/tests/e2e/tracking_insufficient_funds.rs b/crates/e2e/tests/e2e/tracking_insufficient_funds.rs index eea7456e6b..1d38b8af94 100644 --- a/crates/e2e/tests/e2e/tracking_insufficient_funds.rs +++ b/crates/e2e/tests/e2e/tracking_insufficient_funds.rs @@ -144,8 +144,8 @@ async fn test(web3: Web3) { .send_and_watch() .await .unwrap(); - onchain.mint_block().await; let orders_updated = || async { + onchain.mint_block().await; let events_a = crate::database::events_of_order(services.db(), &uid_a).await; let events_b = crate::database::events_of_order(services.db(), &uid_b).await; let order_b_correct_events = events_b.into_iter().map(|e| e.label).collect::>() @@ -166,8 +166,8 @@ async fn test(web3: Web3) { .send_and_watch() .await .unwrap(); - onchain.mint_block().await; let orders_updated = || async { + onchain.mint_block().await; let events_a = crate::database::events_of_order(services.db(), &uid_b).await; let events_b = crate::database::events_of_order(services.db(), &uid_b).await; events_a.last().map(|o| o.label) == Some(OrderEventLabel::Traded)