liminal-server 0.23.1

Standalone server for the liminal messaging bus
Documentation
//! Starts configured exporting bridges after the listeners bind and stops them before the store flush.
//! A refused dial leaves the named link down and is retried while the server keeps serving.

use crate::ServerError;
use crate::config::ServerConfig;
use crate::config::types::MachineConfig;
use crate::link::LinkHost;
use crate::link_bridge::BridgeRegistry;
use crate::server::connection::LysInstall;
use crate::server::connection::services::LiminalConnectionServices;
use std::sync::Arc;
#[path = "runtime_links/carriers.rs"]
mod carriers;
#[path = "runtime_links/retry.rs"]
mod retry;
use retry::RetryLinks;
#[cfg(feature = "test-support")]
#[path = "runtime_links/test_support.rs"]
pub mod test_support;

#[derive(Debug)]
struct Configuration {
    machine: MachineConfig,
    host: Arc<LinkHost>,
    services: Arc<LiminalConnectionServices>,
}

#[derive(Debug, Default)]
pub(in crate::server) struct ConfiguredLinks {
    configuration: Option<Configuration>,
    retry: Option<RetryLinks>,
}

pub(super) fn prepare(
    config: &ServerConfig,
    install: Option<&LysInstall>,
    services: &Arc<LiminalConnectionServices>,
) -> Result<ConfiguredLinks, ServerError> {
    let Some(machine) = config
        .auth
        .as_ref()
        .and_then(|auth| auth.lys.as_ref())
        .and_then(|lys| lys.machine.as_ref())
        .filter(|machine| {
            !machine.links.is_empty() || machine.carrier_choice.broker_echo.is_some()
        })
    else {
        return Ok(ConfiguredLinks::default());
    };
    let install =
        install.ok_or_else(|| refusal("configured outbound links have no installed Lys"))?;
    let Some(host) = install.link_host.as_ref() else {
        // The pass source names its boot refusal; serving does not require a link host.
        return Ok(ConfiguredLinks::default());
    };
    Ok(ConfiguredLinks {
        configuration: Some(Configuration {
            machine: machine.clone(),
            host: Arc::clone(host),
            services: Arc::clone(services),
        }),
        retry: None,
    })
}

impl ConfiguredLinks {
    pub(super) fn start(
        &mut self,
        registry: &BridgeRegistry,
        supervisor: &crate::server::ConnectionSupervisor,
    ) -> Result<(), ServerError> {
        let Some(configuration) = &self.configuration else {
            return Ok(());
        };
        self.retry = Some(RetryLinks::start(configuration, registry, supervisor)?);
        Ok(())
    }
    pub(super) fn finish(&mut self) -> Result<(), ServerError> {
        self.retry.take().map_or(Ok(()), |mut retry| retry.finish())
    }
}

fn refusal(message: impl Into<String>) -> ServerError {
    ServerError::ConfigValidation {
        message: message.into(),
    }
}

pub(super) fn lys(
    config: &ServerConfig,
) -> Result<(Option<tokio::runtime::Runtime>, Option<LysInstall>), ServerError> {
    let runtime = crate::server::connection::lys_ask_runtime(config.auth.as_ref())?;
    let install = super::lys_for(config, runtime.as_ref())?;
    Ok((runtime, install))
}

pub(in crate::server) fn shutdown(
    supervisor: &crate::server::ConnectionSupervisor,
    bound: std::time::Duration,
    stop_accepting: impl FnOnce() -> Result<(), ServerError>,
    publishers: (
        &mut ConfiguredLinks,
        impl FnOnce() -> Result<(), ServerError>,
    ),
) -> Result<(), ServerError> {
    let (links, finalize) = publishers;
    let links_shutdown = links.finish();
    let shutdown =
        crate::server::shutdown::sequence::run(supervisor, bound, stop_accepting, finalize);
    super::raise_in_precedence(links_shutdown, shutdown)
}