Skip to main content

request_root_contract/
request_root_contract.rs

1//! Compiled consumer contract, not production startup/admission wiring.
2use saddle_core::*;
3use saddle_observability::{
4    root_diagnostic::{request_child_view, request_identity_group},
5    *,
6};
7
8fn call(rpc: &str, span: u64, module: &str, service: &str, operation: &str) -> CallContext {
9    CallContext::new(
10        "saddle".into(),
11        module.into(),
12        service.into(),
13        operation.into(),
14        TraceId::from_u128(1),
15        SpanId::from_u64(span),
16    )
17    .with_trace_correlation_id(TraceCorrelationId::new("opaque-gateway-trace").unwrap())
18    .with_rpc_correlation_id(RpcCorrelationId::new(rpc))
19}
20
21// Runtime supplies the actual task number and original physical pair. Numeric
22// observation is not a permit; this function never mints a replacement pair.
23fn database_source(
24    view: &RequestExecutionView,
25    request: &DbPhysicalRequestHalf,
26    execution: &DbPhysicalExecutionHalf,
27    output: Option<&EmergencyDiagnosticHandle>,
28    original: &(dyn std::error::Error + 'static),
29) -> RootRequestFailure {
30    let checked = request
31        .project_diagnostic_context(execution, view.clone())
32        .ok()
33        .unwrap();
34    let db = view
35        .in_db_scope(&checked)
36        .unwrap()
37        .with_db_operation(RegisteredContextOperation::checked("mapping.checks.A").unwrap());
38    let diagnostic = BoundedDiagnostic::capture(
39        DiagnosticCategory::UnexpectedError,
40        CaptureSite::Origin,
41        BoundedDiagnosticCause::new(
42            DiagnosticStage::RequestDb,
43            DiagnosticCode::new("db.decode.type").unwrap(),
44        )
45        .with_column(Some(0), Some(2)),
46    );
47    RootDiagnosticScope::new(&db, output).source_error_with_facts(
48        original,
49        diagnostic,
50        DiagnosticCode::new("db.decode").unwrap(),
51        RootRequestEvent::Database,
52        RootOutcomeFacts {
53            axes: DiagnosticOutcomeAxes {
54                operation: OperationOutcome::Failed,
55                ..Default::default()
56            },
57            transaction: ContextFact::Present(RequestTransactionFact::Unknown),
58        },
59    )
60}
61
62fn main() {
63    // Storage contract exercise only. R0/A/R must reserve the exact layouts before
64    // this constructor is enabled in a real admitted or rejection path.
65    let mut publisher = RequestRootPublisher::create(
66        ContextLabel::checked("saddle").unwrap(),
67        ContextFact::NotEstablished,
68    )
69    .unwrap();
70    let root = publisher.reference();
71    let early = root.view(
72        RequestLocalFacts::new(RequestViewPhase::Reading).with_task(ContextFact::Present(17)),
73    );
74    let read_error = std::io::Error::from(std::io::ErrorKind::UnexpectedEof);
75    let early_failure = RootDiagnosticScope::new(&early, None).source_error(
76        &read_error,
77        DiagnosticStage::RequestDecode,
78        RootRequestEvent::Ingress,
79        RootOutcomeFacts::default(),
80    );
81    let event = EventContext::new(
82        RequestIdentity::new("request-a").unwrap(),
83        RouteIdentity::new("example.live").unwrap(),
84        1,
85    )
86    .unwrap();
87    assert!(
88        publisher
89            .publish(
90                request_identity_group(
91                    &call("0", 1, "entry", "app", "example.live"),
92                    &event,
93                    ContextFact::Present(ContextLabel::checked("local").unwrap())
94                )
95                .unwrap()
96            )
97            .is_ok()
98    );
99    let active = early
100        .refresh(&root)
101        .unwrap()
102        .with_phase(RequestViewPhase::Handler);
103    // Formal Boundary style: real child Call and event originate from its actual
104    // ProfuseContract request. Obs validates rather than inventing a child RPC.
105    let child_event = EventContext::new(
106        RequestIdentity::new("request-a").unwrap(),
107        RouteIdentity::new("receipt.invoke").unwrap(),
108        1,
109    )
110    .unwrap();
111    let child = request_child_view(
112        &active,
113        &call("0.1", 2, "local", "profusecontract", "invoke"),
114        &child_event,
115    )
116    .unwrap();
117    assert!(active.same_request(&child));
118    let (_, issuer) = DbPhysicalDispositionIssuer::issue().into_startup_and_request_issuer();
119    let (request, execution) = issuer.issue_request().unwrap();
120    // Real D passes &sqlx::Error here before driver_ref/business mapping. This
121    // standalone example uses the standard Error contract, with no DB dependency.
122    let raw_error = std::io::Error::new(
123        std::io::ErrorKind::PermissionDenied,
124        "original driver description",
125    );
126    let db_failure = database_source(&active, &request, &execution, None, &raw_error);
127    drop(raw_error);
128    let supervised = RootSupervisionReturn::<()>::failed(
129        db_failure.map_classification(DiagnosticCode::new("handler.failed").unwrap()),
130    );
131    let failure = supervised.consume().err().unwrap();
132    // Public projections contain no source body or root. Real Runtime must also
133    // finish the original physical pair, then drop all views before settlement.
134    let public = failure
135        .finish(&active, None, RootOutcomeFacts::default())
136        .ok()
137        .unwrap();
138    let early_public = early_failure
139        .finish(&active, None, RootOutcomeFacts::default())
140        .ok()
141        .unwrap();
142    let observer = Observer::with_writer(ObserverConfig::default(), std::io::sink()).unwrap();
143    let completed = RootDiagnosticScope::new(&active, None)
144        .start_stage(&observer, RootRequestEvent::Response)
145        .finish_nonfailure(RootOutcomeFacts {
146            axes: DiagnosticOutcomeAxes {
147                operation: OperationOutcome::Succeeded,
148                ..Default::default()
149            },
150            ..Default::default()
151        })
152        .ok()
153        .unwrap();
154    assert_eq!(completed, DiagnosticSubmission::OutputUnavailable);
155    assert_eq!(
156        RootDiagnosticScope::new(&active, None).ordinary(
157            &observer,
158            RootRequestEvent::Handler,
159            RootOutcomeFacts::default()
160        ),
161        DiagnosticSubmission::Enqueued
162    );
163    drop((publisher, root, early, active, child));
164    assert_eq!(
165        public.source_submission(),
166        DiagnosticSubmission::OutputUnavailable
167    );
168    assert_eq!(
169        early_public.terminal_submission(),
170        DiagnosticSubmission::OutputUnavailable
171    );
172    for (name, (payload, shared)) in ["root", "view", "child"]
173        .into_iter()
174        .zip(saddle_core::request_context::request_context_layouts())
175    {
176        println!(
177            "layout {name}: payload={} align={} arc_allocation={} arc_align={}",
178            payload.size(),
179            payload.align(),
180            shared.size(),
181            shared.align()
182        );
183    }
184    println!(
185        "layout receipt={} public={} root_ref={} view_ref={} identity_input={} bounded_detail={} borrowed_stage={}",
186        size_of::<RootRequestFailure>(),
187        size_of::<PublicRequestFailure>(),
188        size_of::<RequestRootRef>(),
189        size_of::<RequestExecutionView>(),
190        size_of::<RequestIdentityGroup>(),
191        size_of::<BoundedDiagnostic>(),
192        size_of::<RootActiveStage<'static>>()
193    );
194    println!("C consumer contract GO; production reservation/lifecycle NOT_RUN");
195    let layout = saddle_observability::root_diagnostic::request_logging_layouts();
196    let (stream, cycle, payload) = saddle_observability::root_diagnostic::original_capture_layout();
197    println!(
198        "layout original_stream={} align={} cycle_detector={} align={} payload_limit={} total_content_limit=none",
199        stream.size(),
200        stream.align(),
201        cycle.size(),
202        cycle.align(),
203        payload
204    );
205    println!(
206        "layout source_frame={} source_record={} emergency_packet={} emergency_slots={} ordinary_command={} ordinary_payload_max={}",
207        layout.source_frame.size(),
208        layout.source_record.size(),
209        layout.emergency_packet.size(),
210        layout.emergency_slots,
211        layout.ordinary_command.size(),
212        layout.ordinary_encoded_bytes_max
213    );
214}