liminal-server 0.25.4

Standalone server for the liminal messaging bus
Documentation
use std::fs;
use std::net::SocketAddr;
use std::path::PathBuf;
use std::sync::atomic::{AtomicU64, Ordering};

use crate::ServerError;

use super::validate;
use crate::config::types::{
    AuthConfig, ChannelDef, ClusterConfig, LimitsConfig, ParticipantConfig, RoutingRuleDef,
    ServerConfig, ServicesConfig,
};

static NEXT_TEMP_DIR_ID: AtomicU64 = AtomicU64::new(0);

fn socket(address: &str) -> Result<SocketAddr, Box<dyn std::error::Error>> {
    Ok(address.parse()?)
}

fn sample_config() -> Result<ServerConfig, Box<dyn std::error::Error>> {
    Ok(ServerConfig {
        listen_address: socket("127.0.0.1:8080")?,
        extra_listen_addresses: Vec::new(),
        health_listen_address: socket("127.0.0.1:8081")?,
        drain_timeout_ms: 30_000,
        channels: vec![ChannelDef {
            name: "orders".to_owned(),
            schema_ref: None,
            durable: true,
            loaded_schema: None,
        }],
        routing_rules: vec![RoutingRuleDef {
            source_channel: "orders".to_owned(),
            target_channel: "orders".to_owned(),
            predicate: None,
        }],
        persistence_path: Some(PathBuf::from(env!("CARGO_MANIFEST_DIR"))),
        cluster: Some(ClusterConfig {
            node_name: "node-a".to_owned(),
            listen_address: socket("127.0.0.1:9000")?,
            seed_nodes: vec![socket("127.0.0.1:9001")?],
            cookie: "test-cookie".to_owned(),
        }),
        auth: None,
        services: ServicesConfig::default(),
        limits: LimitsConfig::default(),
        participant: None,
        websocket: None,
    })
}

/// A worker-front-door config: no channels, routing, persistence, or cluster —
/// the shape the front-door profile requires.
fn worker_front_door_config() -> Result<ServerConfig, Box<dyn std::error::Error>> {
    Ok(ServerConfig {
        channels: Vec::new(),
        routing_rules: Vec::new(),
        persistence_path: None,
        cluster: None,
        services: ServicesConfig {
            profile: "worker-front-door".to_owned(),
            ..ServicesConfig::default()
        },
        ..sample_config()?
    })
}

fn unique_temp_dir(label: &str) -> PathBuf {
    let id = NEXT_TEMP_DIR_ID.fetch_add(1, Ordering::Relaxed);
    std::env::temp_dir().join(format!(
        "liminal-server-validation-{label}-{}-{id}",
        std::process::id()
    ))
}

fn config_validation_message(result: Result<(), ServerError>) -> String {
    let Err(ServerError::ConfigValidation { message }) = result else {
        return String::new();
    };
    message
}

mod authentication;
mod channels;
mod limits;
mod open_mode;
mod schemas;
mod websocket;