Skip to main content

rskit_discovery/
instance.rs

1use std::collections::HashMap;
2
3use serde::{Deserialize, Serialize};
4
5/// A single instance of a service available for discovery.
6#[derive(Debug, Clone, Serialize, Deserialize)]
7pub struct ServiceInstance {
8    /// Unique instance identifier (e.g. UUID).
9    pub id: String,
10    /// Logical service name (e.g. `"payment-service"`).
11    pub name: String,
12    /// Host or IP address.
13    pub address: String,
14    /// Port the service is listening on.
15    pub port: u16,
16    /// Whether the instance is currently healthy.
17    pub healthy: bool,
18    /// Relative load-balancing weight. Zero is treated as one by weighted balancers.
19    #[serde(default = "default_weight")]
20    pub weight: u32,
21    /// Freeform tags for filtering (e.g. `["canary", "us-east-1"]`).
22    pub tags: Vec<String>,
23    /// Arbitrary key-value metadata.
24    pub metadata: HashMap<String, String>,
25}
26
27fn default_weight() -> u32 {
28    1
29}
30
31impl ServiceInstance {
32    /// Returns `"address:port"`.
33    pub fn endpoint(&self) -> String {
34        format!("{}:{}", self.address, self.port)
35    }
36}
37
38#[cfg(test)]
39mod tests {
40    use super::*;
41
42    #[test]
43    fn missing_weight_deserializes_to_default() {
44        let instance: ServiceInstance = serde_json::from_str(
45            r#"{
46                "id":"a",
47                "name":"svc",
48                "address":"127.0.0.1",
49                "port":8080,
50                "healthy":true,
51                "tags":[],
52                "metadata":{}
53            }"#,
54        )
55        .unwrap();
56
57        assert_eq!(instance.weight, 1);
58    }
59}