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, TableLevelSnapshot},
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 fn snapshot_rows(&self, ids: &[EntityId]) -> Result<TableLevelSnapshot, RepositoryError>;
44 fn restore_rows(&mut self, snap: &TableLevelSnapshot) -> Result<(), RepositoryError>;
45}
46
47pub trait ResourceTableRO {
48 fn get(&self, id: &EntityId) -> Result<Option<Resource>, RepositoryError>;
49 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Resource>>, RepositoryError>;
50 fn get_all(&self) -> Result<Vec<Resource>, RepositoryError>;
51}
52
53pub struct ResourceRepository<'a> {
54 redb_table: Box<dyn ResourceTable + 'a>,
55 transaction: &'a Transaction,
56}
57
58impl<'a> ResourceRepository<'a> {
59 pub fn new(redb_table: Box<dyn ResourceTable + 'a>, transaction: &'a Transaction) -> Self {
60 ResourceRepository {
61 redb_table,
62 transaction,
63 }
64 }
65
66 pub fn create_orphan(
67 &mut self,
68 event_buffer: &mut EventBuffer,
69 entity: &Resource,
70 ) -> Result<Resource, RepositoryError> {
71 let new = self.redb_table.create(entity)?;
72 event_buffer.push(Event {
73 origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Created)),
74 ids: vec![new.id],
75 data: None,
76 });
77 Ok(new)
78 }
79
80 pub fn create_orphan_multi(
81 &mut self,
82 event_buffer: &mut EventBuffer,
83 entities: &[Resource],
84 ) -> Result<Vec<Resource>, RepositoryError> {
85 let new_entities = self.redb_table.create_multi(entities)?;
86 event_buffer.push(Event {
87 origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Created)),
88 ids: new_entities.iter().map(|e| e.id).collect(),
89 data: None,
90 });
91 Ok(new_entities)
92 }
93 pub fn create(
94 &mut self,
95 event_buffer: &mut EventBuffer,
96 entity: &Resource,
97 owner_id: EntityId,
98 index: i32,
99 ) -> Result<Resource, RepositoryError> {
100 let new = self.redb_table.create(entity)?;
101 let created_id = new.id;
102
103 let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
104 if index >= 0 && (index as usize) < relationship_ids.len() {
106 relationship_ids.insert(index as usize, created_id);
107 } else {
108 relationship_ids.push(created_id);
109 }
110
111 self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
112 event_buffer.push(Event {
113 origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Created)),
114 ids: vec![created_id],
115 data: None,
116 });
117 Ok(new)
118 }
119
120 pub fn create_multi(
121 &mut self,
122 event_buffer: &mut EventBuffer,
123 entities: &[Resource],
124 owner_id: EntityId,
125 index: i32,
126 ) -> Result<Vec<Resource>, RepositoryError> {
127 let new_entities = self.redb_table.create_multi(entities)?;
128 let created_ids: Vec<EntityId> = new_entities.iter().map(|e| e.id).collect();
129
130 let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
131 if index >= 0 && (index as usize) < relationship_ids.len() {
132 for (i, id) in created_ids.iter().enumerate() {
133 relationship_ids.insert(index as usize + i, *id);
134 }
135 } else {
136 relationship_ids.extend(created_ids.iter());
137 }
138
139 self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
140 event_buffer.push(Event {
141 origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Created)),
142 ids: created_ids,
143 data: None,
144 });
145 Ok(new_entities)
146 }
147
148 pub fn get(&self, id: &EntityId) -> Result<Option<Resource>, RepositoryError> {
149 self.redb_table.get(id)
150 }
151 pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Resource>>, RepositoryError> {
152 self.redb_table.get_multi(ids)
153 }
154 pub fn get_all(&self) -> Result<Vec<Resource>, RepositoryError> {
155 self.redb_table.get_all()
156 }
157
158 pub fn update(
159 &mut self,
160 event_buffer: &mut EventBuffer,
161 entity: &Resource,
162 ) -> Result<Resource, RepositoryError> {
163 let updated = self.redb_table.update(entity)?;
164 event_buffer.push(Event {
165 origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Updated)),
166 ids: vec![updated.id],
167 data: None,
168 });
169 Ok(updated)
170 }
171
172 pub fn update_multi(
173 &mut self,
174 event_buffer: &mut EventBuffer,
175 entities: &[Resource],
176 ) -> Result<Vec<Resource>, RepositoryError> {
177 let updated = self.redb_table.update_multi(entities)?;
178 event_buffer.push(Event {
179 origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Updated)),
180 ids: updated.iter().map(|e| e.id).collect(),
181 data: None,
182 });
183 Ok(updated)
184 }
185
186 pub fn update_with_relationships(
187 &mut self,
188 event_buffer: &mut EventBuffer,
189 entity: &Resource,
190 ) -> Result<Resource, RepositoryError> {
191 let updated = self.redb_table.update_with_relationships(entity)?;
192 event_buffer.push(Event {
193 origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Updated)),
194 ids: vec![updated.id],
195 data: None,
196 });
197 Ok(updated)
198 }
199
200 pub fn update_with_relationships_multi(
201 &mut self,
202 event_buffer: &mut EventBuffer,
203 entities: &[Resource],
204 ) -> Result<Vec<Resource>, RepositoryError> {
205 let updated = self.redb_table.update_with_relationships_multi(entities)?;
206 event_buffer.push(Event {
207 origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Updated)),
208 ids: updated.iter().map(|e| e.id).collect(),
209 data: None,
210 });
211 Ok(updated)
212 }
213
214 pub fn remove(
215 &mut self,
216 event_buffer: &mut EventBuffer,
217 id: &EntityId,
218 ) -> Result<(), RepositoryError> {
219 let _entity = match self.redb_table.get(id)? {
220 Some(e) => e,
221 None => return Ok(()),
222 };
223 let affected_owner_ids: Vec<EntityId> = {
229 let owner_repo =
230 repository_factory::write::create_document_repository(self.transaction);
231 owner_repo
232 .get_relationships_from_right_ids(&DocumentRelationshipField::Resources, &[*id])?
233 .into_iter()
234 .map(|(owner_id, _)| owner_id)
235 .collect()
236 };
237 let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
239 std::collections::HashMap::new();
240 for owner_id in &affected_owner_ids {
241 owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
242 }
243
244 self.redb_table.remove(id)?;
246 event_buffer.push(Event {
247 origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Removed)),
248 ids: vec![*id],
249 data: None,
250 });
251 for owner_id in &affected_owner_ids {
253 if let Some(rel_ids) = owner_rel_before.get(owner_id) {
254 let updated: Vec<EntityId> =
255 rel_ids.iter().copied().filter(|rid| *rid != *id).collect();
256 self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
257 }
258 }
259
260 Ok(())
261 }
262
263 pub fn remove_multi(
264 &mut self,
265 event_buffer: &mut EventBuffer,
266 ids: &[EntityId],
267 ) -> Result<(), RepositoryError> {
268 let entities = self.redb_table.get_multi(ids)?;
269 if entities.is_empty() || entities.iter().all(|e| e.is_none()) {
270 return Ok(());
271 }
272
273 let affected_owner_ids: Vec<EntityId> = {
279 let owner_repo =
280 repository_factory::write::create_document_repository(self.transaction);
281 owner_repo
282 .get_relationships_from_right_ids(&DocumentRelationshipField::Resources, ids)?
283 .into_iter()
284 .map(|(owner_id, _)| owner_id)
285 .collect()
286 };
287 let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
289 std::collections::HashMap::new();
290 for owner_id in &affected_owner_ids {
291 owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
292 }
293
294 self.redb_table.remove_multi(ids)?;
295 event_buffer.push(Event {
296 origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Removed)),
297 ids: ids.into(),
298 data: None,
299 });
300 {
302 let removed_set: std::collections::HashSet<EntityId> = ids.iter().copied().collect();
303 for owner_id in &affected_owner_ids {
304 if let Some(rel_ids) = owner_rel_before.get(owner_id) {
305 let updated: Vec<EntityId> = rel_ids
306 .iter()
307 .copied()
308 .filter(|rid| !removed_set.contains(rid))
309 .collect();
310 self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
311 }
312 }
313 }
314
315 Ok(())
316 }
317 pub fn get_relationships_from_owner(
318 &self,
319 owner_id: &EntityId,
320 ) -> Result<Vec<EntityId>, RepositoryError> {
321 let repo = repository_factory::write::create_document_repository(self.transaction);
322 repo.get_relationship(owner_id, &DocumentRelationshipField::Resources)
323 }
324
325 pub fn set_relationships_in_owner(
326 &mut self,
327 event_buffer: &mut EventBuffer,
328 owner_id: &EntityId,
329 ids: &[EntityId],
330 ) -> Result<(), RepositoryError> {
331 let mut repo = repository_factory::write::create_document_repository(self.transaction);
332 repo.set_relationship(
333 event_buffer,
334 owner_id,
335 &DocumentRelationshipField::Resources,
336 ids,
337 )
338 }
339
340 pub fn snapshot(&self, ids: &[EntityId]) -> Result<EntityTreeSnapshot, RepositoryError> {
341 let table_data = self.redb_table.snapshot_rows(ids)?;
342
343 #[allow(unused_mut)]
345 let mut children = Vec::new();
346
347 Ok(EntityTreeSnapshot {
348 table_data,
349 children,
350 })
351 }
352
353 pub fn restore(
354 &mut self,
355 event_buffer: &mut EventBuffer,
356 snap: &EntityTreeSnapshot,
357 ) -> Result<(), RepositoryError> {
358 self.redb_table.restore_rows(&snap.table_data)?;
362
363 let restored_ids: Vec<EntityId> = snap
365 .table_data
366 .entity_rows
367 .rows
368 .iter()
369 .map(|(id, _)| *id)
370 .collect();
371 if !restored_ids.is_empty() {
372 event_buffer.push(Event {
373 origin: Origin::DirectAccess(DirectAccessEntity::Resource(EntityEvent::Created)),
374 ids: restored_ids.clone(),
375 data: None,
376 });
377 }
378 Ok(())
379 }
380}
381
382pub struct ResourceRepositoryRO<'a> {
383 redb_table: Box<dyn ResourceTableRO + 'a>,
384}
385impl<'a> ResourceRepositoryRO<'a> {
386 pub fn new(redb_table: Box<dyn ResourceTableRO + 'a>) -> Self {
387 ResourceRepositoryRO { redb_table }
388 }
389 pub fn get(&self, id: &EntityId) -> Result<Option<Resource>, RepositoryError> {
390 self.redb_table.get(id)
391 }
392 pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Resource>>, RepositoryError> {
393 self.redb_table.get_multi(ids)
394 }
395 pub fn get_all(&self) -> Result<Vec<Resource>, RepositoryError> {
396 self.redb_table.get_all()
397 }
398}