1use std::fmt::Display;
4
5use crate::{
6 database::transactions::Transaction,
7 direct_access::repository_factory,
8 entities::Root,
9 event::{DirectAccessEntity, EntityEvent, Event, EventBuffer, Origin},
10 snapshot::{EntityTreeSnapshot, TableLevelSnapshot},
11 types::EntityId,
12};
13
14use crate::error::RepositoryError;
15use serde::{Deserialize, Serialize};
16
17#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
18pub enum RootRelationshipField {
19 Document,
20}
21
22impl Display for RootRelationshipField {
23 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
24 write!(f, "{:?}", self)
25 }
26}
27
28pub trait RootTable {
29 fn create(&mut self, entity: &Root) -> Result<Root, RepositoryError>;
30 fn create_multi(&mut self, entities: &[Root]) -> Result<Vec<Root>, RepositoryError>;
31 fn get(&self, id: &EntityId) -> Result<Option<Root>, RepositoryError>;
32 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Root>>, RepositoryError>;
33 fn get_all(&self) -> Result<Vec<Root>, RepositoryError>;
34 fn update(&mut self, entity: &Root) -> Result<Root, RepositoryError>;
35 fn update_multi(&mut self, entities: &[Root]) -> Result<Vec<Root>, RepositoryError>;
36 fn update_with_relationships(&mut self, entity: &Root) -> Result<Root, RepositoryError>;
37 fn update_with_relationships_multi(
38 &mut self,
39 entities: &[Root],
40 ) -> Result<Vec<Root>, RepositoryError>;
41 fn remove(&mut self, id: &EntityId) -> Result<(), RepositoryError>;
42 fn remove_multi(&mut self, ids: &[EntityId]) -> Result<(), RepositoryError>;
43 fn get_relationship(
44 &self,
45 id: &EntityId,
46 field: &RootRelationshipField,
47 ) -> Result<Vec<EntityId>, RepositoryError>;
48 fn get_relationship_many(
49 &self,
50 ids: &[EntityId],
51 field: &RootRelationshipField,
52 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
53 fn get_relationship_count(
54 &self,
55 id: &EntityId,
56 field: &RootRelationshipField,
57 ) -> Result<usize, RepositoryError>;
58 fn get_relationship_in_range(
59 &self,
60 id: &EntityId,
61 field: &RootRelationshipField,
62 offset: usize,
63 limit: usize,
64 ) -> Result<Vec<EntityId>, RepositoryError>;
65 fn get_relationships_from_right_ids(
66 &self,
67 field: &RootRelationshipField,
68 right_ids: &[EntityId],
69 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
70 fn set_relationship_multi(
71 &mut self,
72 field: &RootRelationshipField,
73 relationships: Vec<(EntityId, Vec<EntityId>)>,
74 ) -> Result<(), RepositoryError>;
75 fn set_relationship(
76 &mut self,
77 id: &EntityId,
78 field: &RootRelationshipField,
79 right_ids: &[EntityId],
80 ) -> Result<(), RepositoryError>;
81 fn move_relationship_ids(
82 &mut self,
83 id: &EntityId,
84 field: &RootRelationshipField,
85 ids_to_move: &[EntityId],
86 new_index: i32,
87 ) -> Result<Vec<EntityId>, RepositoryError>;
88 fn snapshot_rows(&self, ids: &[EntityId]) -> Result<TableLevelSnapshot, RepositoryError>;
89 fn restore_rows(&mut self, snap: &TableLevelSnapshot) -> Result<(), RepositoryError>;
90}
91
92pub trait RootTableRO {
93 fn get(&self, id: &EntityId) -> Result<Option<Root>, RepositoryError>;
94 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Root>>, RepositoryError>;
95 fn get_all(&self) -> Result<Vec<Root>, RepositoryError>;
96 fn get_relationship(
97 &self,
98 id: &EntityId,
99 field: &RootRelationshipField,
100 ) -> Result<Vec<EntityId>, RepositoryError>;
101 fn get_relationship_many(
102 &self,
103 ids: &[EntityId],
104 field: &RootRelationshipField,
105 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
106 fn get_relationship_count(
107 &self,
108 id: &EntityId,
109 field: &RootRelationshipField,
110 ) -> Result<usize, RepositoryError>;
111 fn get_relationship_in_range(
112 &self,
113 id: &EntityId,
114 field: &RootRelationshipField,
115 offset: usize,
116 limit: usize,
117 ) -> Result<Vec<EntityId>, RepositoryError>;
118 fn get_relationships_from_right_ids(
119 &self,
120 field: &RootRelationshipField,
121 right_ids: &[EntityId],
122 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
123}
124
125pub struct RootRepository<'a> {
126 redb_table: Box<dyn RootTable + 'a>,
127 transaction: &'a Transaction,
128}
129
130impl<'a> RootRepository<'a> {
131 pub fn new(redb_table: Box<dyn RootTable + 'a>, transaction: &'a Transaction) -> Self {
132 RootRepository {
133 redb_table,
134 transaction,
135 }
136 }
137
138 pub fn create_orphan(
139 &mut self,
140 event_buffer: &mut EventBuffer,
141 entity: &Root,
142 ) -> Result<Root, RepositoryError> {
143 let new = self.redb_table.create(entity)?;
144 event_buffer.push(Event {
145 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Created)),
146 ids: vec![new.id],
147 data: None,
148 });
149 Ok(new)
150 }
151
152 pub fn create_orphan_multi(
153 &mut self,
154 event_buffer: &mut EventBuffer,
155 entities: &[Root],
156 ) -> Result<Vec<Root>, RepositoryError> {
157 let new_entities = self.redb_table.create_multi(entities)?;
158 event_buffer.push(Event {
159 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Created)),
160 ids: new_entities.iter().map(|e| e.id).collect(),
161 data: None,
162 });
163 Ok(new_entities)
164 }
165
166 pub fn get(&self, id: &EntityId) -> Result<Option<Root>, RepositoryError> {
167 self.redb_table.get(id)
168 }
169 pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Root>>, RepositoryError> {
170 self.redb_table.get_multi(ids)
171 }
172 pub fn get_all(&self) -> Result<Vec<Root>, RepositoryError> {
173 self.redb_table.get_all()
174 }
175
176 pub fn update(
177 &mut self,
178 event_buffer: &mut EventBuffer,
179 entity: &Root,
180 ) -> Result<Root, RepositoryError> {
181 let updated = self.redb_table.update(entity)?;
182 event_buffer.push(Event {
183 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
184 ids: vec![updated.id],
185 data: None,
186 });
187 Ok(updated)
188 }
189
190 pub fn update_multi(
191 &mut self,
192 event_buffer: &mut EventBuffer,
193 entities: &[Root],
194 ) -> Result<Vec<Root>, RepositoryError> {
195 let updated = self.redb_table.update_multi(entities)?;
196 event_buffer.push(Event {
197 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
198 ids: updated.iter().map(|e| e.id).collect(),
199 data: None,
200 });
201 Ok(updated)
202 }
203
204 pub fn update_with_relationships(
205 &mut self,
206 event_buffer: &mut EventBuffer,
207 entity: &Root,
208 ) -> Result<Root, RepositoryError> {
209 let updated = self.redb_table.update_with_relationships(entity)?;
210 event_buffer.push(Event {
211 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
212 ids: vec![updated.id],
213 data: None,
214 });
215 Ok(updated)
216 }
217
218 pub fn update_with_relationships_multi(
219 &mut self,
220 event_buffer: &mut EventBuffer,
221 entities: &[Root],
222 ) -> Result<Vec<Root>, RepositoryError> {
223 let updated = self.redb_table.update_with_relationships_multi(entities)?;
224 event_buffer.push(Event {
225 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
226 ids: updated.iter().map(|e| e.id).collect(),
227 data: None,
228 });
229 Ok(updated)
230 }
231
232 pub fn remove(
233 &mut self,
234 event_buffer: &mut EventBuffer,
235 id: &EntityId,
236 ) -> Result<(), RepositoryError> {
237 let entity = match self.redb_table.get(id)? {
238 Some(e) => e,
239 None => return Ok(()),
240 };
241 let document = entity.document;
244
245 repository_factory::write::create_document_repository(self.transaction)
248 .remove(event_buffer, &document)?;
249
250 self.redb_table.remove(id)?;
252 event_buffer.push(Event {
253 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Removed)),
254 ids: vec![*id],
255 data: None,
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 document_ids: Vec<EntityId> = entities
274 .iter()
275 .filter_map(|entity| entity.as_ref().map(|entity| entity.document))
276 .collect();
277
278 repository_factory::write::create_document_repository(self.transaction)
281 .remove_multi(event_buffer, &document_ids)?;
282
283 self.redb_table.remove_multi(ids)?;
284 event_buffer.push(Event {
285 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Removed)),
286 ids: ids.into(),
287 data: None,
288 });
289
290 Ok(())
291 }
292 pub fn get_relationship(
293 &self,
294 id: &EntityId,
295 field: &RootRelationshipField,
296 ) -> Result<Vec<EntityId>, RepositoryError> {
297 self.redb_table.get_relationship(id, field)
298 }
299 pub fn get_relationship_many(
300 &self,
301 ids: &[EntityId],
302 field: &RootRelationshipField,
303 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
304 self.redb_table.get_relationship_many(ids, field)
305 }
306 pub fn get_relationship_count(
307 &self,
308 id: &EntityId,
309 field: &RootRelationshipField,
310 ) -> Result<usize, RepositoryError> {
311 self.redb_table.get_relationship_count(id, field)
312 }
313 pub fn get_relationship_in_range(
314 &self,
315 id: &EntityId,
316 field: &RootRelationshipField,
317 offset: usize,
318 limit: usize,
319 ) -> Result<Vec<EntityId>, RepositoryError> {
320 self.redb_table
321 .get_relationship_in_range(id, field, offset, limit)
322 }
323 pub fn get_relationships_from_right_ids(
324 &self,
325 field: &RootRelationshipField,
326 right_ids: &[EntityId],
327 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
328 self.redb_table
329 .get_relationships_from_right_ids(field, right_ids)
330 }
331
332 pub fn set_relationship_multi(
333 &mut self,
334 event_buffer: &mut EventBuffer,
335 field: &RootRelationshipField,
336 relationships: Vec<(EntityId, Vec<EntityId>)>,
337 ) -> Result<(), RepositoryError> {
338 let all_right_ids: Vec<EntityId> = relationships
340 .iter()
341 .flat_map(|(_, ids)| ids.iter().copied())
342 .collect();
343 if !all_right_ids.is_empty() {
344 match field {
345 RootRelationshipField::Document => {
346 let child_repo =
347 repository_factory::write::create_document_repository(self.transaction);
348 let found = child_repo.get_multi(&all_right_ids)?;
349 let missing: Vec<_> = all_right_ids
350 .iter()
351 .zip(found.iter())
352 .filter(|(_, entity)| entity.is_none())
353 .map(|(id, _)| *id)
354 .collect();
355 if !missing.is_empty() {
356 return Err(RepositoryError::MissingRelationshipTarget {
357 operation: "set_relationship_multi",
358 ids: missing,
359 });
360 }
361 }
362 }
363 }
364 self.redb_table
365 .set_relationship_multi(field, relationships.clone())?;
366 for (left_id, right_ids) in relationships {
367 event_buffer.push(Event {
368 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
369 ids: vec![left_id],
370 data: Some(format!(
371 "{}:{}",
372 field,
373 right_ids
374 .iter()
375 .map(|id| id.to_string())
376 .collect::<Vec<_>>()
377 .join(",")
378 )),
379 });
380 }
381 Ok(())
382 }
383
384 pub fn set_relationship(
385 &mut self,
386 event_buffer: &mut EventBuffer,
387 id: &EntityId,
388 field: &RootRelationshipField,
389 right_ids: &[EntityId],
390 ) -> Result<(), RepositoryError> {
391 if !right_ids.is_empty() {
393 match field {
394 RootRelationshipField::Document => {
395 let child_repo =
396 repository_factory::write::create_document_repository(self.transaction);
397 let found = child_repo.get_multi(right_ids)?;
398 let missing: Vec<_> = right_ids
399 .iter()
400 .zip(found.iter())
401 .filter(|(_, entity)| entity.is_none())
402 .map(|(id, _)| *id)
403 .collect();
404 if !missing.is_empty() {
405 return Err(RepositoryError::MissingRelationshipTarget {
406 operation: "set_relationship",
407 ids: missing,
408 });
409 }
410 }
411 }
412 }
413 self.redb_table.set_relationship(id, field, right_ids)?;
414 event_buffer.push(Event {
415 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
416 ids: vec![*id],
417 data: Some(format!(
418 "{}:{}",
419 field,
420 right_ids
421 .iter()
422 .map(|id| id.to_string())
423 .collect::<Vec<_>>()
424 .join(",")
425 )),
426 });
427 Ok(())
428 }
429
430 pub fn move_relationship_ids(
431 &mut self,
432 event_buffer: &mut EventBuffer,
433 id: &EntityId,
434 field: &RootRelationshipField,
435 ids_to_move: &[EntityId],
436 new_index: i32,
437 ) -> Result<Vec<EntityId>, RepositoryError> {
438 let reordered = self
439 .redb_table
440 .move_relationship_ids(id, field, ids_to_move, new_index)?;
441 event_buffer.push(Event {
442 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
443 ids: vec![*id],
444 data: Some(format!(
445 "{}:{}",
446 field,
447 reordered
448 .iter()
449 .map(|id| id.to_string())
450 .collect::<Vec<_>>()
451 .join(",")
452 )),
453 });
454 Ok(reordered)
455 }
456
457 pub fn snapshot(&self, ids: &[EntityId]) -> Result<EntityTreeSnapshot, RepositoryError> {
458 let table_data = self.redb_table.snapshot_rows(ids)?;
459
460 #[allow(unused_mut)]
462 let mut children = Vec::new();
463
464 {
465 let junction_name = "document_from_root_document_junction";
467 let child_ids: Vec<EntityId> = table_data
468 .forward_junctions
469 .iter()
470 .filter(|j| j.table_name == junction_name)
471 .flat_map(|j| {
472 j.entries
473 .iter()
474 .flat_map(|(_, right_ids)| right_ids.iter().copied())
475 })
476 .collect();
477 if !child_ids.is_empty() {
478 let child_repo =
479 repository_factory::write::create_document_repository(self.transaction);
480 children.push(child_repo.snapshot(&child_ids)?);
481 }
482 }
483
484 Ok(EntityTreeSnapshot {
485 table_data,
486 children,
487 })
488 }
489
490 pub fn restore(
491 &mut self,
492 event_buffer: &mut EventBuffer,
493 snap: &EntityTreeSnapshot,
494 ) -> Result<(), RepositoryError> {
495 for child_snap in &snap.children {
498 if child_snap.table_data.entity_rows.table_name == "document" {
499 repository_factory::write::create_document_repository(self.transaction)
500 .restore(event_buffer, child_snap)?;
501 }
502 }
503
504 self.redb_table.restore_rows(&snap.table_data)?;
506
507 let restored_ids: Vec<EntityId> = snap
509 .table_data
510 .entity_rows
511 .rows
512 .iter()
513 .map(|(id, _)| *id)
514 .collect();
515 if !restored_ids.is_empty() {
516 event_buffer.push(Event {
517 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Created)),
518 ids: restored_ids.clone(),
519 data: None,
520 });
521 }
522 if !restored_ids.is_empty() {
524 event_buffer.push(Event {
525 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
526 ids: restored_ids,
527 data: None,
528 });
529 }
530 Ok(())
531 }
532}
533
534pub struct RootRepositoryRO<'a> {
535 redb_table: Box<dyn RootTableRO + 'a>,
536}
537impl<'a> RootRepositoryRO<'a> {
538 pub fn new(redb_table: Box<dyn RootTableRO + 'a>) -> Self {
539 RootRepositoryRO { redb_table }
540 }
541 pub fn get(&self, id: &EntityId) -> Result<Option<Root>, RepositoryError> {
542 self.redb_table.get(id)
543 }
544 pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Root>>, RepositoryError> {
545 self.redb_table.get_multi(ids)
546 }
547 pub fn get_all(&self) -> Result<Vec<Root>, RepositoryError> {
548 self.redb_table.get_all()
549 }
550 pub fn get_relationship(
551 &self,
552 id: &EntityId,
553 field: &RootRelationshipField,
554 ) -> Result<Vec<EntityId>, RepositoryError> {
555 self.redb_table.get_relationship(id, field)
556 }
557 pub fn get_relationship_many(
558 &self,
559 ids: &[EntityId],
560 field: &RootRelationshipField,
561 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
562 self.redb_table.get_relationship_many(ids, field)
563 }
564 pub fn get_relationship_count(
565 &self,
566 id: &EntityId,
567 field: &RootRelationshipField,
568 ) -> Result<usize, RepositoryError> {
569 self.redb_table.get_relationship_count(id, field)
570 }
571 pub fn get_relationship_in_range(
572 &self,
573 id: &EntityId,
574 field: &RootRelationshipField,
575 offset: usize,
576 limit: usize,
577 ) -> Result<Vec<EntityId>, RepositoryError> {
578 self.redb_table
579 .get_relationship_in_range(id, field, offset, limit)
580 }
581 pub fn get_relationships_from_right_ids(
582 &self,
583 field: &RootRelationshipField,
584 right_ids: &[EntityId],
585 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
586 self.redb_table
587 .get_relationships_from_right_ids(field, right_ids)
588 }
589}