grafos_mq/
locator.rs

1//! TopicLocator for cross-application topic discovery via grafos-locator.
2
3extern crate alloc;
4use alloc::string::String;
5use alloc::vec::Vec;
6
7use serde::{Deserialize, Serialize};
8
9/// A locator describing a topic's partition layout for cross-application discovery.
10#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
11pub struct TopicLocator {
12    /// Schema version for this locator type.
13    pub version: u8,
14    /// Pool name.
15    pub pool: String,
16    /// Topic name.
17    pub topic: String,
18    /// Number of partitions.
19    pub num_partitions: u32,
20    /// Partition stride (slot size in bytes).
21    pub partition_stride: u32,
22    /// Partition capacity (number of slots per partition).
23    pub partition_capacity: u32,
24    /// Lease IDs for each partition's backing memory.
25    pub partition_lease_ids: Vec<u128>,
26}
27
28impl TopicLocator {
29    /// Create a new v1 topic locator.
30    pub fn new(
31        pool: &str,
32        topic: &str,
33        num_partitions: u32,
34        partition_stride: u32,
35        partition_capacity: u32,
36    ) -> Self {
37        TopicLocator {
38            version: 1,
39            pool: String::from(pool),
40            topic: String::from(topic),
41            num_partitions,
42            partition_stride,
43            partition_capacity,
44            partition_lease_ids: Vec::new(),
45        }
46    }
47
48    /// Set the lease IDs for each partition.
49    pub fn with_lease_ids(mut self, ids: Vec<u128>) -> Self {
50        self.partition_lease_ids = ids;
51        self
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58
59    #[test]
60    fn roundtrip() {
61        let loc = TopicLocator::new("prod", "events", 4, 512, 64)
62            .with_lease_ids(alloc::vec![0xA, 0xB, 0xC, 0xD]);
63        let bytes = postcard::to_allocvec(&loc).expect("serialize");
64        let decoded: TopicLocator = postcard::from_bytes(&bytes).expect("deserialize");
65        assert_eq!(loc, decoded);
66        assert_eq!(decoded.version, 1);
67        assert_eq!(decoded.partition_lease_ids.len(), 4);
68    }
69
70    #[test]
71    fn empty_lease_ids() {
72        let loc = TopicLocator::new("dev", "test", 2, 256, 32);
73        assert!(loc.partition_lease_ids.is_empty());
74        let bytes = postcard::to_allocvec(&loc).expect("serialize");
75        let decoded: TopicLocator = postcard::from_bytes(&bytes).expect("deserialize");
76        assert_eq!(loc, decoded);
77    }
78}