use std::fmt;
use std::sync::Arc;
use crate::Config;
use crate::RaftTypeConfig;
use crate::StorageError;
use crate::async_runtime::MpscSender;
use crate::core::SharedReplicateBatch;
use crate::core::notification::Notification;
use crate::progress::inflight_id::InflightId;
use crate::progress::stream_id::StreamId;
use crate::raft_state::IOId;
use crate::replication::response::Progress;
use crate::replication::response::ReplicationResult;
use crate::type_config::alias::CommittedVoteOf;
use crate::type_config::alias::InstantOf;
use crate::type_config::alias::MpscSenderOf;
use crate::type_config::alias::WatchReceiverOf;
use crate::vote::raft_vote::RaftVote;
#[derive(Clone)]
pub(crate) struct ReplicationContext<C>
where C: RaftTypeConfig
{
#[allow(dead_code)]
pub(crate) id: C::NodeId,
pub(crate) target: C::NodeId,
pub(crate) leader_vote: CommittedVoteOf<C>,
pub(crate) stream_id: StreamId,
pub(crate) config: Arc<Config>,
#[allow(clippy::type_complexity)]
pub(crate) tx_notify: MpscSenderOf<C, Notification<C>>,
pub(crate) cancel_rx: WatchReceiverOf<C, ()>,
pub(crate) replicate_batch: SharedReplicateBatch,
}
impl<C> ReplicationContext<C>
where C: RaftTypeConfig
{
pub(crate) fn leader_changed(&self, accepted_io: &IOId<C>) -> bool {
let current_leader = accepted_io.leader_id();
let belonging_leader = self.leader_vote.leader_id();
if current_leader == belonging_leader {
return false;
}
tracing::info!(
"{}: Leader changed from {} to {}, quit replication",
self,
belonging_leader,
current_leader
);
true
}
pub(crate) async fn notify_storage_error(&self, error: StorageError<C>) {
self.tx_notify.send(Notification::StorageError { error }).await.ok();
}
pub(crate) async fn notify_heartbeat_progress(&self, sending_time: InstantOf<C>) {
self.tx_notify
.send(Notification::HeartbeatProgress {
stream_id: self.stream_id,
target: self.target.clone(),
sending_time,
})
.await
.ok();
}
pub(crate) async fn notify_progress(
&self,
result: Result<ReplicationResult<C>, String>,
inflight_id: Option<InflightId>,
) {
self.tx_notify
.send(Notification::ReplicationProgress {
stream_id: self.stream_id,
progress: Progress {
target: self.target.clone(),
result,
},
inflight_id,
})
.await
.ok();
}
}
impl<C> fmt::Display for ReplicationContext<C>
where C: RaftTypeConfig
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{{id: {}, target: {}, {}}}", self.id, self.target, self.stream_id)
}
}
impl<C> fmt::Debug for ReplicationContext<C>
where C: RaftTypeConfig
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ReplicationContext")
.field("id", &self.id)
.field("target", &self.target)
.field("session_id", &self.stream_id)
.field("config", &self.config)
.finish_non_exhaustive()
}
}