Interruption

User has sent an interruption request. These are received differently depending on the Output that presented the interface to the user.

  • CLI:

    • The developer needs to define the SIGINT handler, and pass it into Peace (1, 2).
    • The user presses Ctrl C to interrupt the command execution.
  • Web:

    • The framework needs to track an execution ID to the CmdExecution's interrupt sender.
    • User sends an interrupt request with the execution ID.

Implementation

This follows on from the Cmd Invocation > Web Interface design.

4. Web Component InterruptSenders Access

InterruptSenders may be a newtype for Map<ExecutionId, Sender<InterruptSignal>>

See:

#[leptos::server(endpoint = "/cmd_exec_interrupt")]
pub async fn cmd_exec_interrupt(
    execution_id: &ExecutionId,
) -> Result<(), ServerFnError<NoCustomError>> {
    let interrupt_senders = leptos::use_context::<InterruptSenders>()
        .ok_or_else(|| {
            ServerFnError::<NoCustomError>::ServerError(
                "`InterruptSenders` was not set.".to_string()
            )
        })?;
    if let Some(interrupt_sender) = interrupt_senders.get(execution_id) {
        interrupt_sender.send(InterruptSignal).await;
    }

    Ok(())
}

#[component]
pub fn InterruptButton(
    execution_id: ReadSignal<ExecutionId>,
) -> impl IntoView {
    let cmd_exec_interrupt_action = leptos::create_action(
        |execution_id: &ExecutionId| {
            let execution_id = execution_id.clone();
            async move { cmd_exec_interrupt(&execution_id).await }
        },
    );
    let submitted = cmd_exec_interrupt_action.input(); // RwSignal<Option<String>>
    let pending = cmd_exec_interrupt_action.pending(); // ReadSignal<bool>
    let todo_id = cmd_exec_interrupt_action.value(); // RwSignal<Option<Uuid>>

    view! {
        <form
            on:submit=move |ev| {
                ev.prevent_default(); // don't reload the page.
                cmd_exec_interrupt_action.dispatch(execution_id.get());
            }
        >
            // Execution ID
            <button type="submit">"Interrupt"</button>
        </form>
        // use our loading state
        <p>{move || pending().then("Loading...")}</p>
    }
}