Skip to main content

liminal_server/config/
types.rs

1use std::net::SocketAddr;
2use std::path::PathBuf;
3use std::time::Duration;
4
5/// Declarative configuration for the standalone liminal server wrapper.
6#[derive(Debug, Clone, serde::Deserialize)]
7#[serde(deny_unknown_fields)]
8pub struct ServerConfig {
9    /// Socket address where the standalone server will listen for client traffic.
10    pub listen_address: SocketAddr,
11    /// Socket address where the health endpoint server will listen for probes.
12    pub health_listen_address: SocketAddr,
13    /// Maximum time to allow existing connections to drain during graceful shutdown.
14    pub drain_timeout_ms: u64,
15    /// Channel topology definitions declared by the operator.
16    pub channels: Vec<ChannelDef>,
17    /// Declarative routing rules that connect configured channels.
18    pub routing_rules: Vec<RoutingRuleDef>,
19    /// Optional filesystem location for durable server state.
20    pub persistence_path: Option<PathBuf>,
21    /// Optional beamr distribution cluster membership configuration.
22    pub cluster: Option<ClusterConfig>,
23}
24
25impl ServerConfig {
26    /// Returns the configured graceful-shutdown drain timeout.
27    #[must_use]
28    pub const fn drain_timeout(&self) -> Duration {
29        Duration::from_millis(self.drain_timeout_ms)
30    }
31}
32
33/// Declarative channel definition loaded from server configuration.
34#[derive(Debug, Clone, serde::Deserialize)]
35#[serde(deny_unknown_fields)]
36pub struct ChannelDef {
37    /// Unique channel name used by routing rules and operators.
38    pub name: String,
39    /// Schema reference used to validate messages for this channel.
40    pub schema_ref: String,
41    /// Whether this channel requires durable persistence.
42    pub durable: bool,
43}
44
45/// Declarative routing rule definition loaded from server configuration.
46#[derive(Debug, Clone, serde::Deserialize)]
47#[serde(deny_unknown_fields)]
48pub struct RoutingRuleDef {
49    /// Source channel name from which messages are routed.
50    pub source_channel: String,
51    /// Target channel name to which matching messages are routed.
52    pub target_channel: String,
53    /// Optional predicate expression that filters routed messages.
54    pub predicate: Option<String>,
55}
56
57/// Default beamr distribution handshake cookie, used when the operator does not
58/// configure one. Mirrors beamr's own [`beamr::distribution::DEFAULT_COOKIE`].
59pub const DEFAULT_COOKIE: &str = "beamr-cookie";
60
61/// Beamr distribution cluster configuration for standalone deployment.
62#[derive(Debug, Clone, serde::Deserialize)]
63#[serde(deny_unknown_fields)]
64pub struct ClusterConfig {
65    /// Unique node name advertised to the beamr distribution cluster.
66    pub node_name: String,
67    /// Socket address this node binds for inbound distribution links from peers.
68    ///
69    /// This is distinct from [`ServerConfig::listen_address`] (the client wire
70    /// port): a clustered node listens on two ports — one for clients, one for
71    /// peer distribution traffic.
72    pub listen_address: SocketAddr,
73    /// Seed node socket addresses used to join an existing cluster.
74    pub seed_nodes: Vec<SocketAddr>,
75    /// Shared distribution handshake cookie. Every node in a cluster MUST use the
76    /// same cookie or the OTP handshake is rejected. Defaults to
77    /// [`DEFAULT_COOKIE`] when omitted.
78    #[serde(default = "default_cookie")]
79    pub cookie: String,
80}
81
82fn default_cookie() -> String {
83    DEFAULT_COOKIE.to_owned()
84}