grafos_registry/
registration.rs

1//! Service registration and health status types.
2
3extern crate alloc;
4use alloc::string::String;
5use alloc::vec::Vec;
6
7use serde::{Deserialize, Serialize};
8
9use crate::endpoint::ServiceEndpoint;
10
11/// Health status of a service instance.
12#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
13pub enum HealthStatus {
14    /// Instance is operating normally.
15    Healthy,
16    /// Instance is functional but impaired.
17    Degraded {
18        /// Human-readable reason for degradation.
19        reason: String,
20    },
21    /// Instance is shutting down and should not receive new work.
22    Draining,
23}
24
25/// A tag key-value pair attached to a service registration.
26#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
27pub struct Tag {
28    /// Tag key.
29    pub key: String,
30    /// Tag value.
31    pub value: String,
32}
33
34/// A single service registration in the registry.
35///
36/// Each registration identifies a unique instance of a named service with a
37/// version string, instance ID, endpoints, tags, health status, and a lease
38/// expiry timestamp (set by the registry on insertion).
39#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
40pub struct ServiceRegistration {
41    /// Service name (e.g. `"api-gateway"`).
42    pub name: String,
43    /// Semantic version string (e.g. `"2.1.0"`).
44    pub version: String,
45    /// Unique instance identifier.
46    pub instance_id: u128,
47    /// Reachable endpoints for this instance.
48    pub endpoints: Vec<ServiceEndpoint>,
49    /// Metadata tags for filtering.
50    pub tags: Vec<Tag>,
51    /// Current health status.
52    pub health: HealthStatus,
53    /// Unix timestamp (seconds) at which this registration expires.
54    /// Set by the registry on insertion; 0 means "not yet registered".
55    pub lease_expires_at: u64,
56}
57
58impl ServiceRegistration {
59    /// Create a new registration with the given name, version, and instance ID.
60    ///
61    /// Defaults to [`HealthStatus::Healthy`], no endpoints, no tags, and
62    /// `lease_expires_at = 0`.
63    pub fn new(name: &str, version: &str, instance_id: u128) -> Self {
64        ServiceRegistration {
65            name: String::from(name),
66            version: String::from(version),
67            instance_id,
68            endpoints: Vec::new(),
69            tags: Vec::new(),
70            health: HealthStatus::Healthy,
71            lease_expires_at: 0,
72        }
73    }
74
75    /// Add an endpoint to this registration (builder pattern).
76    pub fn with_endpoint(mut self, endpoint: ServiceEndpoint) -> Self {
77        self.endpoints.push(endpoint);
78        self
79    }
80
81    /// Add a tag to this registration (builder pattern).
82    pub fn with_tag(mut self, key: &str, value: &str) -> Self {
83        self.tags.push(Tag {
84            key: String::from(key),
85            value: String::from(value),
86        });
87        self
88    }
89
90    /// Check whether all required tags are present (AND semantics).
91    pub fn has_tags(&self, required: &[(String, String)]) -> bool {
92        required
93            .iter()
94            .all(|(rk, rv)| self.tags.iter().any(|t| t.key == *rk && t.value == *rv))
95    }
96
97    /// Check whether the version string starts with the given prefix.
98    pub fn version_matches_prefix(&self, prefix: &str) -> bool {
99        self.version.starts_with(prefix)
100    }
101}