Skip to main content

meerkat_runtime/handles/
session_admission.rs

1//! Runtime impl of [`meerkat_core::handles::SessionAdmissionHandle`].
2
3use std::sync::Arc;
4
5use meerkat_core::comms::InputSource;
6use meerkat_core::handles::{DslTransitionError, SessionAdmissionHandle};
7use meerkat_core::lifecycle::{InputId, RunId};
8
9use super::HandleDslAuthority;
10use crate::meerkat_machine::dsl as mm_dsl;
11
12/// Runtime-backed [`SessionAdmissionHandle`] impl.
13///
14/// Routes every trait method to the corresponding DSL input on a dedicated
15/// per-session MeerkatMachine DSL authority.
16#[derive(Debug)]
17pub struct RuntimeSessionAdmissionHandle {
18    dsl: Arc<HandleDslAuthority>,
19}
20
21impl RuntimeSessionAdmissionHandle {
22    /// Construct a handle backed by the session's shared DSL authority.
23    pub fn new(dsl: Arc<HandleDslAuthority>) -> Self {
24        Self { dsl }
25    }
26
27    /// Construct a handle backed by an ephemeral DSL authority.
28    ///
29    /// See [`RuntimeTurnStateHandle::ephemeral`].
30    pub fn ephemeral() -> Self {
31        Self::new(Arc::new(HandleDslAuthority::ephemeral()))
32    }
33}
34
35impl SessionAdmissionHandle for RuntimeSessionAdmissionHandle {
36    fn ingest(
37        &self,
38        runtime_id: &str,
39        work_id: &str,
40        origin: InputSource,
41    ) -> Result<(), DslTransitionError> {
42        // intra-machine: no route; dispatcher not applicable (handle targets the meerkat DSL directly, not a CompositionDispatcher seam)
43        self.dsl.apply_input(
44            mm_dsl::MeerkatMachineInput::Ingest {
45                runtime_id: mm_dsl::AgentRuntimeId::from(runtime_id.to_string()),
46                work_id: mm_dsl::WorkId::from(work_id.to_string()),
47                origin: mm_dsl::WorkOrigin::from(origin),
48            },
49            "SessionAdmissionHandle::ingest",
50        )
51    }
52
53    fn accept_with_completion(
54        &self,
55        input_id: &InputId,
56        request_immediate_processing: bool,
57        interrupt_yielding: bool,
58        wake_if_idle: bool,
59    ) -> Result<(), DslTransitionError> {
60        // intra-machine: no route; dispatcher not applicable (handle targets the meerkat DSL directly, not a CompositionDispatcher seam)
61        self.dsl.apply_input(
62            mm_dsl::MeerkatMachineInput::AcceptWithCompletion {
63                input_id: mm_dsl::InputId::from_domain(input_id),
64                request_immediate_processing,
65                interrupt_yielding,
66                wake_if_idle,
67            },
68            "SessionAdmissionHandle::accept_with_completion",
69        )
70    }
71
72    fn accept_without_wake(&self, input_id: &InputId) -> Result<(), DslTransitionError> {
73        // intra-machine: no route; dispatcher not applicable (handle targets the meerkat DSL directly, not a CompositionDispatcher seam)
74        self.dsl.apply_input(
75            mm_dsl::MeerkatMachineInput::AcceptWithoutWake {
76                input_id: mm_dsl::InputId::from_domain(input_id),
77            },
78            "SessionAdmissionHandle::accept_without_wake",
79        )
80    }
81
82    fn prepare(&self, run_id: &RunId) -> Result<(), DslTransitionError> {
83        // intra-machine: no route; dispatcher not applicable (handle targets the meerkat DSL directly, not a CompositionDispatcher seam)
84        self.dsl.apply_input(
85            mm_dsl::MeerkatMachineInput::Prepare {
86                session_id: mm_dsl::SessionId::default(),
87                run_id: mm_dsl::RunId::from_domain(run_id),
88            },
89            "SessionAdmissionHandle::prepare",
90        )
91    }
92
93    fn commit(&self, _input_id: &InputId, _run_id: &RunId) -> Result<(), DslTransitionError> {
94        // Runtime-backed commit terminalization is owned by
95        // MeerkatMachineCommand::Commit and its durable receipt path. The
96        // handle remains an observation-only compatibility hook.
97        Ok(())
98    }
99}
100
101#[cfg(test)]
102mod tests {
103    use super::*;
104    use uuid::Uuid;
105
106    #[test]
107    fn commit_effect_is_observation_only() {
108        let handle = RuntimeSessionAdmissionHandle::ephemeral();
109        handle
110            .commit(&InputId(Uuid::from_u128(1)), &RunId(Uuid::from_u128(2)))
111            .expect("runtime-backed admission commit is observation-only");
112    }
113}