saddle-runtime 0.3.30

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};

fn guarded_written(
    source: &ReservedRequestView,
    capture: Result<
        saddle_observability::root_diagnostic::WrittenRootFailure,
        saddle_observability::root_diagnostic::RootRequestFailure,
    >,
) -> Result<WrittenReservedFailure, ReservedRequestFailure> {
    capture
        .map(|written| {
            WrittenReservedFailure(ReservedRequestFailure {
                failure: written.into_source(),
                source: source.clone(),
            })
        })
        .map_err(|failure| ReservedRequestFailure {
            failure,
            source: source.clone(),
        })
}

/// 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_borrowed_error_with_facts_written<E: std::error::Error>(
        &self,
        error: &E,
        facts: BoundedDiagnostic,
        classification: DiagnosticCode,
        output: Option<&EmergencyDiagnosticHandle>,
        event: RootRequestEvent,
        outcome: RootOutcomeFacts,
    ) -> Result<WrittenReservedFailure, ReservedRequestFailure> {
        guarded_written(
            self,
            RootDiagnosticScope::new(&self.0.view, output)
                .source_borrowed_error_with_facts_written(
                    error, facts, classification, event, outcome,
                ),
        )
    }

    pub fn source_error_with_facts_written(
        &self,
        error: &(dyn std::error::Error + 'static),
        facts: BoundedDiagnostic,
        classification: DiagnosticCode,
        output: Option<&EmergencyDiagnosticHandle>,
        event: RootRequestEvent,
        outcome: RootOutcomeFacts,
    ) -> Result<WrittenReservedFailure, ReservedRequestFailure> {
        guarded_written(
            self,
            RootDiagnosticScope::new(&self.0.view, output).source_error_with_facts_written(
                error,
                facts,
                classification,
                event,
                outcome,
            ),
        )
    }
    pub fn source_description_written<D: std::fmt::Display + std::fmt::Debug>(
        &self,
        description: &D,
        facts: BoundedDiagnostic,
        classification: DiagnosticCode,
        output: Option<&EmergencyDiagnosticHandle>,
        event: RootRequestEvent,
        outcome: RootOutcomeFacts,
    ) -> Result<WrittenReservedFailure, ReservedRequestFailure> {
        guarded_written(
            self,
            RootDiagnosticScope::new(&self.0.view, output).source_description_written(
                description,
                facts,
                classification,
                event,
                outcome,
            ),
        )
    }
    pub fn source_remote_protocol_written<D: std::fmt::Display + std::fmt::Debug>(
        &self,
        description: &D,
        facts: BoundedDiagnostic,
        classification: DiagnosticCode,
        output: Option<&EmergencyDiagnosticHandle>,
        event: RootRequestEvent,
        outcome: RootOutcomeFacts,
        protocol: saddle_observability::root_diagnostic::RemoteProtocolContext<'_>,
    ) -> Result<WrittenReservedFailure, ReservedRequestFailure> {
        guarded_written(
            self,
            RootDiagnosticScope::new(&self.0.view, output).source_remote_protocol_written(
                description, facts, classification, event, outcome, protocol,
            ),
        )
    }
    pub fn source_grpc_error_written<E: std::error::Error>(
        &self,error:&E,facts:BoundedDiagnostic,classification:DiagnosticCode,
        output:Option<&EmergencyDiagnosticHandle>,event:RootRequestEvent,outcome:RootOutcomeFacts,
        target:saddle_observability::root_diagnostic::GrpcTargetContext<'_>,
    )->Result<WrittenReservedFailure,ReservedRequestFailure>{
        guarded_written(self,RootDiagnosticScope::new(&self.0.view,output).source_grpc_error_written(error,facts,classification,event,outcome,target))
    }
    pub fn source_remote_error_written(
        &self,
        error: &(dyn std::error::Error + 'static),
        facts: BoundedDiagnostic,
        classification: DiagnosticCode,
        output: Option<&EmergencyDiagnosticHandle>,
        event: RootRequestEvent,
        outcome: RootOutcomeFacts,
        target: saddle_observability::root_diagnostic::RemoteTargetContext<'_>,
    ) -> Result<WrittenReservedFailure, ReservedRequestFailure> {
        guarded_written(
            self,
            RootDiagnosticScope::new(&self.0.view, output).source_remote_error_written(
                error, facts, classification, event, outcome, target,
            ),
        )
    }
    pub fn source_existing_error_written(
        &self,
        error: &(dyn std::error::Error + 'static),
        facts: Diagnostic,
        classification: DiagnosticCode,
        output: Option<&EmergencyDiagnosticHandle>,
        event: RootRequestEvent,
        outcome: RootOutcomeFacts,
    ) -> Result<WrittenReservedFailure, ReservedRequestFailure> {
        guarded_written(
            self,
            RootDiagnosticScope::new(&self.0.view, output).source_existing_error_written(
                error,
                facts,
                classification,
                event,
                outcome,
            ),
        )
    }
    pub fn source_existing_description_written<D: std::fmt::Display + std::fmt::Debug>(
        &self,
        description: &D,
        facts: Diagnostic,
        classification: DiagnosticCode,
        output: Option<&EmergencyDiagnosticHandle>,
        event: RootRequestEvent,
        outcome: RootOutcomeFacts,
    ) -> Result<WrittenReservedFailure, ReservedRequestFailure> {
        guarded_written(
            self,
            RootDiagnosticScope::new(&self.0.view, output).source_existing_description_written(
                description,
                facts,
                classification,
                event,
                outcome,
            ),
        )
    }
    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 },
            )),
        }
    }
}