guinea_core/scope/
actors.rs1use crate::actor::Addr;
2use crate::actor::registry::{ActorSnapshot, Owner};
3use crate::actor::traits::ManagedActor;
4use crate::observability::changes::{self, Change};
5
6use super::{Scope, Teardown};
7
8pub(super) struct HeldActor {
9 id: usize,
10 type_name: &'static str,
11 shape: crate::actor::shape::Shape,
12 owner: Owner,
13 snapshot: Box<dyn Fn() -> String>,
14}
15
16impl HeldActor {
17 fn read(&self) -> ActorSnapshot {
18 ActorSnapshot {
19 id: self.id,
20 type_name: self.type_name,
21 shape: self.shape,
22 owner: self.owner,
23 state: (self.snapshot)(),
24 }
25 }
26}
27
28fn read_all(scopes: Vec<Scope>) -> Vec<ActorSnapshot> {
29 scopes
30 .into_iter()
31 .filter_map(|scope| scope.data())
32 .flat_map(|data| data.actors.borrow().iter().map(HeldActor::read).collect::<Vec<_>>())
33 .collect()
34}
35
36fn read_one(scopes: Vec<Scope>, id: usize) -> Option<ActorSnapshot> {
37 scopes.into_iter().filter_map(|scope| scope.data()).find_map(|data| {
38 data.actors
39 .borrow()
40 .iter()
41 .find(|actor| actor.id == id)
42 .map(HeldActor::read)
43 })
44}
45
46struct Unlisted {
48 root: Option<u64>,
49 id: usize,
50}
51
52impl Teardown for Unlisted {
53 fn teardown(self) {
54 changes::changed(|| Change::ActorRemoved {
55 root: self.root,
56 id: self.id,
57 });
58 }
59}
60
61impl Scope {
62 pub fn set_window(&self, id: u64) {
65 if let Some(data) = self.data() {
66 data.window.set(Some(id));
67 }
68 }
69
70 pub fn window(&self) -> Option<u64> {
72 std::iter::successors(Some(*self), Scope::parent)
73 .find_map(|scope| scope.data()?.window.get())
74 }
75
76 pub fn hold_actor<A: ManagedActor + std::fmt::Debug>(
83 &self,
84 addr: &Addr<A>,
85 feature: Option<&'static str>,
86 drives: Option<&'static str>,
87 ) {
88 let Some(data) = self.data() else { return };
89 let id = addr.id();
90 let type_name = crate::actor::short_type_name::<A>();
91 let owner = Owner {
92 scope: Some(self.key()),
93 feature,
94 drives,
95 };
96
97 let held = addr.clone();
98 data.actors.borrow_mut().push(HeldActor {
99 id,
100 type_name,
101 shape: A::SHAPE,
102 owner,
103 snapshot: Box::new(move || held.debug_snapshot()),
104 });
105 drop(data);
106
107 let root = self.window();
108 changes::changed(|| Change::ActorAdded {
109 root,
110 id,
111 type_name,
112 owner,
113 });
114 self.own(Unlisted { root, id });
115 }
116
117 pub fn actors(&self) -> Vec<ActorSnapshot> {
119 read_all(self.subtree())
120 }
121
122 pub fn actor(&self, id: usize) -> Option<ActorSnapshot> {
125 read_one(self.subtree(), id)
126 }
127
128 pub fn actors_here(&self) -> Vec<ActorSnapshot> {
131 read_all(vec![*self])
132 }
133
134 pub fn actor_here(&self, id: usize) -> Option<ActorSnapshot> {
136 read_one(vec![*self], id)
137 }
138}