robotrt-middleware-core 0.1.0-beta.2

RobotRT modular robotics runtime and middleware components.
Documentation
use core_types::{ErrorCode, ErrorDomain, MissionId, RtError, SessionId, TransportDomain};
use mission_core::message::{
    MissionOpen, MissionPeerState, MissionReconcileSummary, MissionUpdate,
};
use mission_core::session::MissionSession;

use crate::session::SessionManager;

use super::MiddlewareStack;

impl MiddlewareStack {
    /// Open a new Mission session and register it with the middleware.
    pub fn open_mission(
        &mut self,
        session_id: SessionId,
        open: MissionOpen,
    ) -> Result<MissionId, RtError> {
        let mission_id = open.mission_id;
        let mut session = mission_core::session::BasicMissionSession::new(mission_id);
        session.open(open)?;
        self.mission_sessions.insert(mission_id, session);
        let _domain = self
            .session_manager
            .get_session(session_id)
            .map(|r| r.domain)
            .unwrap_or(TransportDomain::Local);
        Ok(mission_id)
    }

    /// Mark a mission session as disconnected and transition the transport
    /// session to the Reconnecting state.
    pub fn mission_disconnect(&mut self, session_id: SessionId, reason: impl Into<String>) {
        self.session_manager.mark_reconnecting(session_id, reason);
    }

    /// After a successful reconnect, perform state reconcile with the peer.
    ///
    /// This method:
    /// 1. Marks the transport session as Connected again.
    /// 2. Calls `reconcile(peer_state)` on the stored `BasicMissionSession`.
    /// 3. Returns the `MissionReconcileSummary` so the caller can schedule replay.
    pub fn mission_reconnect_reconcile(
        &mut self,
        session_id: SessionId,
        mission_id: MissionId,
        peer_state: MissionPeerState,
    ) -> Result<MissionReconcileSummary, RtError> {
        self.session_manager.mark_connected(session_id);
        let session = self.mission_sessions.get_mut(&mission_id).ok_or_else(|| {
            RtError::new(
                ErrorCode::NotFound,
                ErrorDomain::Mission,
                false,
                "mission session not found in middleware",
            )
        })?;
        session.reconcile(peer_state)
    }

    /// Advance command replay on an active mission session.
    pub fn mission_complete_replay(
        &mut self,
        mission_id: MissionId,
        replayed: u32,
    ) -> Result<(), RtError> {
        let session = self.mission_sessions.get_mut(&mission_id).ok_or_else(|| {
            RtError::new(
                ErrorCode::NotFound,
                ErrorDomain::Mission,
                false,
                "mission session not found for replay",
            )
        })?;
        session.complete_replay(replayed)
    }

    /// Drain the next update from an active mission session.
    pub fn mission_next_update(&mut self, mission_id: MissionId) -> Option<MissionUpdate> {
        self.mission_sessions.get_mut(&mission_id)?.next_update()
    }
}