diff --git a/lez/wallet-ffi/src/wallet.rs b/lez/wallet-ffi/src/wallet.rs index 79113824..e9c12f63 100644 --- a/lez/wallet-ffi/src/wallet.rs +++ b/lez/wallet-ffi/src/wallet.rs @@ -250,7 +250,7 @@ pub unsafe extern "C" fn wallet_ffi_save(handle: *mut WalletHandle) -> WalletFfi match wallet .store_persistent_data() - .and_then(|()| block_on(wallet.dump_statistics())) + .and_then(|()| block_on(wallet.client_rotation())) { Ok(()) => WalletFfiError::Success, Err(e) => { diff --git a/lez/wallet/src/cli/mod.rs b/lez/wallet/src/cli/mod.rs index d7ef49bd..d436de52 100644 --- a/lez/wallet/src/cli/mod.rs +++ b/lez/wallet/src/cli/mod.rs @@ -295,9 +295,9 @@ pub async fn execute_subcommand( // Kind of a sledgehammer solution, but it is not clear if there is the case to not store // statistics wallet_core - .dump_statistics() + .client_rotation() .await - .context("Failed to store statistics")?; + .context("Failed to rotate wallet")?; Ok(subcommand_ret) } diff --git a/lez/wallet/src/lib.rs b/lez/wallet/src/lib.rs index b884f4eb..e8be74bf 100644 --- a/lez/wallet/src/lib.rs +++ b/lez/wallet/src/lib.rs @@ -253,7 +253,8 @@ impl WalletCore { Ok(()) } - pub async fn dump_statistics(&mut self) -> Result<()> { + /// Rotates multi-client and stores metrics. + pub async fn client_rotation(&mut self) -> Result<()> { let leader_statistic = self .statistics .get_mut(self.multi_sequencer_client.leader_url()) @@ -263,6 +264,14 @@ impl WalletCore { .update_statistics(leader_statistic) .await; + self.multi_sequencer_client + .rotate( + &self.config.sequencers, + &mut self.statistics, + self.config.calibration_limit, + ) + .await?; + let statistics_serialized = serde_json::to_vec_pretty(&self.statistics)?; let mut file = tokio::fs::File::create(&self.statistics_path) .await diff --git a/lez/wallet/src/multi_client.rs b/lez/wallet/src/multi_client.rs index ee41aa06..ef4e246f 100644 --- a/lez/wallet/src/multi_client.rs +++ b/lez/wallet/src/multi_client.rs @@ -88,11 +88,11 @@ pub struct MultiSequencerClient { } impl MultiSequencerClient { - pub async fn new( + async fn setup( conn_data: &[SequencerConnectionData], statistics: &mut HashMap, calibration_limit: usize, - ) -> Result { + ) -> Result<(Url, SequencerClient)> { let mut client_list = HashMap::new(); for SequencerConnectionData { @@ -141,12 +141,23 @@ impl MultiSequencerClient { client_list.insert(sequencer_addr.clone(), sequencer_client); } - let (leader_url, leader) = choose_leader(&client_list, statistics) + // Dropping client list, for reasons why, see comment in structure definition. + + let res = choose_leader(&client_list, statistics) .ok_or_else(|| anyhow::anyhow!("Failed to find leader"))?; - log::info!("Chosen leader is {leader_url:?}"); + log::info!("Chosen leader is {:?}", res.0); + + Ok(res) + } + + pub async fn new( + conn_data: &[SequencerConnectionData], + statistics: &mut HashMap, + calibration_limit: usize, + ) -> Result { + let (leader_url, leader) = Self::setup(conn_data, statistics, calibration_limit).await?; - // Dropping client list, for reasons why, see comment in structure definition. Ok(Self { leader, leader_url, @@ -154,6 +165,23 @@ impl MultiSequencerClient { }) } + /// Re-choose leader, `statistic_updates` must be empty. + pub async fn rotate( + &mut self, + conn_data: &[SequencerConnectionData], + statistics: &mut HashMap, + calibration_limit: usize, + ) -> Result<()> { + let (leader_url, leader) = Self::setup(conn_data, statistics, calibration_limit).await?; + + log::info!("Chosen leader is {leader_url:?}"); + + self.leader = leader; + self.leader_url = leader_url; + + Ok(()) + } + #[must_use] pub const fn leader(&self) -> &SequencerClient { &self.leader