use super::capacity_snapshot::{CapacitySnapshot, read_capacity_snapshot};
use crate::server::participant::ParticipantSemanticError;
use liminal::durability::DurableStore;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(super) enum PreviousStop {
Clean,
Unclean,
Unknown,
}
pub(super) struct ConversationRepair {
pub(super) server_incarnation: u64,
pub(super) conversation_id: u64,
pub(super) done: usize,
pub(super) total: usize,
pub(super) appended_rows: u64,
pub(super) conversation_elapsed_ms: u64,
pub(super) elapsed_ms: u64,
}
impl PreviousStop {
pub(super) fn read(
store: &dyn DurableStore,
current: u64,
) -> Result<Self, ParticipantSemanticError> {
if current == 1 {
return Ok(Self::Unknown);
}
match read_capacity_snapshot(store)? {
Some((_, Ok(CapacitySnapshot::LegacyCleanStop(_)))) => Ok(Self::Unknown),
Some((
_,
Ok(CapacitySnapshot::CleanStop {
server_incarnation, ..
}),
)) if server_incarnation.checked_add(1) == Some(current) => Ok(Self::Clean),
Some((_, Err(refusal))) => {
tracing::warn!(%refusal, "previous stop's capacity publication was refused by name");
Ok(Self::Unclean)
}
_ => Ok(Self::Unclean),
}
}
pub(super) const fn name(self) -> &'static str {
match self {
Self::Clean => "clean",
Self::Unclean => "unclean",
Self::Unknown => "unknown",
}
}
pub(super) fn started(self, server_incarnation: u64, conversations: usize) {
if self == Self::Unclean {
tracing::warn!(
step = "restart repair",
server_incarnation,
conversations,
previous_stop = self.name(),
"restart repair started"
);
} else {
tracing::info!(
step = "restart repair",
server_incarnation,
conversations,
previous_stop = self.name(),
"restart repair started"
);
}
}
pub(super) fn conversation_finished(self, progress: &ConversationRepair) {
if self == Self::Unclean {
tracing::warn!(
step = "restart repair",
previous_stop = self.name(),
server_incarnation = progress.server_incarnation,
conversation_id = progress.conversation_id,
done = progress.done,
total = progress.total,
appended_rows = progress.appended_rows,
conversation_elapsed_ms = progress.conversation_elapsed_ms,
elapsed_ms = progress.elapsed_ms,
"restart repair finished a conversation"
);
} else {
tracing::info!(
step = "restart repair",
previous_stop = self.name(),
server_incarnation = progress.server_incarnation,
conversation_id = progress.conversation_id,
done = progress.done,
total = progress.total,
appended_rows = progress.appended_rows,
conversation_elapsed_ms = progress.conversation_elapsed_ms,
elapsed_ms = progress.elapsed_ms,
"restart repair finished a conversation"
);
}
}
pub(super) fn finished(self, server_incarnation: u64, conversations: usize, elapsed_ms: u64) {
if self == Self::Unclean {
tracing::warn!(
step = "restart repair",
server_incarnation,
conversations,
previous_stop = self.name(),
elapsed_ms,
"restart repair finished"
);
} else {
tracing::info!(
step = "restart repair",
server_incarnation,
conversations,
previous_stop = self.name(),
elapsed_ms,
"restart repair finished"
);
}
}
}