rmux-server 0.10.0

Tokio daemon and request dispatcher for the RMUX terminal multiplexer.
Documentation
use std::cell::RefCell;
use std::future::Future;

use rmux_proto::{Request, Response, SessionId, SessionName};

use super::queue::QueueExecutionContext;

tokio::task_local! {
    static QUEUED_NEW_SESSION_TRANSITION: RefCell<Option<QueuedCurrentSessionTransition>>;
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub(super) struct QueuedCurrentSessionTransition {
    session_id: SessionId,
    session_name: SessionName,
}

impl QueuedCurrentSessionTransition {
    pub(super) async fn capture<T, F>(
        context: &QueueExecutionContext,
        request: &Request,
        future: F,
    ) -> (T, Option<Self>)
    where
        F: Future<Output = T>,
    {
        if !context.accepts_explicit_current_session_transition()
            || !matches!(request, Request::NewSession(_) | Request::NewSessionExt(_))
        {
            return (future.await, None);
        }

        QUEUED_NEW_SESSION_TRANSITION
            .scope(RefCell::new(None), async move {
                let output = future.await;
                let transition =
                    QUEUED_NEW_SESSION_TRANSITION.with(|captured| captured.borrow().clone());
                (output, transition)
            })
            .await
    }

    pub(super) fn commit(self, response: &Response) -> Option<Self> {
        matches!(
            response,
            Response::NewSession(response) if response.session_name == self.session_name
        )
        .then_some(self)
    }

    pub(super) fn apply(&self, context: &mut QueueExecutionContext) {
        context
            .rebase_after_explicit_current_session_transition(self.session_id, &self.session_name);
    }
}

pub(in crate::handler) fn record_queued_new_session_transition(
    session_id: SessionId,
    session_name: SessionName,
) {
    let _ = QUEUED_NEW_SESSION_TRANSITION.try_with(|captured| {
        let mut captured = captured.borrow_mut();
        if captured.is_none() {
            *captured = Some(QueuedCurrentSessionTransition {
                session_id,
                session_name,
            });
        }
    });
}