diff --git a/crates/curp/src/client/unary.rs b/crates/curp/src/client/unary.rs index d0c7de17d..fdccfdf61 100644 --- a/crates/curp/src/client/unary.rs +++ b/crates/curp/src/client/unary.rs @@ -9,7 +9,7 @@ use tracing::{debug, warn}; use super::{state::State, ClientApi, LeaderStateUpdate, ProposeResponse, RepeatableClientApi}; use crate::{ members::ServerId, - quorum, + quorum, recover_quorum, rpc::{ connect::ConnectApi, ConfChange, CurpError, FetchClusterRequest, FetchClusterResponse, FetchReadStateRequest, Member, MoveLeaderRequest, ProposeConfChangeRequest, ProposeId, @@ -97,12 +97,17 @@ impl Unary { }) .await; let super_quorum = super_quorum(responses.len()); + let recover_quorum = recover_quorum(responses.len()); let mut err: Option = None; let mut execute_result: Option = None; - let mut ok_cnt = 0; + let (mut ok_cnt, mut key_conflict_cnt) = (0, 0); while let Some((id, resp)) = responses.next().await { + if key_conflict_cnt >= recover_quorum { + return Err(CurpError::KeyConflict(())); + } + let resp = match resp { Ok(resp) => resp.into_inner(), Err(e) => { @@ -110,6 +115,9 @@ impl Unary { if e.should_abort_fast_round() { return Err(e); } + if matches!(e, CurpError::KeyConflict(())) { + key_conflict_cnt.add_assign(1); + } if let Some(old_err) = err.as_ref() { if old_err.priority() <= e.priority() { err = Some(e);