fix(wallet): added client rotation

This commit is contained in:
Pravdyvy 2026-07-17 17:31:11 +03:00
parent 0bc08c7357
commit b3810ff77d
4 changed files with 46 additions and 9 deletions

View File

@ -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) => {

View File

@ -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)
}

View File

@ -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

View File

@ -88,11 +88,11 @@ pub struct MultiSequencerClient {
}
impl MultiSequencerClient {
pub async fn new(
async fn setup(
conn_data: &[SequencerConnectionData],
statistics: &mut HashMap<Url, Statistics>,
calibration_limit: usize,
) -> Result<Self> {
) -> 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<Url, Statistics>,
calibration_limit: usize,
) -> Result<Self> {
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<Url, Statistics>,
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