harmos_runtime/operations/
scope.rs1use std::collections::BTreeMap;
18use std::sync::atomic::{AtomicBool, Ordering};
19use std::sync::{Arc, Mutex, Weak};
20use tokio::sync::watch;
22use super::lane::Admission;
24use crate::operations::OperationInstanceId;
25use crate::operations::instances::{Instances, Reservation};
26use crate::state::Position;
27use crate::supervision::instance::{Instance, Phase, Status};
28
29#[derive(Clone, Copy)]
38pub struct Scope<'a> {
39 core: &'a ScopeCore,
40}
41
42#[derive(Clone)]
43pub(crate) struct ScopeCore {
44 instances: Arc<Instances>,
45 parent: Weak<Instance>,
46 admission: Admission,
47 cause: Option<Position>,
48 children: Arc<Mutex<BTreeMap<OperationInstanceId, Child>>>,
49 closed: Arc<AtomicBool>,
50}
51
52pub(crate) struct ClosedScope {
53 children: Vec<Child>,
54}
55
56pub(crate) struct Child {
57 settled: watch::Receiver<Status>,
58 control: Arc<Instance>,
59}
60
61impl<'a> Scope<'a> {
68 pub(crate) fn owned(&self) -> ScopeCore {
69 self.core.clone()
70 }
71
72 pub(crate) fn over(core: &'a ScopeCore) -> Self {
73 Self { core }
74 }
75
76 #[cfg(any(feature = "plugin", feature = "plugin-guest", feature = "plugin-sidecar"))]
77 pub(crate) fn original_control(&self) -> Weak<Instance> {
78 self.core.parent.clone()
79 }
80
81 pub(crate) fn reserve_tracked<O>(
82 &self, id: OperationInstanceId, lane: &'static str, submitted: tokio::time::Instant, privileged: bool,
83 retired: impl Fn() + Send + Sync + 'static,
84 ) -> crate::Result<Reservation<O>>
85 where
86 O: Send + 'static,
87 {
88 let mut tracked = self.core.children.lock().expect("scope child lock is healthy");
89 if self.core.closed.load(Ordering::Acquire) {
90 return Err(crate::Error::Closing { domain: "operation scope" });
91 }
92 let children = Arc::downgrade(&self.core.children);
93 let preparation = self.core.instances.reserve(id, lane, submitted, privileged, move || {
94 if let Some(children) = children.upgrade() {
95 let removed = children.lock().expect("scope child lock is healthy").remove(&id);
96 drop(removed);
97 }
98 retired();
99 })?;
100 let child = Child::new(preparation.control());
101 if let Some(parent) = self.core.parent.upgrade() {
102 parent.track(&child.settlement());
103 }
104 tracked.insert(id, child);
105 Ok(preparation.inherit(self.core.cause))
106 }
107
108 pub fn now(&self) -> tokio::time::Instant {
109 crate::supervision::executor::now()
110 }
111
112 pub fn resources<A: crate::Application>(&self) -> &'a A::Resources {
113 self.core.instances.resources_of::<A>()
114 }
115
116 pub fn records<A: crate::Application>(&self) -> crate::records::RecordManager<A> {
117 crate::records::RecordManager::new(self.state::<A>())
118 }
119
120 pub fn storage<A: crate::Application>(&self) -> Option<&'a crate::storage::StorageManager<crate::storage::ErasedCatalog>> {
121 self.core.instances.handles_of::<A>().storage.get()
122 }
123
124 pub fn streams<A: crate::Application>(&self) -> crate::streams::StreamManager<A> {
125 self.core.instances.handles_of::<A>().streams.clone()
126 }
127
128 pub fn evidence<A: crate::Application>(&self) -> crate::evidence::Evidence<A> {
129 self.core.instances.handles_of::<A>().evidence.clone()
130 }
131
132 pub fn state<A: crate::Application>(&self) -> crate::state::StateManager<A> {
133 let journal = self.core.instances.state_of::<A>();
134 match self.core.cause {
135 Some(cause) => journal.caused_by(cause),
136 None => journal,
137 }
138 }
139}
140
141impl std::fmt::Debug for Scope<'_> {
142 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
143 formatter.debug_struct("Scope").field("lane", &self.core.admission.name()).field("cause", &self.core.cause).finish()
144 }
145}
146
147impl ScopeCore {
148 pub(crate) fn new(instances: Arc<Instances>, admission: Admission, cause: Option<Position>, parent: Weak<Instance>) -> Self {
149 Self {
150 instances,
151 parent,
152 admission,
153 cause,
154 children: Arc::new(Mutex::new(BTreeMap::new())),
155 closed: Arc::new(AtomicBool::new(false)),
156 }
157 }
158
159 pub(crate) fn close(self) -> ClosedScope {
160 let children: Vec<_> = {
161 let mut children = self.children.lock().expect("scope child lock is healthy");
162 self.closed.store(true, Ordering::Release);
163 std::mem::take(&mut *children).into_values().collect()
164 };
165 for child in &children {
166 child.control.cancel();
167 }
168
169 ClosedScope { children }
170 }
171}
172
173impl ClosedScope {
174 pub(crate) async fn drain(&mut self) {
175 for child in &mut self.children {
176 let _ = child.settled.wait_for(|status| status.phase() == Phase::Settled).await;
177 }
178 }
179}
180
181impl Child {
182 pub(crate) fn settlement(&self) -> Arc<Instance> {
183 Arc::clone(&self.control)
184 }
185
186 pub(crate) fn new(control: Arc<Instance>) -> Self {
187 let settled = control.settlement();
188 Self { settled, control }
189 }
190}
191
192