1use std::fmt::Display;
4
5use crate::{
6 database::transactions::Transaction,
7 direct_access::repository_factory,
8 entities::Resource,
9 event::{DirectAccessEntity, EntityEvent, Event, EventBuffer, Origin},
10 snapshot::EntityTreeSnapshot,
11 types::EntityId,
12};
13
14use crate::direct_access::document::DocumentRelationshipField;
15use crate::error::RepositoryError;
16use serde::{Deserialize, Serialize};
17
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
19pub enum ResourceRelationshipField {}
20
21impl Display for ResourceRelationshipField {
22 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
23 write!(f, "{:?}", self)
24 }
25}
26
27pub trait ResourceTable {
28 fn create(&mut self, entity: &Resource) -> Result<Resource, RepositoryError>;
29 fn create_multi(&mut self, entities: &[Resource]) -> Result<Vec<Resource>, RepositoryError>;
30 fn get(&self, id: &EntityId) -> Result<Option<Resource>, RepositoryError>;
31 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Resource>>, RepositoryError>;
32 fn get_all(&self) -> Result<Vec<Resource>, RepositoryError>;
33 fn update(&mut self, entity: &Resource) -> Result<Resource, RepositoryError>;
34 fn update_multi(&mut self, entities: &[Resource]) -> Result<Vec<Resource>, RepositoryError>;
35 fn update_with_relationships(&mut self, entity: &Resource)
36 -> Result<Resource, RepositoryError>;
37 fn update_with_relationships_multi(
38 &mut self,
39 entities: &[Resource],
40 ) -> Result<Vec<Resource>, RepositoryError>;
41 fn remove(&mut self, id: &EntityId) -> Result<(), RepositoryError>;
42 fn remove_multi(&mut self, ids: &[EntityId]) -> Result<(), RepositoryError>;
43}
44
45pub trait ResourceTableRO {
46 fn get(&self, id: &EntityId) -> Result<Option<Resource>, RepositoryError>;
47 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Resource>>, RepositoryError>;
48 fn get_all(&self) -> Result<Vec<Resource>, RepositoryError>;
49}
50
51pub struct ResourceRepository<'a> {
52 redb_table: Box<dyn ResourceTable + 'a>,
53 transaction: &'a Transaction,
54}
55
56impl<'a> ResourceRepository<'a> {
57 pub fn new(redb_table: Box<dyn ResourceTable + 'a>, transaction: &'a Transaction) -> Self {
58 ResourceRepository {
59 redb_table,
60 transaction,
61 }
62 }
63
64 pub fn create_orphan(
65 &mut self,
66 event_buffer: &mut EventBuffer,
67 entity: &Resource,
68 ) -> Result<Resource, RepositoryError> {
69 let new = self.redb_table.create(entity)?;
70 event_buffer.push(Event {
71 origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Created)),
72 ids: vec![new.id],
73 data: None,
74 });
75 Ok(new)
76 }
77
78 pub fn create_orphan_multi(
79 &mut self,
80 event_buffer: &mut EventBuffer,
81 entities: &[Resource],
82 ) -> Result<Vec<Resource>, RepositoryError> {
83 let new_entities = self.redb_table.create_multi(entities)?;
84 event_buffer.push(Event {
85 origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Created)),
86 ids: new_entities.iter().map(|e| e.id).collect(),
87 data: None,
88 });
89 Ok(new_entities)
90 }
91 pub fn create(
92 &mut self,
93 event_buffer: &mut EventBuffer,
94 entity: &Resource,
95 owner_id: EntityId,
96 index: i32,
97 ) -> Result<Resource, RepositoryError> {
98 let new = self.redb_table.create(entity)?;
99 let created_id = new.id;
100
101 let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
102 if index >= 0 && (index as usize) < relationship_ids.len() {
104 relationship_ids.insert(index as usize, created_id);
105 } else {
106 relationship_ids.push(created_id);
107 }
108
109 self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
110 event_buffer.push(Event {
111 origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Created)),
112 ids: vec![created_id],
113 data: None,
114 });
115 Ok(new)
116 }
117
118 pub fn create_multi(
119 &mut self,
120 event_buffer: &mut EventBuffer,
121 entities: &[Resource],
122 owner_id: EntityId,
123 index: i32,
124 ) -> Result<Vec<Resource>, RepositoryError> {
125 let new_entities = self.redb_table.create_multi(entities)?;
126 let created_ids: Vec<EntityId> = new_entities.iter().map(|e| e.id).collect();
127
128 let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
129 if index >= 0 && (index as usize) < relationship_ids.len() {
130 for (i, id) in created_ids.iter().enumerate() {
131 relationship_ids.insert(index as usize + i, *id);
132 }
133 } else {
134 relationship_ids.extend(created_ids.iter());
135 }
136
137 self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
138 event_buffer.push(Event {
139 origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Created)),
140 ids: created_ids,
141 data: None,
142 });
143 Ok(new_entities)
144 }
145
146 pub fn get(&self, id: &EntityId) -> Result<Option<Resource>, RepositoryError> {
147 self.redb_table.get(id)
148 }
149 pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Resource>>, RepositoryError> {
150 self.redb_table.get_multi(ids)
151 }
152 pub fn get_all(&self) -> Result<Vec<Resource>, RepositoryError> {
153 self.redb_table.get_all()
154 }
155
156 pub fn update(
157 &mut self,
158 event_buffer: &mut EventBuffer,
159 entity: &Resource,
160 ) -> Result<Resource, RepositoryError> {
161 let updated = self.redb_table.update(entity)?;
162 event_buffer.push(Event {
163 origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Updated)),
164 ids: vec![updated.id],
165 data: None,
166 });
167 Ok(updated)
168 }
169
170 pub fn update_multi(
171 &mut self,
172 event_buffer: &mut EventBuffer,
173 entities: &[Resource],
174 ) -> Result<Vec<Resource>, RepositoryError> {
175 let updated = self.redb_table.update_multi(entities)?;
176 event_buffer.push(Event {
177 origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Updated)),
178 ids: updated.iter().map(|e| e.id).collect(),
179 data: None,
180 });
181 Ok(updated)
182 }
183
184 pub fn update_with_relationships(
185 &mut self,
186 event_buffer: &mut EventBuffer,
187 entity: &Resource,
188 ) -> Result<Resource, RepositoryError> {
189 let updated = self.redb_table.update_with_relationships(entity)?;
190 event_buffer.push(Event {
191 origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Updated)),
192 ids: vec![updated.id],
193 data: None,
194 });
195 Ok(updated)
196 }
197
198 pub fn update_with_relationships_multi(
199 &mut self,
200 event_buffer: &mut EventBuffer,
201 entities: &[Resource],
202 ) -> Result<Vec<Resource>, RepositoryError> {
203 let updated = self.redb_table.update_with_relationships_multi(entities)?;
204 event_buffer.push(Event {
205 origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Updated)),
206 ids: updated.iter().map(|e| e.id).collect(),
207 data: None,
208 });
209 Ok(updated)
210 }
211
212 pub fn remove(
213 &mut self,
214 event_buffer: &mut EventBuffer,
215 id: &EntityId,
216 ) -> Result<(), RepositoryError> {
217 let _entity = match self.redb_table.get(id)? {
218 Some(e) => e,
219 None => return Ok(()),
220 };
221 let affected_owner_ids: Vec<EntityId> = {
227 let owner_repo =
228 repository_factory::write::create_document_repository(self.transaction);
229 owner_repo
230 .get_relationships_from_right_ids(&DocumentRelationshipField::Resources, &[*id])?
231 .into_iter()
232 .map(|(owner_id, _)| owner_id)
233 .collect()
234 };
235 let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
237 std::collections::HashMap::new();
238 for owner_id in &affected_owner_ids {
239 owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
240 }
241
242 self.redb_table.remove(id)?;
244 event_buffer.push(Event {
245 origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Removed)),
246 ids: vec![*id],
247 data: None,
248 });
249 for owner_id in &affected_owner_ids {
251 if let Some(rel_ids) = owner_rel_before.get(owner_id) {
252 let updated: Vec<EntityId> =
253 rel_ids.iter().copied().filter(|rid| *rid != *id).collect();
254 self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
255 }
256 }
257
258 Ok(())
259 }
260
261 pub fn remove_multi(
262 &mut self,
263 event_buffer: &mut EventBuffer,
264 ids: &[EntityId],
265 ) -> Result<(), RepositoryError> {
266 let entities = self.redb_table.get_multi(ids)?;
267 if entities.is_empty() || entities.iter().all(|e| e.is_none()) {
268 return Ok(());
269 }
270
271 let affected_owner_ids: Vec<EntityId> = {
277 let owner_repo =
278 repository_factory::write::create_document_repository(self.transaction);
279 owner_repo
280 .get_relationships_from_right_ids(&DocumentRelationshipField::Resources, ids)?
281 .into_iter()
282 .map(|(owner_id, _)| owner_id)
283 .collect()
284 };
285 let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
287 std::collections::HashMap::new();
288 for owner_id in &affected_owner_ids {
289 owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
290 }
291
292 self.redb_table.remove_multi(ids)?;
293 event_buffer.push(Event {
294 origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Removed)),
295 ids: ids.into(),
296 data: None,
297 });
298 {
300 let removed_set: std::collections::HashSet<EntityId> = ids.iter().copied().collect();
301 for owner_id in &affected_owner_ids {
302 if let Some(rel_ids) = owner_rel_before.get(owner_id) {
303 let updated: Vec<EntityId> = rel_ids
304 .iter()
305 .copied()
306 .filter(|rid| !removed_set.contains(rid))
307 .collect();
308 self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
309 }
310 }
311 }
312
313 Ok(())
314 }
315 pub fn get_relationships_from_owner(
316 &self,
317 owner_id: &EntityId,
318 ) -> Result<Vec<EntityId>, RepositoryError> {
319 let repo = repository_factory::write::create_document_repository(self.transaction);
320 repo.get_relationship(owner_id, &DocumentRelationshipField::Resources)
321 }
322
323 pub fn set_relationships_in_owner(
324 &mut self,
325 event_buffer: &mut EventBuffer,
326 owner_id: &EntityId,
327 ids: &[EntityId],
328 ) -> Result<(), RepositoryError> {
329 let mut repo = repository_factory::write::create_document_repository(self.transaction);
330 repo.set_relationship(
331 event_buffer,
332 owner_id,
333 &DocumentRelationshipField::Resources,
334 ids,
335 )
336 }
337
338 pub fn snapshot(&self, _ids: &[EntityId]) -> Result<EntityTreeSnapshot, RepositoryError> {
339 let store_snap = self.transaction.snapshot_store();
340 Ok(EntityTreeSnapshot {
341 store_snapshot: Some(store_snap),
342 })
343 }
344
345 pub fn restore(
346 &mut self,
347 event_buffer: &mut EventBuffer,
348 snap: &EntityTreeSnapshot,
349 ) -> Result<(), RepositoryError> {
350 let store_snap = snap
351 .store_snapshot
352 .as_ref()
353 .ok_or_else(|| RepositoryError::Serialization("missing store snapshot".into()))?;
354 self.transaction.restore_store(store_snap);
355
356 let store = self.transaction.get_store();
357
358 let res_ids: Vec<_> = store.resources.read().unwrap().keys().copied().collect();
360 if !res_ids.is_empty() {
361 event_buffer.push(Event {
362 origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Created)),
363 ids: res_ids,
364 data: None,
365 });
366 }
367
368 Ok(())
369 }
370}
371
372pub struct ResourceRepositoryRO<'a> {
373 redb_table: Box<dyn ResourceTableRO + 'a>,
374}
375impl<'a> ResourceRepositoryRO<'a> {
376 pub fn new(redb_table: Box<dyn ResourceTableRO + 'a>) -> Self {
377 ResourceRepositoryRO { redb_table }
378 }
379 pub fn get(&self, id: &EntityId) -> Result<Option<Resource>, RepositoryError> {
380 self.redb_table.get(id)
381 }
382 pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Resource>>, RepositoryError> {
383 self.redb_table.get_multi(ids)
384 }
385 pub fn get_all(&self) -> Result<Vec<Resource>, RepositoryError> {
386 self.redb_table.get_all()
387 }
388}