aimdb_core/remote/
metadata.rs

1//! Record metadata types for remote introspection
2
3use core::any::TypeId;
4use serde::{Deserialize, Serialize};
5use std::string::String;
6
7/// Metadata about a registered record type
8///
9/// Provides information for remote introspection, including buffer
10/// configuration, producer/consumer counts, and timestamps.
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct RecordMetadata {
13    /// Record type name (Rust type name)
14    pub name: String,
15
16    /// TypeId as hexadecimal string
17    pub type_id: String,
18
19    /// Buffer type: "spmc_ring", "single_latest", "mailbox", or "none"
20    pub buffer_type: String,
21
22    /// Buffer capacity (None for unbounded or no buffer)
23    #[serde(skip_serializing_if = "Option::is_none")]
24    pub buffer_capacity: Option<usize>,
25
26    /// Number of registered producer services
27    pub producer_count: usize,
28
29    /// Number of registered consumer services
30    pub consumer_count: usize,
31
32    /// Whether write operations are permitted for this record
33    pub writable: bool,
34
35    /// When the record was registered (ISO 8601)
36    pub created_at: String,
37
38    /// Last update timestamp (ISO 8601), None if never updated
39    #[serde(skip_serializing_if = "Option::is_none")]
40    pub last_update: Option<String>,
41
42    /// Number of outbound connector links registered
43    pub outbound_connector_count: usize,
44}
45
46impl RecordMetadata {
47    /// Creates a new record metadata entry
48    ///
49    /// # Arguments
50    /// * `type_id` - The TypeId of the record
51    /// * `name` - The Rust type name
52    /// * `buffer_type` - Buffer type string
53    /// * `buffer_capacity` - Optional buffer capacity
54    /// * `producer_count` - Number of producers
55    /// * `consumer_count` - Number of consumers
56    /// * `writable` - Whether writes are permitted
57    /// * `created_at` - Creation timestamp (ISO 8601)
58    /// * `outbound_connector_count` - Number of outbound connectors
59    #[allow(clippy::too_many_arguments)]
60    pub fn new(
61        type_id: TypeId,
62        name: String,
63        buffer_type: String,
64        buffer_capacity: Option<usize>,
65        producer_count: usize,
66        consumer_count: usize,
67        writable: bool,
68        created_at: String,
69        outbound_connector_count: usize,
70    ) -> Self {
71        Self {
72            name,
73            type_id: format!("{:?}", type_id),
74            buffer_type,
75            buffer_capacity,
76            producer_count,
77            consumer_count,
78            writable,
79            created_at,
80            last_update: None,
81            outbound_connector_count,
82        }
83    }
84
85    /// Sets the last update timestamp
86    pub fn with_last_update(mut self, timestamp: String) -> Self {
87        self.last_update = Some(timestamp);
88        self
89    }
90
91    /// Sets the last update timestamp from an Option
92    pub fn with_last_update_opt(mut self, timestamp: Option<String>) -> Self {
93        self.last_update = timestamp;
94        self
95    }
96}
97
98#[cfg(test)]
99mod tests {
100    use super::*;
101
102    #[test]
103    fn test_record_metadata_creation() {
104        let type_id = TypeId::of::<i32>();
105        let metadata = RecordMetadata::new(
106            type_id,
107            "i32".to_string(),
108            "spmc_ring".to_string(),
109            Some(100),
110            1,
111            2,
112            false,
113            "2025-10-31T10:00:00.000Z".to_string(),
114            0,
115        );
116
117        assert_eq!(metadata.name, "i32");
118        assert_eq!(metadata.buffer_type, "spmc_ring");
119        assert_eq!(metadata.buffer_capacity, Some(100));
120        assert_eq!(metadata.producer_count, 1);
121        assert_eq!(metadata.consumer_count, 2);
122        assert_eq!(metadata.outbound_connector_count, 0);
123        assert!(!metadata.writable);
124    }
125
126    #[test]
127    fn test_record_metadata_serialization() {
128        let type_id = TypeId::of::<String>();
129        let metadata = RecordMetadata::new(
130            type_id,
131            "String".to_string(),
132            "single_latest".to_string(),
133            None,
134            1,
135            1,
136            true,
137            "2025-10-31T10:00:00.000Z".to_string(),
138            2,
139        )
140        .with_last_update("2025-10-31T12:00:00.000Z".to_string());
141
142        let json = serde_json::to_string(&metadata).unwrap();
143        assert!(json.contains("\"name\":\"String\""));
144        assert!(json.contains("\"buffer_type\":\"single_latest\""));
145        assert!(json.contains("\"writable\":true"));
146        assert!(json.contains("\"outbound_connector_count\":2"));
147    }
148}