Skip to main content

FrameworkRequestFailure

Struct FrameworkRequestFailure 

Source
pub struct FrameworkRequestFailure<E, D = BoundedDiagnostic> { /* private fields */ }
Expand description

Only the actual context-bound source submission above constructs this value. No Clone, Default, From, raw identity constructor, or context replacement.

use saddle_observability::FrameworkRequestFailure;
fn naked() -> Result<(), FrameworkRequestFailure<u32>> { Err(17) }
use saddle_observability::FrameworkRequestFailure;
fn bypass() -> Result<(), FrameworkRequestFailure<u32>> {
    let value: Result<(), u32> = Err(17);
    value?;
    Ok(())
}
use saddle_observability::FrameworkRequestFailure;
fn forged(source: FrameworkRequestFailure<u32>) -> FrameworkRequestFailure<u32> {
    FrameworkRequestFailure { error: 17, ..source }
}

Implementations§

Source§

impl<E, D> FrameworkRequestFailure<E, D>

Source

pub fn error(&self) -> &E

Examples found in repository?
examples/early_request_diagnostic.rs (line 50)
32fn main() {
33    // Caller is at the accepted socket phase; no trace, span, request or task is
34    // fabricated to satisfy a constructor. The output may genuinely be absent.
35    let scope =
36        RequestDiagnosticScope::early(None, EarlyRequestContext::socket_accepted("example"))
37            .with_phase(DiagnosticRequestPhase::ReadingHead);
38    let failure = match read_head(&mut io::empty(), &scope) {
39        Err(failure) => failure,
40        Ok(()) => panic!("owned empty reader must fail"),
41    };
42    let id = failure.source_diagnostic().id();
43    let (retained, delivery) = failure.finish_boundary_retained(
44        None,
45        &DiagnosticOutcomeAxes {
46            operation: OperationOutcome::Failed,
47            ..Default::default()
48        },
49    );
50    assert_eq!(retained.error().kind(), io::ErrorKind::UnexpectedEof);
51    assert_eq!(retained.source_diagnostic().id(), id);
52    assert_eq!(
53        delivery.source_submission(),
54        DiagnosticSubmission::OutputUnavailable
55    );
56    assert_eq!(
57        delivery.boundary_submission(),
58        DiagnosticSubmission::OutputUnavailable
59    );
60    // Real consumer keeps `retained` in its task/response result, not just bool.
61    println!("GO: early source retained without invented identities or output");
62}
More examples
Hide additional examples
examples/outbound_child_diagnostic.rs (line 72)
12fn main() {
13    let observer = Observer::with_writer(ObserverConfig::default(), std::io::sink()).unwrap();
14    let (incoming, _) = observer
15        .start_external_call_with_rpc(
16            "shop",
17            "ingress",
18            "orders",
19            "query",
20            Some("gateway-opaque"),
21            RpcCorrelationId::new("0.3").unwrap(),
22        )
23        .unwrap();
24    let ingress_event = EventContext::new(
25        RequestIdentity::new("request-7").unwrap(),
26        RouteIdentity::new("/incoming").unwrap(),
27        1,
28    )
29    .unwrap();
30    let parent = RequestDiagnosticScope::output_unavailable(incoming.context(), &ingress_event)
31        .with_task(DiagnosticTaskId::from_runtime_id("42").unwrap())
32        .unwrap_or_else(|_| panic!("task"))
33        .with_zone(DiagnosticZone::from_validated_ingress("zone-a").unwrap());
34
35    // programming.rs generates the wire child; Boundary uses its trace/rpc plus
36    // request_id/function. The adapter below does NOT generate these identities.
37    let wire_trace = "gateway-opaque";
38    let wire_rpc = "0.3.1";
39    let request_id = "request-7";
40    let function = "remote.query";
41    let (root, _) = observer
42        .start_external_call_with_rpc(
43            "saddle",
44            "zone-a",
45            "profusecontract",
46            "invoke",
47            Some(wire_trace),
48            RpcCorrelationId::new(wire_rpc).unwrap(),
49        )
50        .unwrap();
51    let event = EventContext::new(
52        RequestIdentity::new(request_id).unwrap(),
53        RouteIdentity::new(function).unwrap(),
54        1,
55    )
56    .unwrap();
57    let child = parent
58        .derive_outbound_child(root.context(), &event)
59        .unwrap();
60    let failure = child.fail(
61        std::io::ErrorKind::ConnectionRefused,
62        DiagnosticCategory::UnexpectedError,
63        BoundedDiagnosticCause::new(
64            DiagnosticStage::RequestDecode,
65            DiagnosticCode::new("outbound.connect_failed").unwrap(),
66        ),
67    );
68    let id = failure.source_diagnostic().id();
69    let (retained, delivery) =
70        failure.finish_boundary_retained(None, &DiagnosticOutcomeAxes::default());
71    assert_eq!(retained.source_diagnostic().id(), id);
72    assert_eq!(*retained.error(), std::io::ErrorKind::ConnectionRefused);
73    assert_eq!(
74        delivery.source_submission(),
75        DiagnosticSubmission::OutputUnavailable
76    );
77    assert_eq!(
78        delivery.boundary_submission(),
79        DiagnosticSubmission::OutputUnavailable
80    );
81    println!("GO: Boundary-shaped child Call/Event consumed; absent output retains same failure");
82}
Source

pub fn submission(&self) -> DiagnosticSubmission

Source

pub fn map_error<F>( self, map: impl FnOnce(E) -> F, ) -> FrameworkRequestFailure<F, D>

Source

pub fn record_boundary( &self, output: &EmergencyDiagnosticHandle, axes: &DiagnosticOutcomeAxes, ) -> DiagnosticSubmission

Source

pub fn record_boundary_optional( &self, output: Option<&EmergencyDiagnosticHandle>, axes: &DiagnosticOutcomeAxes, ) -> DiagnosticSubmission

Source

pub fn finish_boundary_retained( self, output: Option<&EmergencyDiagnosticHandle>, axes: &DiagnosticOutcomeAxes, ) -> (Self, BoundaryDiagnosticDelivery)

Declared terminal observation without discarding the original error or diagnostic on missing/full/closed output. The returned SAME mandatory carrier must remain in the enclosing result until its actual terminal. This does not prove that arbitrary Rust drop/forget can be forbidden.

Examples found in repository?
examples/early_request_diagnostic.rs (lines 43-49)
32fn main() {
33    // Caller is at the accepted socket phase; no trace, span, request or task is
34    // fabricated to satisfy a constructor. The output may genuinely be absent.
35    let scope =
36        RequestDiagnosticScope::early(None, EarlyRequestContext::socket_accepted("example"))
37            .with_phase(DiagnosticRequestPhase::ReadingHead);
38    let failure = match read_head(&mut io::empty(), &scope) {
39        Err(failure) => failure,
40        Ok(()) => panic!("owned empty reader must fail"),
41    };
42    let id = failure.source_diagnostic().id();
43    let (retained, delivery) = failure.finish_boundary_retained(
44        None,
45        &DiagnosticOutcomeAxes {
46            operation: OperationOutcome::Failed,
47            ..Default::default()
48        },
49    );
50    assert_eq!(retained.error().kind(), io::ErrorKind::UnexpectedEof);
51    assert_eq!(retained.source_diagnostic().id(), id);
52    assert_eq!(
53        delivery.source_submission(),
54        DiagnosticSubmission::OutputUnavailable
55    );
56    assert_eq!(
57        delivery.boundary_submission(),
58        DiagnosticSubmission::OutputUnavailable
59    );
60    // Real consumer keeps `retained` in its task/response result, not just bool.
61    println!("GO: early source retained without invented identities or output");
62}
More examples
Hide additional examples
examples/outbound_child_diagnostic.rs (line 70)
12fn main() {
13    let observer = Observer::with_writer(ObserverConfig::default(), std::io::sink()).unwrap();
14    let (incoming, _) = observer
15        .start_external_call_with_rpc(
16            "shop",
17            "ingress",
18            "orders",
19            "query",
20            Some("gateway-opaque"),
21            RpcCorrelationId::new("0.3").unwrap(),
22        )
23        .unwrap();
24    let ingress_event = EventContext::new(
25        RequestIdentity::new("request-7").unwrap(),
26        RouteIdentity::new("/incoming").unwrap(),
27        1,
28    )
29    .unwrap();
30    let parent = RequestDiagnosticScope::output_unavailable(incoming.context(), &ingress_event)
31        .with_task(DiagnosticTaskId::from_runtime_id("42").unwrap())
32        .unwrap_or_else(|_| panic!("task"))
33        .with_zone(DiagnosticZone::from_validated_ingress("zone-a").unwrap());
34
35    // programming.rs generates the wire child; Boundary uses its trace/rpc plus
36    // request_id/function. The adapter below does NOT generate these identities.
37    let wire_trace = "gateway-opaque";
38    let wire_rpc = "0.3.1";
39    let request_id = "request-7";
40    let function = "remote.query";
41    let (root, _) = observer
42        .start_external_call_with_rpc(
43            "saddle",
44            "zone-a",
45            "profusecontract",
46            "invoke",
47            Some(wire_trace),
48            RpcCorrelationId::new(wire_rpc).unwrap(),
49        )
50        .unwrap();
51    let event = EventContext::new(
52        RequestIdentity::new(request_id).unwrap(),
53        RouteIdentity::new(function).unwrap(),
54        1,
55    )
56    .unwrap();
57    let child = parent
58        .derive_outbound_child(root.context(), &event)
59        .unwrap();
60    let failure = child.fail(
61        std::io::ErrorKind::ConnectionRefused,
62        DiagnosticCategory::UnexpectedError,
63        BoundedDiagnosticCause::new(
64            DiagnosticStage::RequestDecode,
65            DiagnosticCode::new("outbound.connect_failed").unwrap(),
66        ),
67    );
68    let id = failure.source_diagnostic().id();
69    let (retained, delivery) =
70        failure.finish_boundary_retained(None, &DiagnosticOutcomeAxes::default());
71    assert_eq!(retained.source_diagnostic().id(), id);
72    assert_eq!(*retained.error(), std::io::ErrorKind::ConnectionRefused);
73    assert_eq!(
74        delivery.source_submission(),
75        DiagnosticSubmission::OutputUnavailable
76    );
77    assert_eq!(
78        delivery.boundary_submission(),
79        DiagnosticSubmission::OutputUnavailable
80    );
81    println!("GO: Boundary-shaped child Call/Event consumed; absent output retains same failure");
82}
Source

pub fn source_diagnostic(&self) -> &D

Examples found in repository?
examples/early_request_diagnostic.rs (line 42)
32fn main() {
33    // Caller is at the accepted socket phase; no trace, span, request or task is
34    // fabricated to satisfy a constructor. The output may genuinely be absent.
35    let scope =
36        RequestDiagnosticScope::early(None, EarlyRequestContext::socket_accepted("example"))
37            .with_phase(DiagnosticRequestPhase::ReadingHead);
38    let failure = match read_head(&mut io::empty(), &scope) {
39        Err(failure) => failure,
40        Ok(()) => panic!("owned empty reader must fail"),
41    };
42    let id = failure.source_diagnostic().id();
43    let (retained, delivery) = failure.finish_boundary_retained(
44        None,
45        &DiagnosticOutcomeAxes {
46            operation: OperationOutcome::Failed,
47            ..Default::default()
48        },
49    );
50    assert_eq!(retained.error().kind(), io::ErrorKind::UnexpectedEof);
51    assert_eq!(retained.source_diagnostic().id(), id);
52    assert_eq!(
53        delivery.source_submission(),
54        DiagnosticSubmission::OutputUnavailable
55    );
56    assert_eq!(
57        delivery.boundary_submission(),
58        DiagnosticSubmission::OutputUnavailable
59    );
60    // Real consumer keeps `retained` in its task/response result, not just bool.
61    println!("GO: early source retained without invented identities or output");
62}
More examples
Hide additional examples
examples/outbound_child_diagnostic.rs (line 68)
12fn main() {
13    let observer = Observer::with_writer(ObserverConfig::default(), std::io::sink()).unwrap();
14    let (incoming, _) = observer
15        .start_external_call_with_rpc(
16            "shop",
17            "ingress",
18            "orders",
19            "query",
20            Some("gateway-opaque"),
21            RpcCorrelationId::new("0.3").unwrap(),
22        )
23        .unwrap();
24    let ingress_event = EventContext::new(
25        RequestIdentity::new("request-7").unwrap(),
26        RouteIdentity::new("/incoming").unwrap(),
27        1,
28    )
29    .unwrap();
30    let parent = RequestDiagnosticScope::output_unavailable(incoming.context(), &ingress_event)
31        .with_task(DiagnosticTaskId::from_runtime_id("42").unwrap())
32        .unwrap_or_else(|_| panic!("task"))
33        .with_zone(DiagnosticZone::from_validated_ingress("zone-a").unwrap());
34
35    // programming.rs generates the wire child; Boundary uses its trace/rpc plus
36    // request_id/function. The adapter below does NOT generate these identities.
37    let wire_trace = "gateway-opaque";
38    let wire_rpc = "0.3.1";
39    let request_id = "request-7";
40    let function = "remote.query";
41    let (root, _) = observer
42        .start_external_call_with_rpc(
43            "saddle",
44            "zone-a",
45            "profusecontract",
46            "invoke",
47            Some(wire_trace),
48            RpcCorrelationId::new(wire_rpc).unwrap(),
49        )
50        .unwrap();
51    let event = EventContext::new(
52        RequestIdentity::new(request_id).unwrap(),
53        RouteIdentity::new(function).unwrap(),
54        1,
55    )
56    .unwrap();
57    let child = parent
58        .derive_outbound_child(root.context(), &event)
59        .unwrap();
60    let failure = child.fail(
61        std::io::ErrorKind::ConnectionRefused,
62        DiagnosticCategory::UnexpectedError,
63        BoundedDiagnosticCause::new(
64            DiagnosticStage::RequestDecode,
65            DiagnosticCode::new("outbound.connect_failed").unwrap(),
66        ),
67    );
68    let id = failure.source_diagnostic().id();
69    let (retained, delivery) =
70        failure.finish_boundary_retained(None, &DiagnosticOutcomeAxes::default());
71    assert_eq!(retained.source_diagnostic().id(), id);
72    assert_eq!(*retained.error(), std::io::ErrorKind::ConnectionRefused);
73    assert_eq!(
74        delivery.source_submission(),
75        DiagnosticSubmission::OutputUnavailable
76    );
77    assert_eq!(
78        delivery.boundary_submission(),
79        DiagnosticSubmission::OutputUnavailable
80    );
81    println!("GO: Boundary-shaped child Call/Event consumed; absent output retains same failure");
82}
Source

pub fn finish_boundary( self, output: &EmergencyDiagnosticHandle, axes: &DiagnosticOutcomeAxes, ) -> (E, BoundaryDiagnosticDelivery)

Sole consuming release of the original error: records its boundary first. The enclosing component must use this only at its declared public boundary, not as an adapter back to a legacy internal technical-failure path.

Source§

impl<D> FrameworkRequestFailure<(), D>

Source

pub fn into_reference(self) -> RequestBoundaryReference<D>

Consume a capture receipt into its context-preserving boundary reference.

Auto Trait Implementations§

§

impl<E, D> Freeze for FrameworkRequestFailure<E, D>
where E: Freeze, D: Freeze,

§

impl<E, D> RefUnwindSafe for FrameworkRequestFailure<E, D>

§

impl<E, D> Send for FrameworkRequestFailure<E, D>
where E: Send, D: Send,

§

impl<E, D> Sync for FrameworkRequestFailure<E, D>
where E: Sync, D: Sync,

§

impl<E, D> Unpin for FrameworkRequestFailure<E, D>
where E: Unpin, D: Unpin,

§

impl<E, D> UnsafeUnpin for FrameworkRequestFailure<E, D>
where E: UnsafeUnpin, D: UnsafeUnpin,

§

impl<E, D> UnwindSafe for FrameworkRequestFailure<E, D>
where E: UnwindSafe, D: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.