use crate::history::{
clock::ClockProvenance,
epoch::{CohortTopology, EpochTag, LsnKind, MaterializationSafety},
identity::{ArtifactRef, IdentityDiscipline},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Timestamp {
pub secs: i64,
pub nanos: u32,
}
impl Timestamp {
#[must_use]
pub fn from_secs(secs: i64) -> Self {
Self { secs, nanos: 0 }
}
}
#[derive(Debug)]
pub struct TemporalState<H> {
pub epoch: EpochTag,
pub ordering_key: Option<LsnKind>,
pub wall_time: Option<Timestamp>,
pub clock: ClockProvenance,
pub safety: MaterializationSafety,
pub handle: H,
}
#[derive(Debug)]
pub struct TemporalCohort<H> {
pub artifact: ArtifactRef,
pub discipline: IdentityDiscipline,
pub topology: CohortTopology,
pub states: Vec<TemporalState<H>>,
}
impl<H> TemporalCohort<H> {
#[must_use]
pub fn at(&self, t: Timestamp) -> Option<&TemporalState<H>> {
self.states
.iter()
.filter(|s| s.wall_time.is_some_and(|wt| wt <= t))
.max_by_key(|s| s.wall_time)
}
#[must_use]
pub fn nearest(&self, t: Timestamp) -> Option<&TemporalState<H>> {
self.states
.iter()
.filter(|s| s.wall_time.is_some())
.min_by_key(|s| {
let wt = s.wall_time.unwrap_or(t);
(wt.secs - t.secs).unsigned_abs()
})
}
pub fn epochs(&self) -> impl Iterator<Item = EpochTag> + '_ {
self.states.iter().map(|s| s.epoch)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Tombstone {
pub last_seen_epoch: EpochTag,
pub first_absent_epoch: EpochTag,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct IdentityDiscontinuity {
pub at_epoch: EpochTag,
pub discipline: IdentityDiscipline,
pub description: String,
}