Skip to main content

riffdb_types/
replication.rs

1//! Shared checked replication identities; constructing one grants no authority.
2
3use std::num::NonZeroU64;
4
5/// Nonzero lineage-shared leadership fence, distinct from a transaction position.
6/// Constructing a value never grants leadership or authorizes its persistence.
7#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
8pub struct LeadershipEpochV1(NonZeroU64);
9
10impl LeadershipEpochV1 {
11    /// Reconstructs a nonzero fence; zero is never an active leadership epoch.
12    #[must_use]
13    pub const fn new(value: u64) -> Option<Self> {
14        match NonZeroU64::new(value) {
15            Some(value) => Some(Self(value)),
16            None => None,
17        }
18    }
19
20    /// Initial leadership fence for receipted activation.
21    #[must_use]
22    pub const fn initial() -> Self {
23        Self(NonZeroU64::MIN)
24    }
25
26    /// Returns the exact nonzero position.
27    #[must_use]
28    pub const fn get(self) -> u64 {
29        self.0.get()
30    }
31
32    /// Preflights a promotion fence without mutation; exhaustion never wraps.
33    #[must_use]
34    pub const fn checked_next(self) -> Option<Self> {
35        match self.get().checked_add(1) {
36            Some(next) => Self::new(next),
37            None => None,
38        }
39    }
40}
41
42/// Opaque storage-local hold identity, never a NodeId or authority token.
43#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
44pub struct ReplicationSourceHoldIdV1([u8; 16]);
45
46impl ReplicationSourceHoldIdV1 {
47    /// Zero is unassigned. Constructing an ID grants no mutation capability.
48    #[must_use]
49    pub fn new(bytes: [u8; 16]) -> Option<Self> {
50        (bytes != [0; 16]).then_some(Self(bytes))
51    }
52
53    /// Canonical bytes for the storage owner's codec and key.
54    #[must_use]
55    pub const fn as_bytes(&self) -> &[u8; 16] {
56        &self.0
57    }
58}
59
60impl std::fmt::Debug for ReplicationSourceHoldIdV1 {
61    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62        f.write_str("ReplicationSourceHoldIdV1([redacted])")
63    }
64}
65
66/// A request-selected follower registration in one exact source lineage.
67/// This target grants no authority and contains no transport or credential data.
68#[derive(Clone, Copy, Eq, Hash, PartialEq)]
69pub struct ReplicationFollowerAuditTargetV1 {
70    database_id: crate::DatabaseId,
71    history_incarnation: NonZeroU64,
72    leadership_epoch: LeadershipEpochV1,
73    hold_id: ReplicationSourceHoldIdV1,
74}
75
76impl ReplicationFollowerAuditTargetV1 {
77    /// Checks the remaining nonzero lineage component before target construction.
78    #[must_use]
79    pub const fn new(
80        database_id: crate::DatabaseId,
81        history_incarnation: u64,
82        leadership_epoch: LeadershipEpochV1,
83        hold_id: ReplicationSourceHoldIdV1,
84    ) -> Option<Self> {
85        match NonZeroU64::new(history_incarnation) {
86            Some(history_incarnation) => Some(Self {
87                database_id,
88                history_incarnation,
89                leadership_epoch,
90                hold_id,
91            }),
92            None => None,
93        }
94    }
95
96    /// Exact source database identity.
97    #[must_use]
98    pub const fn database_id(self) -> crate::DatabaseId {
99        self.database_id
100    }
101    /// Nonzero source history incarnation.
102    #[must_use]
103    pub const fn history_incarnation(self) -> u64 {
104        self.history_incarnation.get()
105    }
106    /// Nonzero source leadership epoch.
107    #[must_use]
108    pub const fn leadership_epoch(self) -> LeadershipEpochV1 {
109        self.leadership_epoch
110    }
111    /// Opaque source-local registration identity.
112    #[must_use]
113    pub const fn hold_id(self) -> ReplicationSourceHoldIdV1 {
114        self.hold_id
115    }
116}
117
118impl std::fmt::Debug for ReplicationFollowerAuditTargetV1 {
119    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120        f.write_str("ReplicationFollowerAuditTargetV1([REDACTED])")
121    }
122}