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 {
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)
}