harmos_runtime/state/
managed.rs1use std::sync::Arc;
18
19use super::{At, Error, Origin, Position, TrackedState};
23use crate::Application;
24
25pub struct ManagedState<A: Application> {
34 tracked: Arc<TrackedState<A>>,
35}
36
37impl<A: Application> ManagedState<A> {
44 pub(super) fn new(tracked: Arc<TrackedState<A>>) -> Self {
45 Self { tracked }
46 }
47
48 #[tracing::instrument(target = "harmos::state", name = "state.read", level = "debug", skip_all)]
49 pub async fn read<R>(&self, read: impl FnOnce(&A::State) -> R) -> Result<At<R>, Error> {
50 if self.tracked.poisoned() {
51 return Err(self.tracked.unavailable());
52 }
53 let state = self.tracked.state.read().await;
54 if self.tracked.poisoned() {
56 return Err(self.tracked.unavailable());
57 }
58
59 Ok(At { value: read(&state.value), position: state.position })
60 }
61
62 #[tracing::instrument(target = "harmos::state", name = "state.at", level = "debug", skip_all)]
63 pub async fn at(&self, origin: Origin<A::State>, at: Position) -> Result<At<A::State>, Error> {
64 if self.tracked.poisoned() {
65 return Err(self.tracked.unavailable());
66 }
67
68 {
69 let tail = self.tracked.tail.read().await;
70 if tail.splits_commit(at) || tail.splits_commit(origin.position) {
71 return Err(Error::IncompleteCommit);
72 }
73 }
74 self.tracked.reads.state(origin, at).await
75 }
76}
77
78impl<A: Application> Clone for ManagedState<A> {
79 fn clone(&self) -> Self {
80 Self::new(Arc::clone(&self.tracked))
81 }
82}
83
84