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 async fn load_session(&self, id: &str) -> Result<Option<Session>, SessionLoadError>;
33
34 async fn load_or_create(&self, id: &str, model: &str) -> Result<Session, SessionLoadError>;
36
37 async fn load_merged(&self, id: &str) -> Result<Option<Session>, SessionLoadError>;
41
42 async fn save_session(&self, session: &mut Session) -> Result<(), SessionSaveError>;
48
49 async fn save_and_cache(&self, session: &mut Session) -> Result<(), SessionSaveError>;
55
56 async fn inspect_for_response(&self, id: &str) -> Result<Option<Session>, SessionLoadError> {
60 self.load_merged(id).await
61 }
62
63 async fn mutate_for_response(
69 &self,
70 id: &str,
71 mutate: Box<
72 dyn for<'session> FnOnce(&'session mut Session) -> Result<(), RespondError>
73 + Send
74 + 'static,
75 >,
76 ) -> Result<Option<Session>, RespondError> {
77 let Some(mut session) = self.load_merged(id).await? else {
78 return Ok(None);
79 };
80 mutate(&mut session)?;
81 self.save_and_cache(&mut session).await?;
82 Ok(Some(session))
83 }
84}
85
86#[async_trait]
90impl SessionAccess for SessionRepository {
91 fn bind_response_writer(
92 &self,
93 owner: Option<bamboo_domain::RootActorRuntimeWrite>,
94 ) -> Result<Option<std::sync::Arc<dyn SessionAccess>>, SessionSaveError> {
95 owner
96 .map(|owner| {
97 self.bind_root_response_writer(owner)
98 .map(|bound| std::sync::Arc::new(bound) as std::sync::Arc<dyn SessionAccess>)
99 .map_err(|error| SessionSaveError::StorageError(error.to_string()))
100 })
101 .transpose()
102 }
103
104 async fn load_session(&self, id: &str) -> Result<Option<Session>, SessionLoadError> {
105 match SessionRepository::load(self, id).await {
107 Some(session) => Ok(Some(session)),
108 None => Err(SessionLoadError::NotFound(id.to_string())),
109 }
110 }
111
112 async fn load_or_create(&self, id: &str, model: &str) -> Result<Session, SessionLoadError> {
113 Ok(SessionRepository::load_or_create(self, id, model).await)
114 }
115
116 async fn load_merged(&self, id: &str) -> Result<Option<Session>, SessionLoadError> {
117 SessionRepository::load_merged_checked(self, id)
118 .await
119 .map_err(|error| SessionLoadError::StorageError(error.to_string()))
120 }
121
122 async fn save_session(&self, session: &mut Session) -> Result<(), SessionSaveError> {
123 self.persistence()
125 .merge_save_runtime(session)
126 .await
127 .map_err(|e| SessionSaveError::StorageError(e.to_string()))
128 }
129
130 async fn save_and_cache(&self, session: &mut Session) -> Result<(), SessionSaveError> {
131 SessionRepository::save_and_cache(self, session).await;
132 Ok(())
133 }
134
135 async fn inspect_for_response(&self, id: &str) -> Result<Option<Session>, SessionLoadError> {
136 let cache = self.cache().clone();
137 let session_id = id.to_string();
138 self.persistence()
139 .inspect_runtime_session_for_response(id, move || {
140 crate::read_cached_session(&cache, &session_id)
141 })
142 .await
143 .map_err(|error| SessionLoadError::StorageError(error.to_string()))
144 }
145
146 async fn mutate_for_response(
147 &self,
148 id: &str,
149 mutate: Box<
150 dyn for<'session> FnOnce(&'session mut Session) -> Result<(), RespondError>
151 + Send
152 + 'static,
153 >,
154 ) -> Result<Option<Session>, RespondError> {
155 let cache_for_load = self.cache().clone();
156 let publish_cache = self.cache().clone();
157 let session_id = id.to_string();
158 match self
159 .persistence()
160 .mutate_runtime_session_and_publish(
161 id,
162 move || crate::read_cached_session(&cache_for_load, &session_id),
163 move |session| mutate(session),
164 move |saved| {
165 publish_cache.insert(
166 saved.id.clone(),
167 std::sync::Arc::new(crate::SessionSnapshot::new(saved.clone())),
168 );
169 },
170 )
171 .await
172 {
173 Ok(Ok(session)) => Ok(session),
174 Ok(Err(error)) => Err(error),
175 Err(error) => Err(RespondError::SaveFailed(SessionSaveError::StorageError(
176 error.to_string(),
177 ))),
178 }
179 }
180}