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.
- The developer needs to define the
-
Web:
- The framework needs to track an execution ID to the
CmdExecution
's interrupt sender. - User sends an interrupt request with the execution ID.
- The framework needs to track an execution ID to the
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>
}
}