bamboo_engine/session_app/
repository.rs1use async_trait::async_trait;
4use bamboo_domain::Session;
5
6use super::errors::{RespondError, SessionLoadError, SessionSaveError};
7use crate::SessionRepository;
8
9#[async_trait]
16pub trait SessionAccess: Send + Sync {
17 fn bind_response_writer(
20 &self,
21 owner: Option<bamboo_domain::RootActorRuntimeWrite>,
22 ) -> Result<Option<std::sync::Arc<dyn SessionAccess>>, SessionSaveError> {
23 if owner.is_some() {
24 return Err(SessionSaveError::StorageError(
25 "Root response writer is unsupported".into(),
26 ));
27 }
28 Ok(None)
29 }
30
31 fn bind_response_writer_with_inherited(
34 &self,
35 owner: Option<bamboo_domain::RootActorRuntimeWrite>,
36 inherited: Option<bamboo_domain::InheritedChildWait>,
37 ) -> Result<Option<std::sync::Arc<dyn SessionAccess>>, SessionSaveError> {
38 if inherited.is_some() {
39 return Err(SessionSaveError::StorageError(
40 "inherited response writer is unsupported".into(),
41 ));
42 }
43 self.bind_response_writer(owner)
44 }
45
46 async fn load_session(&self, id: &str) -> Result<Option<Session>, SessionLoadError>;
48
49 async fn load_or_create(&self, id: &str, model: &str) -> Result<Session, SessionLoadError>;
51
52 async fn load_merged(&self, id: &str) -> Result<Option<Session>, SessionLoadError>;
56
57 async fn save_session(&self, session: &mut Session) -> Result<(), SessionSaveError>;
63
64 async fn save_and_cache(&self, session: &mut Session) -> Result<(), SessionSaveError>;
70
71 async fn inspect_for_response(&self, id: &str) -> Result<Option<Session>, SessionLoadError> {
75 self.load_merged(id).await
76 }
77
78 async fn mutate_for_response(
84 &self,
85 id: &str,
86 mutate: Box<
87 dyn for<'session> FnOnce(&'session mut Session) -> Result<(), RespondError>
88 + Send
89 + 'static,
90 >,
91 ) -> Result<Option<Session>, RespondError> {
92 let Some(mut session) = self.load_merged(id).await? else {
93 return Ok(None);
94 };
95 mutate(&mut session)?;
96 self.save_and_cache(&mut session).await?;
97 Ok(Some(session))
98 }
99}
100
101#[async_trait]
105impl SessionAccess for SessionRepository {
106 fn bind_response_writer(
107 &self,
108 owner: Option<bamboo_domain::RootActorRuntimeWrite>,
109 ) -> Result<Option<std::sync::Arc<dyn SessionAccess>>, SessionSaveError> {
110 owner
111 .map(|owner| {
112 self.bind_root_response_writer(owner)
113 .map(|bound| std::sync::Arc::new(bound) as std::sync::Arc<dyn SessionAccess>)
114 .map_err(|error| SessionSaveError::StorageError(error.to_string()))
115 })
116 .transpose()
117 }
118
119 fn bind_response_writer_with_inherited(
120 &self,
121 owner: Option<bamboo_domain::RootActorRuntimeWrite>,
122 inherited: Option<bamboo_domain::InheritedChildWait>,
123 ) -> Result<Option<std::sync::Arc<dyn SessionAccess>>, SessionSaveError> {
124 match owner {
125 Some(owner) => self
126 .bind_root_response_writer_with_inherited(owner, inherited)
127 .map(|bound| Some(std::sync::Arc::new(bound) as std::sync::Arc<dyn SessionAccess>))
128 .map_err(|error| SessionSaveError::StorageError(error.to_string())),
129 None if inherited.is_some() => Err(SessionSaveError::StorageError(
130 "inherited response writer requires its Root owner".into(),
131 )),
132 None => Ok(None),
133 }
134 }
135
136 async fn load_session(&self, id: &str) -> Result<Option<Session>, SessionLoadError> {
137 match SessionRepository::load(self, id).await {
139 Some(session) => Ok(Some(session)),
140 None => Err(SessionLoadError::NotFound(id.to_string())),
141 }
142 }
143
144 async fn load_or_create(&self, id: &str, model: &str) -> Result<Session, SessionLoadError> {
145 Ok(SessionRepository::load_or_create(self, id, model).await)
146 }
147
148 async fn load_merged(&self, id: &str) -> Result<Option<Session>, SessionLoadError> {
149 SessionRepository::load_merged_checked(self, id)
150 .await
151 .map_err(|error| SessionLoadError::StorageError(error.to_string()))
152 }
153
154 async fn save_session(&self, session: &mut Session) -> Result<(), SessionSaveError> {
155 self.persistence()
157 .merge_save_runtime(session)
158 .await
159 .map_err(|e| SessionSaveError::StorageError(e.to_string()))
160 }
161
162 async fn save_and_cache(&self, session: &mut Session) -> Result<(), SessionSaveError> {
163 SessionRepository::save_and_cache(self, session).await;
164 Ok(())
165 }
166
167 async fn inspect_for_response(&self, id: &str) -> Result<Option<Session>, SessionLoadError> {
168 let cache = self.cache().clone();
169 let session_id = id.to_string();
170 self.persistence()
171 .inspect_runtime_session_for_response(id, move || {
172 crate::read_cached_session(&cache, &session_id)
173 })
174 .await
175 .map_err(|error| SessionLoadError::StorageError(error.to_string()))
176 }
177
178 async fn mutate_for_response(
179 &self,
180 id: &str,
181 mutate: Box<
182 dyn for<'session> FnOnce(&'session mut Session) -> Result<(), RespondError>
183 + Send
184 + 'static,
185 >,
186 ) -> Result<Option<Session>, RespondError> {
187 let cache_for_load = self.cache().clone();
188 let publish_cache = self.cache().clone();
189 let session_id = id.to_string();
190 match self
191 .persistence()
192 .mutate_runtime_session_and_publish(
193 id,
194 move || crate::read_cached_session(&cache_for_load, &session_id),
195 move |session| mutate(session),
196 move |saved| {
197 publish_cache.insert(
198 saved.id.clone(),
199 std::sync::Arc::new(crate::SessionSnapshot::new(saved.clone())),
200 );
201 },
202 )
203 .await
204 {
205 Ok(Ok(session)) => Ok(session),
206 Ok(Err(error)) => Err(error),
207 Err(error) => Err(RespondError::SaveFailed(SessionSaveError::StorageError(
208 error.to_string(),
209 ))),
210 }
211 }
212}