1use std::sync::{Arc, Mutex};
2
3use tokio::sync::broadcast;
4use tokio::task::JoinHandle;
5
6use crate::approval::{ApprovalBroker, ApprovalError};
7use crate::events::RunEvent;
8use crate::result::RunResult;
9use crate::runner::RunEventStream;
10use crate::runtime::CancellationToken;
11use crate::tools::ApprovalDecision;
12
13pub(crate) type RunEventSenderSlot = Arc<Mutex<Option<broadcast::Sender<RunEvent>>>>;
14type RunJoinHandle = JoinHandle<Result<RunResult, String>>;
15type SharedJoinHandle = Arc<tokio::sync::Mutex<Option<RunJoinHandle>>>;
16
17#[derive(Debug, Clone, PartialEq, Eq)]
18pub enum RunHandleStatus {
19 Running,
20 Completed,
21 Failed,
22 Cancelled,
23}
24
25#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct RunHandleState {
27 pub status: RunHandleStatus,
28 pub done: bool,
29 pub cancelled: bool,
30 pub error: Option<String>,
31}
32
33impl RunHandleState {
34 pub fn running() -> Self {
35 Self {
36 status: RunHandleStatus::Running,
37 done: false,
38 cancelled: false,
39 error: None,
40 }
41 }
42
43 pub fn completed() -> Self {
44 Self {
45 status: RunHandleStatus::Completed,
46 done: true,
47 cancelled: false,
48 error: None,
49 }
50 }
51
52 pub fn failed(error: impl Into<String>) -> Self {
53 Self {
54 status: RunHandleStatus::Failed,
55 done: true,
56 cancelled: false,
57 error: Some(error.into()),
58 }
59 }
60
61 pub fn cancelled() -> Self {
62 Self {
63 status: RunHandleStatus::Cancelled,
64 done: true,
65 cancelled: true,
66 error: Some("run cancelled".to_string()),
67 }
68 }
69}
70
71#[derive(Clone)]
72pub(crate) struct SharedRunResult {
73 join: SharedJoinHandle,
74}
75
76impl SharedRunResult {
77 pub(crate) fn new(join: RunJoinHandle) -> Self {
78 Self {
79 join: Arc::new(tokio::sync::Mutex::new(Some(join))),
80 }
81 }
82
83 pub(crate) async fn wait(&self) -> Result<RunResult, String> {
84 let join = self
85 .join
86 .lock()
87 .await
88 .take()
89 .ok_or_else(|| "run result already taken".to_string())?;
90 join.await
91 .map_err(|error| format!("run task failed: {error}"))?
92 }
93}
94
95#[derive(Clone)]
96pub struct RunHandle {
97 sender: RunEventSenderSlot,
98 events: Arc<Mutex<Vec<RunEvent>>>,
99 result: SharedRunResult,
100 state: Arc<Mutex<RunHandleState>>,
101 cancellation_token: CancellationToken,
102 approval_broker: ApprovalBroker,
103}
104
105impl RunHandle {
106 pub(crate) fn new(
107 sender: RunEventSenderSlot,
108 events: Arc<Mutex<Vec<RunEvent>>>,
109 result: SharedRunResult,
110 state: Arc<Mutex<RunHandleState>>,
111 cancellation_token: CancellationToken,
112 approval_broker: ApprovalBroker,
113 ) -> Self {
114 Self {
115 sender,
116 events,
117 result,
118 state,
119 cancellation_token,
120 approval_broker,
121 }
122 }
123
124 pub fn events(&self) -> RunEventStream {
125 let receiver = self
126 .sender
127 .lock()
128 .ok()
129 .and_then(|sender| sender.as_ref().map(broadcast::Sender::subscribe));
130 RunEventStream::from_live(receiver, Some(self.result.clone()), self.event_snapshot())
131 }
132
133 pub(crate) fn into_event_stream(self) -> RunEventStream {
134 let receiver = self
135 .sender
136 .lock()
137 .ok()
138 .and_then(|sender| sender.as_ref().map(broadcast::Sender::subscribe));
139 RunEventStream::from_live(receiver, Some(self.result.clone()), self.event_snapshot())
140 }
141
142 pub async fn result(&self) -> Result<RunResult, String> {
143 self.result.wait().await
144 }
145
146 pub fn state(&self) -> RunHandleState {
147 self.state
148 .lock()
149 .map(|state| state.clone())
150 .unwrap_or_else(|_| RunHandleState::failed("run handle state lock poisoned"))
151 }
152
153 pub fn cancel(&self) {
154 self.cancellation_token.cancel();
155 if let Ok(mut state) = self.state.lock() {
156 if !state.done {
157 *state = RunHandleState::cancelled();
158 }
159 }
160 }
161
162 pub fn cancellation_token(&self) -> &CancellationToken {
163 &self.cancellation_token
164 }
165
166 pub async fn approve(
167 &self,
168 request_id: impl AsRef<str>,
169 decision: ApprovalDecision,
170 ) -> Result<(), ApprovalError> {
171 self.approval_broker.resolve(request_id, decision)
172 }
173
174 pub fn approval_broker(&self) -> &ApprovalBroker {
175 &self.approval_broker
176 }
177
178 fn event_snapshot(&self) -> Vec<RunEvent> {
179 self.events
180 .lock()
181 .map(|events| events.clone())
182 .unwrap_or_default()
183 }
184}