Skip to main content

zlayer_types/api/
storage.rs

1//! Storage replication API DTOs.
2//!
3//! Wire types for the storage replication status endpoint. These are the
4//! response shapes consumed by both the daemon and SDK clients.
5
6use serde::{Deserialize, Serialize};
7use utoipa::ToSchema;
8
9/// Replication detail within the storage status response
10#[derive(Debug, Serialize, Deserialize, ToSchema)]
11pub struct ReplicationInfo {
12    /// Whether replication is configured
13    pub enabled: bool,
14    /// Current status: "active", "disabled", or "error"
15    pub status: String,
16    /// ISO-8601 timestamp of the last successful sync, or null
17    #[serde(skip_serializing_if = "Option::is_none")]
18    pub last_sync: Option<String>,
19    /// Number of WAL segments pending upload
20    pub pending_changes: usize,
21}
22
23/// Storage status response
24#[derive(Debug, Serialize, Deserialize, ToSchema)]
25pub struct StorageStatusResponse {
26    /// Replication status details
27    pub replication: ReplicationInfo,
28}
29
30#[cfg(test)]
31mod tests {
32    use super::*;
33
34    #[test]
35    fn test_replication_info_disabled_serialize() {
36        let info = ReplicationInfo {
37            enabled: false,
38            status: "disabled".to_string(),
39            last_sync: None,
40            pending_changes: 0,
41        };
42        let json = serde_json::to_string(&info).unwrap();
43        assert!(json.contains("\"enabled\":false"));
44        assert!(json.contains("\"disabled\""));
45        assert!(json.contains("\"pending_changes\":0"));
46        // last_sync should be omitted when None
47        assert!(!json.contains("last_sync"));
48    }
49
50    #[test]
51    fn test_replication_info_active_serialize() {
52        let info = ReplicationInfo {
53            enabled: true,
54            status: "active".to_string(),
55            last_sync: Some("2025-01-15T10:30:00+00:00".to_string()),
56            pending_changes: 3,
57        };
58        let json = serde_json::to_string(&info).unwrap();
59        assert!(json.contains("\"enabled\":true"));
60        assert!(json.contains("\"active\""));
61        assert!(json.contains("2025-01-15T10:30:00+00:00"));
62        assert!(json.contains("\"pending_changes\":3"));
63    }
64
65    #[test]
66    fn test_storage_status_response_serialize() {
67        let response = StorageStatusResponse {
68            replication: ReplicationInfo {
69                enabled: false,
70                status: "disabled".to_string(),
71                last_sync: None,
72                pending_changes: 0,
73            },
74        };
75        let json = serde_json::to_string(&response).unwrap();
76        assert!(json.contains("\"replication\""));
77        assert!(json.contains("\"enabled\":false"));
78    }
79}