Skip to main content

middleware_core/stack/
mission_ops.rs

1use core_types::{ErrorCode, ErrorDomain, MissionId, RtError, SessionId, TransportDomain};
2use mission_core::message::{
3    MissionOpen, MissionPeerState, MissionReconcileSummary, MissionUpdate,
4};
5use mission_core::session::MissionSession;
6
7use crate::session::SessionManager;
8
9use super::MiddlewareStack;
10
11impl MiddlewareStack {
12    /// Open a new Mission session and register it with the middleware.
13    pub fn open_mission(
14        &mut self,
15        session_id: SessionId,
16        open: MissionOpen,
17    ) -> Result<MissionId, RtError> {
18        let mission_id = open.mission_id;
19        let mut session = mission_core::session::BasicMissionSession::new(mission_id);
20        session.open(open)?;
21        self.mission_sessions.insert(mission_id, session);
22        let _domain = self
23            .session_manager
24            .get_session(session_id)
25            .map(|r| r.domain)
26            .unwrap_or(TransportDomain::Local);
27        Ok(mission_id)
28    }
29
30    /// Mark a mission session as disconnected and transition the transport
31    /// session to the Reconnecting state.
32    pub fn mission_disconnect(&mut self, session_id: SessionId, reason: impl Into<String>) {
33        self.session_manager.mark_reconnecting(session_id, reason);
34    }
35
36    /// After a successful reconnect, perform state reconcile with the peer.
37    ///
38    /// This method:
39    /// 1. Marks the transport session as Connected again.
40    /// 2. Calls `reconcile(peer_state)` on the stored `BasicMissionSession`.
41    /// 3. Returns the `MissionReconcileSummary` so the caller can schedule replay.
42    pub fn mission_reconnect_reconcile(
43        &mut self,
44        session_id: SessionId,
45        mission_id: MissionId,
46        peer_state: MissionPeerState,
47    ) -> Result<MissionReconcileSummary, RtError> {
48        self.session_manager.mark_connected(session_id);
49        let session = self.mission_sessions.get_mut(&mission_id).ok_or_else(|| {
50            RtError::new(
51                ErrorCode::NotFound,
52                ErrorDomain::Mission,
53                false,
54                "mission session not found in middleware",
55            )
56        })?;
57        session.reconcile(peer_state)
58    }
59
60    /// Advance command replay on an active mission session.
61    pub fn mission_complete_replay(
62        &mut self,
63        mission_id: MissionId,
64        replayed: u32,
65    ) -> Result<(), RtError> {
66        let session = self.mission_sessions.get_mut(&mission_id).ok_or_else(|| {
67            RtError::new(
68                ErrorCode::NotFound,
69                ErrorDomain::Mission,
70                false,
71                "mission session not found for replay",
72            )
73        })?;
74        session.complete_replay(replayed)
75    }
76
77    /// Drain the next update from an active mission session.
78    pub fn mission_next_update(&mut self, mission_id: MissionId) -> Option<MissionUpdate> {
79        self.mission_sessions.get_mut(&mission_id)?.next_update()
80    }
81}