cf_system_sdk_directory/
api.rs1use anyhow::Result;
6use async_trait::async_trait;
7
8#[derive(Clone, Debug, PartialEq, Eq, Hash)]
10pub struct ServiceEndpoint {
11 pub uri: String,
12}
13
14impl ServiceEndpoint {
15 pub fn new(uri: impl Into<String>) -> Self {
16 Self { uri: uri.into() }
17 }
18
19 #[must_use]
20 pub fn http(host: &str, port: u16) -> Self {
21 Self {
22 uri: format!("{}://{}:{}", "http", host, port),
23 }
24 }
25
26 #[must_use]
27 pub fn https(host: &str, port: u16) -> Self {
28 Self {
29 uri: format!("https://{host}:{port}"),
30 }
31 }
32
33 pub fn uds(path: impl AsRef<std::path::Path>) -> Self {
34 Self {
35 uri: format!("unix://{}", path.as_ref().display()),
36 }
37 }
38}
39
40#[derive(Debug, Clone)]
42pub struct ServiceInstanceInfo {
43 pub module: String,
45 pub instance_id: String,
47 pub endpoint: ServiceEndpoint,
49 pub version: Option<String>,
51}
52
53#[derive(Debug, Clone)]
55pub struct RegisterInstanceInfo {
56 pub module: String,
58 pub instance_id: String,
60 pub grpc_services: Vec<(String, ServiceEndpoint)>,
62 pub version: Option<String>,
64}
65
66#[async_trait]
73pub trait DirectoryClient: Send + Sync {
74 async fn resolve_grpc_service(&self, service_name: &str) -> Result<ServiceEndpoint>;
76
77 async fn list_instances(&self, module: &str) -> Result<Vec<ServiceInstanceInfo>>;
79
80 async fn register_instance(&self, info: RegisterInstanceInfo) -> Result<()>;
82
83 async fn deregister_instance(&self, module: &str, instance_id: &str) -> Result<()>;
85
86 async fn send_heartbeat(&self, module: &str, instance_id: &str) -> Result<()>;
88}
89
90#[cfg(test)]
91#[cfg_attr(coverage_nightly, coverage(off))]
92mod tests {
93 use super::*;
94
95 #[test]
96 fn test_service_endpoint_creation() {
97 let http_ep = ServiceEndpoint::http("localhost", 8080);
98 assert_eq!(http_ep.uri, concat!("http", "://localhost:8080"));
99
100 let https_endpoint = ServiceEndpoint::https("localhost", 8443);
101 assert_eq!(https_endpoint.uri, "https://localhost:8443");
102
103 let uds_ep = ServiceEndpoint::uds("/tmp/socket.sock");
104 assert!(uds_ep.uri.starts_with("unix://"));
105 assert!(uds_ep.uri.contains("socket.sock"));
106
107 let custom_ep = ServiceEndpoint::new(concat!("http", "://example.com"));
108 assert_eq!(custom_ep.uri, concat!("http", "://example.com"));
109 }
110
111 #[test]
112 fn test_register_instance_info() {
113 let info = RegisterInstanceInfo {
114 module: "test_module".to_owned(),
115 instance_id: "instance1".to_owned(),
116 grpc_services: vec![(
117 "test.Service".to_owned(),
118 ServiceEndpoint::http("127.0.0.1", 8001),
119 )],
120 version: Some("1.0.0".to_owned()),
121 };
122
123 assert_eq!(info.module, "test_module");
124 assert_eq!(info.instance_id, "instance1");
125 assert_eq!(info.grpc_services.len(), 1);
126 }
127}