opendev_web/state/
approvals.rs1use tokio::sync::oneshot;
4
5use super::{
6 AppState, ApprovalResult, AskUserResult, PendingApproval, PendingApprovalSlot, PendingAskUser,
7 PendingAskUserSlot, PendingPlanApproval, PendingPlanApprovalSlot, PlanApprovalResult,
8};
9
10impl AppState {
11 pub async fn add_pending_approval(
18 &self,
19 id: String,
20 approval: PendingApproval,
21 ) -> oneshot::Receiver<ApprovalResult> {
22 let (tx, rx) = oneshot::channel();
23 self.inner.pending_approvals.lock().await.insert(
24 id,
25 PendingApprovalSlot {
26 meta: approval,
27 tx: Some(tx),
28 },
29 );
30 rx
31 }
32
33 pub async fn resolve_approval(
37 &self,
38 id: &str,
39 approved: bool,
40 auto_approve: bool,
41 ) -> Option<PendingApproval> {
42 let mut approvals = self.inner.pending_approvals.lock().await;
43 if let Some(mut slot) = approvals.remove(id) {
44 if let Some(tx) = slot.tx.take() {
45 let _ = tx.send(ApprovalResult {
46 approved,
47 auto_approve,
48 });
49 }
50 Some(slot.meta)
51 } else {
52 None
53 }
54 }
55
56 pub async fn get_pending_approval(&self, id: &str) -> Option<PendingApproval> {
58 self.inner
59 .pending_approvals
60 .lock()
61 .await
62 .get(id)
63 .map(|slot| slot.meta.clone())
64 }
65
66 pub async fn clear_session_approvals(&self, session_id: &str) {
71 let mut approvals = self.inner.pending_approvals.lock().await;
72 let to_remove: Vec<String> = approvals
73 .iter()
74 .filter(|(_, slot)| slot.meta.session_id.as_deref() == Some(session_id))
75 .map(|(id, _)| id.clone())
76 .collect();
77
78 for id in to_remove {
79 if let Some(mut slot) = approvals.remove(&id)
80 && let Some(tx) = slot.tx.take()
81 {
82 let _ = tx.send(ApprovalResult {
83 approved: false,
84 auto_approve: false,
85 });
86 }
87 }
88 }
89
90 pub async fn add_pending_ask_user(
96 &self,
97 id: String,
98 ask_user: PendingAskUser,
99 ) -> oneshot::Receiver<AskUserResult> {
100 let (tx, rx) = oneshot::channel();
101 self.inner.pending_ask_users.lock().await.insert(
102 id,
103 PendingAskUserSlot {
104 meta: ask_user,
105 tx: Some(tx),
106 },
107 );
108 rx
109 }
110
111 pub async fn resolve_ask_user(
113 &self,
114 id: &str,
115 answers: Option<serde_json::Value>,
116 cancelled: bool,
117 ) -> Option<PendingAskUser> {
118 let mut ask_users = self.inner.pending_ask_users.lock().await;
119 if let Some(mut slot) = ask_users.remove(id) {
120 if let Some(tx) = slot.tx.take() {
121 let _ = tx.send(AskUserResult { answers, cancelled });
122 }
123 Some(slot.meta)
124 } else {
125 None
126 }
127 }
128
129 pub async fn get_pending_ask_user(&self, id: &str) -> Option<PendingAskUser> {
131 self.inner
132 .pending_ask_users
133 .lock()
134 .await
135 .get(id)
136 .map(|slot| slot.meta.clone())
137 }
138
139 pub async fn add_pending_plan_approval(
146 &self,
147 id: String,
148 plan_approval: PendingPlanApproval,
149 ) -> oneshot::Receiver<PlanApprovalResult> {
150 let (tx, rx) = oneshot::channel();
151 self.inner.pending_plan_approvals.lock().await.insert(
152 id,
153 PendingPlanApprovalSlot {
154 meta: plan_approval,
155 tx: Some(tx),
156 },
157 );
158 rx
159 }
160
161 pub async fn resolve_plan_approval(
168 &self,
169 id: &str,
170 action: String,
171 feedback: String,
172 ) -> Option<PendingPlanApproval> {
173 let mut plan_approvals = self.inner.pending_plan_approvals.lock().await;
174 if let Some(mut slot) = plan_approvals.remove(id) {
175 if let Some(tx) = slot.tx.take() {
176 let _ = tx.send(PlanApprovalResult { action, feedback });
177 }
178 Some(slot.meta)
179 } else {
180 None
181 }
182 }
183
184 pub async fn get_pending_plan_approval(&self, id: &str) -> Option<PendingPlanApproval> {
186 self.inner
187 .pending_plan_approvals
188 .lock()
189 .await
190 .get(id)
191 .map(|slot| slot.meta.clone())
192 }
193
194 pub async fn clear_session_plan_approvals(&self, session_id: &str) {
196 let mut plan_approvals = self.inner.pending_plan_approvals.lock().await;
197 let to_remove: Vec<String> = plan_approvals
198 .iter()
199 .filter(|(_, slot)| slot.meta.session_id.as_deref() == Some(session_id))
200 .map(|(id, _)| id.clone())
201 .collect();
202
203 for id in to_remove {
204 if let Some(mut slot) = plan_approvals.remove(&id)
205 && let Some(tx) = slot.tx.take()
206 {
207 let _ = tx.send(PlanApprovalResult {
208 action: "reject".to_string(),
209 feedback: "Session ended".to_string(),
210 });
211 }
212 }
213 }
214}