saddle-runtime 0.3.25

Saddle managed asynchronous runtime and lifecycle
Documentation
//! Guarded access to C's source and interval protocol. No new allocation.
#[cfg(test)]
mod tests;
use super::*;
use saddle_core::{BoundedDiagnostic, Diagnostic, DiagnosticCode};
use saddle_observability::root_diagnostic::RootActiveStage;
use saddle_observability::{DiagnosticSubmission, Observer};

/// Finalization is deliberately absent: final projection is not a second
/// completion of one of these intervals.
#[derive(Clone, Copy)]
pub enum ReservedObservationStage {
    Ingress,
    Admission,
    Handler,
    Database,
    Outbound,
    Response,
}
impl ReservedObservationStage {
    fn event(self) -> RootRequestEvent {
        match self {
            Self::Ingress => RootRequestEvent::Ingress,
            Self::Admission => RootRequestEvent::Admission,
            Self::Handler => RootRequestEvent::Handler,
            Self::Database => RootRequestEvent::Database,
            Self::Outbound => RootRequestEvent::Outbound,
            Self::Response => RootRequestEvent::Response,
        }
    }
}

impl ReservedRequestView {
    pub fn source_error_with_facts(
        &self,
        error: &(dyn std::error::Error + 'static),
        facts: BoundedDiagnostic,
        classification: DiagnosticCode,
        output: Option<&EmergencyDiagnosticHandle>,
        event: RootRequestEvent,
        outcome: RootOutcomeFacts,
    ) -> ReservedRequestFailure {
        ReservedRequestFailure {
            failure: RootDiagnosticScope::new(&self.0.view, output).source_error_with_facts(
                error,
                facts,
                classification,
                event,
                outcome,
            ),
            source: self.clone(),
        }
    }
    pub fn source_description<D: std::fmt::Display + std::fmt::Debug>(
        &self,
        description: &D,
        facts: BoundedDiagnostic,
        classification: DiagnosticCode,
        output: Option<&EmergencyDiagnosticHandle>,
        event: RootRequestEvent,
        outcome: RootOutcomeFacts,
    ) -> ReservedRequestFailure {
        ReservedRequestFailure {
            failure: RootDiagnosticScope::new(&self.0.view, output).source_description(
                description,
                facts,
                classification,
                event,
                outcome,
            ),
            source: self.clone(),
        }
    }
    pub fn source_existing_error(
        &self,
        error: &(dyn std::error::Error + 'static),
        facts: Diagnostic,
        classification: DiagnosticCode,
        output: Option<&EmergencyDiagnosticHandle>,
        event: RootRequestEvent,
        outcome: RootOutcomeFacts,
    ) -> ReservedRequestFailure {
        ReservedRequestFailure {
            failure: RootDiagnosticScope::new(&self.0.view, output).source_existing_error(
                error,
                facts,
                classification,
                event,
                outcome,
            ),
            source: self.clone(),
        }
    }
    pub fn source_existing_description<D: std::fmt::Display + std::fmt::Debug>(
        &self,
        description: &D,
        facts: Diagnostic,
        classification: DiagnosticCode,
        output: Option<&EmergencyDiagnosticHandle>,
        event: RootRequestEvent,
        outcome: RootOutcomeFacts,
    ) -> ReservedRequestFailure {
        ReservedRequestFailure {
            failure: RootDiagnosticScope::new(&self.0.view, output).source_existing_description(
                description,
                facts,
                classification,
                event,
                outcome,
            ),
            source: self.clone(),
        }
    }
    pub fn start_stage<'a>(
        &'a self,
        observer: &'a Observer,
        output: Option<&'a EmergencyDiagnosticHandle>,
        stage: ReservedObservationStage,
    ) -> ReservedActiveStage<'a> {
        ReservedActiveStage {
            inner: RootDiagnosticScope::new(&self.0.view, output)
                .start_stage(observer, stage.event()),
            guard: self,
        }
    }
}

/// Borrows the actual guarded view; neither raw Core view nor source receipt
/// can escape its permission. Stored inline in the consumer's measured future.
/// ```compile_fail
/// use saddle_runtime::request_task::reserved::*;
/// fn escape(view:ReservedRequestView,observer:&saddle_observability::Observer) -> ReservedActiveStage<'_> {
///     view.start_stage(observer,None,ReservedObservationStage::Database)
/// }
/// ```
/// ```compile_fail
/// use saddle_runtime::request_task::reserved::*;
/// fn replay(stage:ReservedActiveStage<'_>) {
///     let _=stage.finish_nonfailure(Default::default());
///     let _=stage.finish_nonfailure(Default::default());
/// }
/// ```
#[must_use = "finish this observation interval, or Drop records observation cancellation"]
pub struct ReservedActiveStage<'a> {
    inner: RootActiveStage<'a>,
    guard: &'a ReservedRequestView,
}
impl ReservedActiveStage<'_> {
    pub fn finish_failure_retained(
        self,
        failure: ReservedRequestFailure,
        facts: RootOutcomeFacts,
    ) -> Result<(ReservedRequestFailure, DiagnosticSubmission), (Self, ReservedRequestFailure)> {
        let Self { inner, guard } = self;
        let ReservedRequestFailure { failure, source } = failure;
        match inner.finish_failure_retained(failure, facts) {
            Ok((failure, submission)) => Ok((ReservedRequestFailure { failure, source }, submission)),
            Err((inner, failure)) => Err((Self { inner, guard }, ReservedRequestFailure { failure, source })),
        }
    }
    pub fn finish_failure_public(
        self,
        failure: ReservedRequestFailure,
        facts: RootOutcomeFacts,
    ) -> Result<
        saddle_observability::root_diagnostic::PublicRequestFailure,
        (Self, ReservedRequestFailure),
    > {
        let Self { inner, guard } = self;
        let ReservedRequestFailure { failure, source } = failure;
        inner
            .finish_failure_public(failure, facts)
            .map_err(|(inner, failure)| {
                (
                    Self { inner, guard },
                    ReservedRequestFailure { failure, source },
                )
            })
    }
    pub fn finish_nonfailure(self, facts: RootOutcomeFacts) -> Result<DiagnosticSubmission, Self> {
        let Self { inner, guard } = self;
        inner
            .finish_nonfailure(facts)
            .map_err(|inner| Self { inner, guard })
    }
    pub fn finish_failure(
        self,
        failure: ReservedRequestFailure,
        facts: RootOutcomeFacts,
    ) -> Result<(ReservedRequestFailure, DiagnosticSubmission), (Self, ReservedRequestFailure)>
    {
        let Self { inner, guard } = self;
        let ReservedRequestFailure { failure, source } = failure;
        match inner.finish_failure(failure, facts) {
            Ok((failure, submission)) => {
                Ok((ReservedRequestFailure { failure, source }, submission))
            }
            Err((inner, failure)) => Err((
                Self { inner, guard },
                ReservedRequestFailure { failure, source },
            )),
        }
    }
}