tsoracle-core 0.2.4

Sync algorithm core for tsoracle: window allocator, 46/18-bit timestamp packing, monotonicity invariants, and the shared cluster peer type.
Documentation
//
//  ░▀█▀░█▀▀░█▀█░█▀▄░█▀█░█▀▀░█░░░█▀▀
//  ░░█░░▀▀█░█░█░█▀▄░█▀█░█░░░█░░░█▀▀
//  ░░▀░░▀▀▀░▀▀▀░▀░▀░▀░▀░▀▀▀░▀▀▀░▀▀▀
//
//  tsoracle — Distributed Timestamp Oracle
//  https://www.tsoracle.rs
//
//  Copyright (c) 2026 Prisma Risk
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      https://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

//! A consensus peer and the tsoracle service endpoint it advertises.

/// A known peer node and the network endpoint where its TSO service can be
/// reached for follower-redirect hints.
///
/// `node_id` is the consensus node identity (the OmniPaxos `NodeId`/pid or the
/// openraft `NodeId`). `endpoint` is the advertised tsoracle service address
/// surfaced via `LeaderState::Follower::leader_endpoint` when this peer is the
/// elected leader. This is the cross-backend shape consensus drivers share so
/// the `leader_endpoint` derivation reads the same regardless of the engine
/// underneath.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TsoPeer {
    pub node_id: u64,
    pub endpoint: String,
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn carries_node_id_and_endpoint() {
        let peer = TsoPeer {
            node_id: 2,
            endpoint: "http://node-2:50051".to_string(),
        };
        assert_eq!(peer.node_id, 2);
        assert_eq!(peer.endpoint, "http://node-2:50051");
    }

    #[test]
    fn equality_is_by_node_id_and_endpoint() {
        let left = TsoPeer {
            node_id: 1,
            endpoint: "http://a".to_string(),
        };
        let same = TsoPeer {
            node_id: 1,
            endpoint: "http://a".to_string(),
        };
        let different_endpoint = TsoPeer {
            node_id: 1,
            endpoint: "http://b".to_string(),
        };
        assert_eq!(left, same);
        assert_ne!(left, different_endpoint);
    }

    #[test]
    fn is_usable_as_a_hash_set_member() {
        use std::collections::HashSet;

        let mut peers = HashSet::new();
        peers.insert(TsoPeer {
            node_id: 1,
            endpoint: "http://a".to_string(),
        });
        let duplicate = peers.insert(TsoPeer {
            node_id: 1,
            endpoint: "http://a".to_string(),
        });
        assert!(!duplicate, "an equal peer must hash to the same bucket");
        assert_eq!(peers.len(), 1);
    }
}