use std::{path::Path, time::Duration};
use crate::configuration::load_bundle_configuration;
mod authorization;
mod client;
mod connection;
mod constants;
mod context;
mod contract;
mod delivery;
mod errors;
mod handlers;
mod identity;
mod lifecycle;
mod startup_state;
mod stream;
mod tmux;
use self::authorization::load_authorization_context;
pub use self::client::{RelayStreamSession, request_relay};
pub use self::connection::{BundleCatalog, serve_connection};
use self::constants::*;
use self::context::*;
pub use self::contract::*;
pub use self::delivery::AcpWorkerReadinessState;
pub use self::delivery::observability::{
PermissionQueueEvent, subscribe_acp_worker_state, subscribe_permission_queue_events,
};
use self::errors::*;
use self::identity::*;
pub fn handle_request(
request: RelayRequest,
configuration_root: &Path,
bundle_name: &str,
runtime_directory: &Path,
) -> Result<RelayResponse, RelayError> {
handle_request_with_principal(
request,
configuration_root,
bundle_name,
runtime_directory,
None,
)
}
fn handle_request_with_principal(
request: RelayRequest,
configuration_root: &Path,
bundle_name: &str,
runtime_directory: &Path,
principal: Option<RequestPrincipal>,
) -> Result<RelayResponse, RelayError> {
let bundle = load_bundle_configuration(configuration_root, bundle_name).map_err(map_config)?;
let authorization = load_authorization_context(configuration_root, &bundle)?;
handlers::handle_request(
request,
&bundle,
&authorization,
runtime_directory,
principal,
)
}
pub fn reconcile_bundle(
configuration_root: &Path,
bundle_name: &str,
tmux_socket: &Path,
) -> Result<ReconciliationReport, RelayError> {
lifecycle::reconcile_bundle(configuration_root, bundle_name, tmux_socket)
}
pub fn startup_bundle(
configuration_root: &Path,
bundle_name: &str,
runtime_directory: &Path,
) -> Result<BundleStartupReport, RelayError> {
lifecycle::startup_bundle(configuration_root, bundle_name, runtime_directory)
}
pub fn shutdown_bundle_runtime(tmux_socket: &Path) -> Result<ShutdownReport, RelayError> {
lifecycle::shutdown_bundle_runtime(tmux_socket)
}
pub fn load_startup_failures(
runtime_directory: &Path,
) -> Result<Vec<StartupFailureRecord>, String> {
startup_state::load_startup_failures(runtime_directory)
}
pub fn append_startup_failure(
runtime_directory: &Path,
record: StartupFailureRecord,
) -> Result<StartupFailureRecord, String> {
startup_state::append_startup_failure(runtime_directory, record)
}
#[must_use]
pub fn wait_for_async_delivery_shutdown(timeout: Duration) -> usize {
delivery::wait_for_async_delivery_shutdown(timeout)
}
#[must_use]
pub fn read_acp_worker_state(
bundle_name: &str,
runtime_directory: &Path,
target_session: &str,
) -> Option<&'static str> {
delivery::get_acp_worker_state(bundle_name, runtime_directory, target_session).map(|state| {
match state {
delivery::AcpWorkerReadinessState::Initializing => "initializing",
delivery::AcpWorkerReadinessState::Available => "available",
delivery::AcpWorkerReadinessState::Busy => "busy",
delivery::AcpWorkerReadinessState::Recovering => "recovering",
delivery::AcpWorkerReadinessState::Unavailable => "unavailable",
}
})
}
pub(in crate::relay) fn dispatch_request(
request: RelayRequest,
configuration_root: &Path,
bundle_name: &str,
runtime_directory: &Path,
principal: Option<RequestPrincipal>,
) -> RelayResponse {
match handle_request_with_principal(
request,
configuration_root,
bundle_name,
runtime_directory,
principal,
) {
Ok(value) => value,
Err(error) => RelayResponse::Error { error },
}
}