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 async fn load_session(&self, id: &str) -> Result<Option<Session>, SessionLoadError>;
19
20 async fn load_or_create(&self, id: &str, model: &str) -> Result<Session, SessionLoadError>;
22
23 async fn load_merged(&self, id: &str) -> Result<Option<Session>, SessionLoadError>;
27
28 async fn save_session(&self, session: &mut Session) -> Result<(), SessionSaveError>;
34
35 async fn save_and_cache(&self, session: &mut Session) -> Result<(), SessionSaveError>;
41
42 async fn inspect_for_response(&self, id: &str) -> Result<Option<Session>, SessionLoadError> {
46 self.load_merged(id).await
47 }
48
49 async fn mutate_for_response(
55 &self,
56 id: &str,
57 mutate: Box<
58 dyn for<'session> FnOnce(&'session mut Session) -> Result<(), RespondError>
59 + Send
60 + 'static,
61 >,
62 ) -> Result<Option<Session>, RespondError> {
63 let Some(mut session) = self.load_merged(id).await? else {
64 return Ok(None);
65 };
66 mutate(&mut session)?;
67 self.save_and_cache(&mut session).await?;
68 Ok(Some(session))
69 }
70}
71
72#[async_trait]
76impl SessionAccess for SessionRepository {
77 async fn load_session(&self, id: &str) -> Result<Option<Session>, SessionLoadError> {
78 match SessionRepository::load(self, id).await {
80 Some(session) => Ok(Some(session)),
81 None => Err(SessionLoadError::NotFound(id.to_string())),
82 }
83 }
84
85 async fn load_or_create(&self, id: &str, model: &str) -> Result<Session, SessionLoadError> {
86 Ok(SessionRepository::load_or_create(self, id, model).await)
87 }
88
89 async fn load_merged(&self, id: &str) -> Result<Option<Session>, SessionLoadError> {
90 SessionRepository::load_merged_checked(self, id)
91 .await
92 .map_err(|error| SessionLoadError::StorageError(error.to_string()))
93 }
94
95 async fn save_session(&self, session: &mut Session) -> Result<(), SessionSaveError> {
96 self.persistence()
98 .merge_save_runtime(session)
99 .await
100 .map_err(|e| SessionSaveError::StorageError(e.to_string()))
101 }
102
103 async fn save_and_cache(&self, session: &mut Session) -> Result<(), SessionSaveError> {
104 SessionRepository::save_and_cache(self, session).await;
105 Ok(())
106 }
107
108 async fn inspect_for_response(&self, id: &str) -> Result<Option<Session>, SessionLoadError> {
109 let cache = self.cache().clone();
110 let session_id = id.to_string();
111 self.persistence()
112 .inspect_runtime_session_for_response(id, move || {
113 crate::read_cached_session(&cache, &session_id)
114 })
115 .await
116 .map_err(|error| SessionLoadError::StorageError(error.to_string()))
117 }
118
119 async fn mutate_for_response(
120 &self,
121 id: &str,
122 mutate: Box<
123 dyn for<'session> FnOnce(&'session mut Session) -> Result<(), RespondError>
124 + Send
125 + 'static,
126 >,
127 ) -> Result<Option<Session>, RespondError> {
128 let cache_for_load = self.cache().clone();
129 let publish_cache = self.cache().clone();
130 let session_id = id.to_string();
131 match self
132 .persistence()
133 .mutate_runtime_session_and_publish(
134 id,
135 move || crate::read_cached_session(&cache_for_load, &session_id),
136 move |session| mutate(session),
137 move |saved| {
138 publish_cache.insert(
139 saved.id.clone(),
140 std::sync::Arc::new(parking_lot::RwLock::new(saved.clone())),
141 );
142 },
143 )
144 .await
145 {
146 Ok(Ok(session)) => Ok(session),
147 Ok(Err(error)) => Err(error),
148 Err(error) => Err(RespondError::SaveFailed(SessionSaveError::StorageError(
149 error.to_string(),
150 ))),
151 }
152 }
153}