liminal-server 0.23.1

Standalone server for the liminal messaging bus
Documentation
use super::ParticipantSemanticHandler;
use super::{
    ConnectionFateClass, ConnectionIncarnation, ConnectionRuntime, ParticipantServiceFatal,
    ServerError,
};

impl ConnectionRuntime {
    pub(super) fn participant_service_fatal(
        &self,
    ) -> Result<Option<ParticipantServiceFatal>, ServerError> {
        let Some(service) = self.participant_service() else {
            return Ok(None);
        };
        service
            .service_fatal()
            .map_err(|error| ServerError::ParticipantIncarnation {
                phase: "participant fatal latch inspection",
                message: error.to_string(),
            })
    }

    fn activate_fatal_shutdown(&self) {
        if let Some(shutdown) = self.fatal_shutdown.as_ref() {
            shutdown.initiate();
        }
    }

    pub(super) fn ensure_participant_service_live(&self) -> Result<(), ServerError> {
        let Some(fatal) = self.participant_service_fatal()? else {
            return Ok(());
        };
        self.activate_fatal_shutdown();
        Err(ServerError::ParticipantServiceFatal { fatal })
    }

    fn latch_connection_fate_intent_incomplete(
        &self,
        open_sequence: u64,
        conversation_id: u64,
    ) -> Result<ParticipantServiceFatal, ServerError> {
        let Some(service) = self.participant_service() else {
            return Err(ServerError::ParticipantIncarnation {
                phase: "connection-fate fatal latch",
                message: "a durable Open lacks its installed participant service".to_owned(),
            });
        };
        let fatal = service
            .latch_connection_fate_intent_incomplete(open_sequence, conversation_id)
            .map_err(|error| ServerError::ParticipantIncarnation {
                phase: "connection-fate fatal latch",
                message: error.to_string(),
            })?;
        self.activate_fatal_shutdown();
        Ok(fatal)
    }

    pub(super) fn complete_connection_fate_fatal(
        &self,
        open_sequence: u64,
        conversations: &[u64],
        phase: &'static str,
        error: &impl std::fmt::Display,
    ) -> ServerError {
        tracing::error!(open_sequence, phase, %error, "durable connection-fate intent is incomplete");
        let Some(&conversation_id) = conversations.first() else {
            return ServerError::ParticipantIncarnation {
                phase: "connection-fate fatal target",
                message: "a durable Open has no tracked conversation target".to_owned(),
            };
        };
        match self.latch_connection_fate_intent_incomplete(open_sequence, conversation_id) {
            Ok(fatal) => ServerError::ParticipantServiceFatal { fatal },
            Err(latch_error) => latch_error,
        }
    }

    /// Runs one typed terminal fold after classification and before teardown.
    pub(in crate::server::connection) fn complete_connection_fate(
        &self,
        connection_incarnation: Option<ConnectionIncarnation>,
        class: ConnectionFateClass,
        conversations: &[u64],
    ) -> Result<(), ServerError> {
        if conversations.is_empty() {
            return Ok(());
        }
        self.ensure_participant_service_live()?;
        let (Some(connection_incarnation), Some(_), Some(authority)) = (
            connection_incarnation,
            self.participant_service(),
            self.incarnations.as_ref(),
        ) else {
            return Err(ServerError::ParticipantIncarnation {
                phase: "connection-fate authority composition",
                message: "tracked participant conversations lack a complete service/incarnation authority"
                    .to_owned(),
            });
        };
        let intent =
            authority.open_connection_fate(connection_incarnation, class, conversations)?;
        self.fold_or_park_connection_fate(intent)
    }

    /// Resolves the bound-only protocol-error gate from participant authority.
    pub(in crate::server::connection) fn connection_has_bound_participant(
        &self,
        connection_incarnation: Option<ConnectionIncarnation>,
        conversations: &[u64],
    ) -> Result<bool, ServerError> {
        if conversations.is_empty() {
            return Ok(false);
        }
        self.ensure_participant_service_live()?;
        let (Some(connection_incarnation), Some(service)) =
            (connection_incarnation, self.participant_service())
        else {
            return Err(ServerError::ParticipantIncarnation {
                phase: "bound participant classification",
                message:
                    "tracked participant conversations lack a complete service/incarnation pair"
                        .to_owned(),
            });
        };
        service
            .connection_has_bound_participant(connection_incarnation, conversations)
            .map_err(|error| ServerError::ParticipantIncarnation {
                phase: "bound participant classification",
                message: error.to_string(),
            })
    }
}