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