meerkat_runtime/
user_interrupt.rs1use std::sync::Arc;
2
3use meerkat_core::lifecycle::CoreExecutorInterruptHandle;
4use meerkat_core::types::SessionId;
5
6use crate::meerkat_machine::MeerkatMachine;
7use crate::runtime_state::RuntimeState;
8use crate::traits::RuntimeDriverError;
9
10impl MeerkatMachine {
11 pub async fn hard_cancel_current_run(
12 &self,
13 session_id: &SessionId,
14 reason: impl Into<String>,
15 ) -> Result<(), RuntimeDriverError> {
16 self.dispatch_user_interrupt(session_id, reason.into())
17 .await
18 }
19
20 pub(super) async fn apply_user_interrupt_live_cancel(
24 &self,
25 session_id: &SessionId,
26 reason: String,
27 ) -> Result<(), RuntimeDriverError> {
28 let authority = UserInterruptAuthority::new();
29 self.hard_cancel_current_run_authorized(session_id, reason, authority)
30 .await
31 }
32
33 async fn hard_cancel_current_run_authorized(
34 &self,
35 session_id: &SessionId,
36 reason: String,
37 _authority: UserInterruptAuthority,
38 ) -> Result<(), RuntimeDriverError> {
39 let handle = self.interrupt_handle_for(session_id).await?;
40 handle.hard_cancel_current_run(reason).await.map_err(|err| {
41 RuntimeDriverError::Internal(format!("failed to hard cancel run: {err}"))
42 })
43 }
44
45 async fn interrupt_handle_for(
46 &self,
47 session_id: &SessionId,
48 ) -> Result<Arc<dyn CoreExecutorInterruptHandle>, RuntimeDriverError> {
49 let handle = {
50 let sessions = self.sessions.read().await;
51 let entry = sessions
52 .get(session_id)
53 .ok_or(RuntimeDriverError::NotReady {
54 state: RuntimeState::Destroyed,
55 })?;
56 entry.interrupt_handle()
57 };
58
59 let Some(handle) = handle else {
60 let state = self
61 .existing_session_runtime_state(session_id)
62 .await
63 .unwrap_or(RuntimeState::Destroyed);
64 return Err(RuntimeDriverError::NotReady { state });
65 };
66
67 Ok(handle)
68 }
69}
70
71struct UserInterruptAuthority(());
72
73impl UserInterruptAuthority {
74 fn new() -> Self {
75 Self(())
76 }
77}