Skip to main content

nodedb_types/
lsn.rs

1// SPDX-License-Identifier: Apache-2.0
2
3//! Log Sequence Number — monotonically increasing identifier for WAL records.
4//!
5//! LSNs are the universal ordering primitive across both Origin and Lite.
6//! On Origin: WAL record ordering. On Lite: sync watermark tracking.
7
8use std::fmt;
9
10use serde::{Deserialize, Serialize};
11
12/// Log Sequence Number.
13///
14/// On Origin: anchors every write, snapshot, and consistency check.
15/// On Lite: tracks sync progress (last-seen LSN from Origin).
16#[derive(
17    Debug,
18    Clone,
19    Copy,
20    PartialEq,
21    Eq,
22    PartialOrd,
23    Ord,
24    Hash,
25    Serialize,
26    Deserialize,
27    rkyv::Archive,
28    rkyv::Serialize,
29    rkyv::Deserialize,
30    zerompk::ToMessagePack,
31    zerompk::FromMessagePack,
32)]
33pub struct Lsn(u64);
34
35impl Lsn {
36    pub const ZERO: Lsn = Lsn(0);
37
38    pub const fn new(value: u64) -> Self {
39        Self(value)
40    }
41
42    pub const fn as_u64(self) -> u64 {
43        self.0
44    }
45
46    /// Returns the next LSN (self + 1).
47    pub const fn next(self) -> Self {
48        Self(self.0 + 1)
49    }
50
51    /// Returns true if this LSN is ahead of `other`.
52    pub const fn is_ahead_of(self, other: Self) -> bool {
53        self.0 > other.0
54    }
55}
56
57impl fmt::Display for Lsn {
58    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59        write!(f, "lsn:{}", self.0)
60    }
61}
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66
67    #[test]
68    fn lsn_ordering() {
69        let a = Lsn::new(1);
70        let b = Lsn::new(2);
71        assert!(a < b);
72        assert_eq!(a.next(), b);
73        assert!(b.is_ahead_of(a));
74        assert!(!a.is_ahead_of(b));
75    }
76
77    #[test]
78    fn lsn_display() {
79        assert_eq!(Lsn::new(42).to_string(), "lsn:42");
80    }
81
82    #[test]
83    fn lsn_zero() {
84        assert_eq!(Lsn::ZERO.as_u64(), 0);
85    }
86}