1use std::fmt::Display;
4
5use crate::{
6 database::hashmap_store::HashMapStoreSnapshot,
7 database::hashmap_store::{read_or_recover, write_or_recover},
13 database::transactions::Transaction,
14 direct_access::repository_factory,
15 entities::Entity,
16 event::{DirectAccessEntity, EntityEvent, Event, EventBuffer, Origin},
17 snapshot::EntityTreeSnapshot,
18 types::EntityId,
19};
20
21use crate::direct_access::workspace::WorkspaceRelationshipField;
22use crate::error::RepositoryError;
23use serde::{Deserialize, Serialize};
24
25#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
26pub enum EntityRelationshipField {
27 Fields,
28 InheritsFrom,
29 Relationships,
30}
31
32impl Display for EntityRelationshipField {
33 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
34 write!(f, "{:?}", self)
35 }
36}
37
38pub trait EntityTable {
39 fn create(&mut self, entity: &Entity) -> Result<Entity, RepositoryError>;
40 fn create_multi(&mut self, entities: &[Entity]) -> Result<Vec<Entity>, RepositoryError>;
41 fn get(&self, id: &EntityId) -> Result<Option<Entity>, RepositoryError>;
42 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Entity>>, RepositoryError>;
43 fn get_all(&self) -> Result<Vec<Entity>, RepositoryError>;
44 fn update(&mut self, entity: &Entity) -> Result<Entity, RepositoryError>;
45 fn update_multi(&mut self, entities: &[Entity]) -> Result<Vec<Entity>, RepositoryError>;
46 fn update_with_relationships(&mut self, entity: &Entity) -> Result<Entity, RepositoryError>;
47 fn update_with_relationships_multi(
48 &mut self,
49 entities: &[Entity],
50 ) -> Result<Vec<Entity>, RepositoryError>;
51 fn remove(&mut self, id: &EntityId) -> Result<(), RepositoryError>;
52 fn remove_multi(&mut self, ids: &[EntityId]) -> Result<(), RepositoryError>;
53 fn get_relationship(
54 &self,
55 id: &EntityId,
56 field: &EntityRelationshipField,
57 ) -> Result<Vec<EntityId>, RepositoryError>;
58 fn get_relationship_many(
59 &self,
60 ids: &[EntityId],
61 field: &EntityRelationshipField,
62 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
63 fn get_relationship_count(
64 &self,
65 id: &EntityId,
66 field: &EntityRelationshipField,
67 ) -> Result<usize, RepositoryError>;
68 fn get_relationship_in_range(
69 &self,
70 id: &EntityId,
71 field: &EntityRelationshipField,
72 offset: usize,
73 limit: usize,
74 ) -> Result<Vec<EntityId>, RepositoryError>;
75 fn get_relationships_from_right_ids(
76 &self,
77 field: &EntityRelationshipField,
78 right_ids: &[EntityId],
79 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
80 fn set_relationship_multi(
81 &mut self,
82 field: &EntityRelationshipField,
83 relationships: Vec<(EntityId, Vec<EntityId>)>,
84 ) -> Result<(), RepositoryError>;
85 fn set_relationship(
86 &mut self,
87 id: &EntityId,
88 field: &EntityRelationshipField,
89 right_ids: &[EntityId],
90 ) -> Result<(), RepositoryError>;
91 fn move_relationship_ids(
92 &mut self,
93 id: &EntityId,
94 field: &EntityRelationshipField,
95 ids_to_move: &[EntityId],
96 new_index: i32,
97 ) -> Result<Vec<EntityId>, RepositoryError>;
98}
99
100pub trait EntityTableRO {
101 fn get(&self, id: &EntityId) -> Result<Option<Entity>, RepositoryError>;
102 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Entity>>, RepositoryError>;
103 fn get_all(&self) -> Result<Vec<Entity>, RepositoryError>;
104 fn get_relationship(
105 &self,
106 id: &EntityId,
107 field: &EntityRelationshipField,
108 ) -> Result<Vec<EntityId>, RepositoryError>;
109 fn get_relationship_many(
110 &self,
111 ids: &[EntityId],
112 field: &EntityRelationshipField,
113 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
114 fn get_relationship_count(
115 &self,
116 id: &EntityId,
117 field: &EntityRelationshipField,
118 ) -> Result<usize, RepositoryError>;
119 fn get_relationship_in_range(
120 &self,
121 id: &EntityId,
122 field: &EntityRelationshipField,
123 offset: usize,
124 limit: usize,
125 ) -> Result<Vec<EntityId>, RepositoryError>;
126 fn get_relationships_from_right_ids(
127 &self,
128 field: &EntityRelationshipField,
129 right_ids: &[EntityId],
130 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
131}
132
133pub struct EntityRepository<'a> {
134 table: Box<dyn EntityTable + 'a>,
135 transaction: &'a Transaction,
136}
137
138impl<'a> EntityRepository<'a> {
139 pub fn new(table: Box<dyn EntityTable + 'a>, transaction: &'a Transaction) -> Self {
140 EntityRepository { table, transaction }
141 }
142
143 pub fn create_orphan(
144 &mut self,
145 event_buffer: &mut EventBuffer,
146 entity: &Entity,
147 ) -> Result<Entity, RepositoryError> {
148 let new = self.table.create(entity)?;
149 event_buffer.push(Event {
150 origin: Origin::DirectAccess(DirectAccessEntity::Entity(EntityEvent::Created)),
151 ids: vec![new.id],
152 data: None,
153 });
154 Ok(new)
155 }
156
157 pub fn create_orphan_multi(
158 &mut self,
159 event_buffer: &mut EventBuffer,
160 entities: &[Entity],
161 ) -> Result<Vec<Entity>, RepositoryError> {
162 let new_entities = self.table.create_multi(entities)?;
163 event_buffer.push(Event {
164 origin: Origin::DirectAccess(DirectAccessEntity::Entity(EntityEvent::Created)),
165 ids: new_entities.iter().map(|e| e.id).collect(),
166 data: None,
167 });
168 Ok(new_entities)
169 }
170 pub fn create(
171 &mut self,
172 event_buffer: &mut EventBuffer,
173 entity: &Entity,
174 owner_id: EntityId,
175 index: i32,
176 ) -> Result<Entity, RepositoryError> {
177 let new = self.table.create(entity)?;
178 let created_id = new.id;
179
180 let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
181 if index >= 0 && (index as usize) < relationship_ids.len() {
183 relationship_ids.insert(index as usize, created_id);
184 } else {
185 relationship_ids.push(created_id);
186 }
187
188 self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
189 event_buffer.push(Event {
190 origin: Origin::DirectAccess(DirectAccessEntity::Entity(EntityEvent::Created)),
191 ids: vec![created_id],
192 data: None,
193 });
194 Ok(new)
195 }
196
197 pub fn create_multi(
198 &mut self,
199 event_buffer: &mut EventBuffer,
200 entities: &[Entity],
201 owner_id: EntityId,
202 index: i32,
203 ) -> Result<Vec<Entity>, RepositoryError> {
204 let new_entities = self.table.create_multi(entities)?;
205 let created_ids: Vec<EntityId> = new_entities.iter().map(|e| e.id).collect();
206
207 let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
208 if index >= 0 && (index as usize) < relationship_ids.len() {
209 for (i, id) in created_ids.iter().enumerate() {
210 relationship_ids.insert(index as usize + i, *id);
211 }
212 } else {
213 relationship_ids.extend(created_ids.iter());
214 }
215
216 self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
217 event_buffer.push(Event {
218 origin: Origin::DirectAccess(DirectAccessEntity::Entity(EntityEvent::Created)),
219 ids: created_ids,
220 data: None,
221 });
222 Ok(new_entities)
223 }
224
225 pub fn get(&self, id: &EntityId) -> Result<Option<Entity>, RepositoryError> {
226 self.table.get(id)
227 }
228 pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Entity>>, RepositoryError> {
229 self.table.get_multi(ids)
230 }
231 pub fn get_all(&self) -> Result<Vec<Entity>, RepositoryError> {
232 self.table.get_all()
233 }
234
235 pub fn update(
236 &mut self,
237 event_buffer: &mut EventBuffer,
238 entity: &Entity,
239 ) -> Result<Entity, RepositoryError> {
240 let updated = self.table.update(entity)?;
241 event_buffer.push(Event {
242 origin: Origin::DirectAccess(DirectAccessEntity::Entity(EntityEvent::Updated)),
243 ids: vec![updated.id],
244 data: None,
245 });
246 Ok(updated)
247 }
248
249 pub fn update_multi(
250 &mut self,
251 event_buffer: &mut EventBuffer,
252 entities: &[Entity],
253 ) -> Result<Vec<Entity>, RepositoryError> {
254 let updated = self.table.update_multi(entities)?;
255 event_buffer.push(Event {
256 origin: Origin::DirectAccess(DirectAccessEntity::Entity(EntityEvent::Updated)),
257 ids: updated.iter().map(|e| e.id).collect(),
258 data: None,
259 });
260 Ok(updated)
261 }
262
263 pub fn update_with_relationships(
264 &mut self,
265 event_buffer: &mut EventBuffer,
266 entity: &Entity,
267 ) -> Result<Entity, RepositoryError> {
268 let updated = self.table.update_with_relationships(entity)?;
269 event_buffer.push(Event {
270 origin: Origin::DirectAccess(DirectAccessEntity::Entity(EntityEvent::Updated)),
271 ids: vec![updated.id],
272 data: None,
273 });
274 Ok(updated)
275 }
276
277 pub fn update_with_relationships_multi(
278 &mut self,
279 event_buffer: &mut EventBuffer,
280 entities: &[Entity],
281 ) -> Result<Vec<Entity>, RepositoryError> {
282 let updated = self.table.update_with_relationships_multi(entities)?;
283 event_buffer.push(Event {
284 origin: Origin::DirectAccess(DirectAccessEntity::Entity(EntityEvent::Updated)),
285 ids: updated.iter().map(|e| e.id).collect(),
286 data: None,
287 });
288 Ok(updated)
289 }
290
291 pub fn remove(
292 &mut self,
293 event_buffer: &mut EventBuffer,
294 id: &EntityId,
295 ) -> Result<(), RepositoryError> {
296 let entity = match self.table.get(id)? {
297 Some(e) => e,
298 None => return Ok(()),
299 };
300 let fields = entity.fields.clone();
303 let relationships = entity.relationships.clone();
304
305 repository_factory::write::create_field_repository(self.transaction)?
308 .remove_multi(event_buffer, &fields)?;
309 repository_factory::write::create_relationship_repository(self.transaction)?
310 .remove_multi(event_buffer, &relationships)?;
311 let affected_owner_ids: Vec<EntityId> = {
313 let owner_repo =
314 repository_factory::write::create_workspace_repository(self.transaction)?;
315 owner_repo
316 .get_relationships_from_right_ids(&WorkspaceRelationshipField::Entities, &[*id])?
317 .into_iter()
318 .map(|(owner_id, _)| owner_id)
319 .collect()
320 };
321 let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
323 std::collections::HashMap::new();
324 for owner_id in &affected_owner_ids {
325 owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
326 }
327
328 self.table.remove(id)?;
330 event_buffer.push(Event {
331 origin: Origin::DirectAccess(DirectAccessEntity::Entity(EntityEvent::Removed)),
332 ids: vec![*id],
333 data: None,
334 });
335 for owner_id in &affected_owner_ids {
337 if let Some(rel_ids) = owner_rel_before.get(owner_id) {
338 let updated: Vec<EntityId> =
339 rel_ids.iter().copied().filter(|rid| *rid != *id).collect();
340 self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
341 }
342 }
343
344 Ok(())
345 }
346
347 pub fn remove_multi(
348 &mut self,
349 event_buffer: &mut EventBuffer,
350 ids: &[EntityId],
351 ) -> Result<(), RepositoryError> {
352 let entities = self.table.get_multi(ids)?;
353 if entities.is_empty() || entities.iter().all(|e| e.is_none()) {
354 return Ok(());
355 }
356
357 let mut fields_ids: Vec<EntityId> = entities
360 .iter()
361 .flat_map(|entity| entity.as_ref().map(|entity| entity.fields.clone()))
362 .flatten()
363 .collect();
364 fields_ids.sort();
366 fields_ids.dedup();
367 let mut relationships_ids: Vec<EntityId> = entities
368 .iter()
369 .flat_map(|entity| entity.as_ref().map(|entity| entity.relationships.clone()))
370 .flatten()
371 .collect();
372 relationships_ids.sort();
374 relationships_ids.dedup();
375
376 repository_factory::write::create_field_repository(self.transaction)?
379 .remove_multi(event_buffer, &fields_ids)?;
380 repository_factory::write::create_relationship_repository(self.transaction)?
381 .remove_multi(event_buffer, &relationships_ids)?;
382 let affected_owner_ids: Vec<EntityId> = {
384 let owner_repo =
385 repository_factory::write::create_workspace_repository(self.transaction)?;
386 owner_repo
387 .get_relationships_from_right_ids(&WorkspaceRelationshipField::Entities, ids)?
388 .into_iter()
389 .map(|(owner_id, _)| owner_id)
390 .collect()
391 };
392 let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
394 std::collections::HashMap::new();
395 for owner_id in &affected_owner_ids {
396 owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
397 }
398
399 self.table.remove_multi(ids)?;
400 event_buffer.push(Event {
401 origin: Origin::DirectAccess(DirectAccessEntity::Entity(EntityEvent::Removed)),
402 ids: ids.into(),
403 data: None,
404 });
405 {
407 let removed_set: std::collections::HashSet<EntityId> = ids.iter().copied().collect();
408 for owner_id in &affected_owner_ids {
409 if let Some(rel_ids) = owner_rel_before.get(owner_id) {
410 let updated: Vec<EntityId> = rel_ids
411 .iter()
412 .copied()
413 .filter(|rid| !removed_set.contains(rid))
414 .collect();
415 self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
416 }
417 }
418 }
419
420 Ok(())
421 }
422 pub fn get_relationship(
423 &self,
424 id: &EntityId,
425 field: &EntityRelationshipField,
426 ) -> Result<Vec<EntityId>, RepositoryError> {
427 self.table.get_relationship(id, field)
428 }
429 pub fn get_relationship_many(
430 &self,
431 ids: &[EntityId],
432 field: &EntityRelationshipField,
433 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
434 self.table.get_relationship_many(ids, field)
435 }
436 pub fn get_relationship_count(
437 &self,
438 id: &EntityId,
439 field: &EntityRelationshipField,
440 ) -> Result<usize, RepositoryError> {
441 self.table.get_relationship_count(id, field)
442 }
443 pub fn get_relationship_in_range(
444 &self,
445 id: &EntityId,
446 field: &EntityRelationshipField,
447 offset: usize,
448 limit: usize,
449 ) -> Result<Vec<EntityId>, RepositoryError> {
450 self.table
451 .get_relationship_in_range(id, field, offset, limit)
452 }
453 pub fn get_relationships_from_right_ids(
454 &self,
455 field: &EntityRelationshipField,
456 right_ids: &[EntityId],
457 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
458 self.table
459 .get_relationships_from_right_ids(field, right_ids)
460 }
461
462 pub fn set_relationship_multi(
463 &mut self,
464 event_buffer: &mut EventBuffer,
465 field: &EntityRelationshipField,
466 relationships: Vec<(EntityId, Vec<EntityId>)>,
467 ) -> Result<(), RepositoryError> {
468 let all_right_ids: Vec<EntityId> = relationships
470 .iter()
471 .flat_map(|(_, ids)| ids.iter().copied())
472 .collect();
473 if !all_right_ids.is_empty() {
474 match field {
475 EntityRelationshipField::Fields => {
476 let child_repo =
477 repository_factory::write::create_field_repository(self.transaction)?;
478 let found = child_repo.get_multi(&all_right_ids)?;
479 let missing: Vec<_> = all_right_ids
480 .iter()
481 .zip(found.iter())
482 .filter(|(_, entity)| entity.is_none())
483 .map(|(id, _)| *id)
484 .collect();
485 if !missing.is_empty() {
486 return Err(RepositoryError::MissingRelationshipTarget {
487 operation: "set_relationship_multi",
488 ids: missing,
489 });
490 }
491 }
492 EntityRelationshipField::InheritsFrom => {
493 let child_repo =
494 repository_factory::write::create_entity_repository(self.transaction)?;
495 let found = child_repo.get_multi(&all_right_ids)?;
496 let missing: Vec<_> = all_right_ids
497 .iter()
498 .zip(found.iter())
499 .filter(|(_, entity)| entity.is_none())
500 .map(|(id, _)| *id)
501 .collect();
502 if !missing.is_empty() {
503 return Err(RepositoryError::MissingRelationshipTarget {
504 operation: "set_relationship_multi",
505 ids: missing,
506 });
507 }
508 }
509 EntityRelationshipField::Relationships => {
510 let child_repo = repository_factory::write::create_relationship_repository(
511 self.transaction,
512 )?;
513 let found = child_repo.get_multi(&all_right_ids)?;
514 let missing: Vec<_> = all_right_ids
515 .iter()
516 .zip(found.iter())
517 .filter(|(_, entity)| entity.is_none())
518 .map(|(id, _)| *id)
519 .collect();
520 if !missing.is_empty() {
521 return Err(RepositoryError::MissingRelationshipTarget {
522 operation: "set_relationship_multi",
523 ids: missing,
524 });
525 }
526 }
527 }
528 }
529 self.table
530 .set_relationship_multi(field, relationships.clone())?;
531 for (left_id, right_ids) in relationships {
532 event_buffer.push(Event {
533 origin: Origin::DirectAccess(DirectAccessEntity::Entity(EntityEvent::Updated)),
534 ids: vec![left_id],
535 data: Some(format!(
536 "{}:{}",
537 field,
538 right_ids
539 .iter()
540 .map(|id| id.to_string())
541 .collect::<Vec<_>>()
542 .join(",")
543 )),
544 });
545 }
546 Ok(())
547 }
548
549 pub fn set_relationship(
550 &mut self,
551 event_buffer: &mut EventBuffer,
552 id: &EntityId,
553 field: &EntityRelationshipField,
554 right_ids: &[EntityId],
555 ) -> Result<(), RepositoryError> {
556 if !right_ids.is_empty() {
558 match field {
559 EntityRelationshipField::Fields => {
560 let child_repo =
561 repository_factory::write::create_field_repository(self.transaction)?;
562 let found = child_repo.get_multi(right_ids)?;
563 let missing: Vec<_> = right_ids
564 .iter()
565 .zip(found.iter())
566 .filter(|(_, entity)| entity.is_none())
567 .map(|(id, _)| *id)
568 .collect();
569 if !missing.is_empty() {
570 return Err(RepositoryError::MissingRelationshipTarget {
571 operation: "set_relationship",
572 ids: missing,
573 });
574 }
575 }
576 EntityRelationshipField::InheritsFrom => {
577 let child_repo =
578 repository_factory::write::create_entity_repository(self.transaction)?;
579 let found = child_repo.get_multi(right_ids)?;
580 let missing: Vec<_> = right_ids
581 .iter()
582 .zip(found.iter())
583 .filter(|(_, entity)| entity.is_none())
584 .map(|(id, _)| *id)
585 .collect();
586 if !missing.is_empty() {
587 return Err(RepositoryError::MissingRelationshipTarget {
588 operation: "set_relationship",
589 ids: missing,
590 });
591 }
592 }
593 EntityRelationshipField::Relationships => {
594 let child_repo = repository_factory::write::create_relationship_repository(
595 self.transaction,
596 )?;
597 let found = child_repo.get_multi(right_ids)?;
598 let missing: Vec<_> = right_ids
599 .iter()
600 .zip(found.iter())
601 .filter(|(_, entity)| entity.is_none())
602 .map(|(id, _)| *id)
603 .collect();
604 if !missing.is_empty() {
605 return Err(RepositoryError::MissingRelationshipTarget {
606 operation: "set_relationship",
607 ids: missing,
608 });
609 }
610 }
611 }
612 }
613 self.table.set_relationship(id, field, right_ids)?;
614 event_buffer.push(Event {
615 origin: Origin::DirectAccess(DirectAccessEntity::Entity(EntityEvent::Updated)),
616 ids: vec![*id],
617 data: Some(format!(
618 "{}:{}",
619 field,
620 right_ids
621 .iter()
622 .map(|id| id.to_string())
623 .collect::<Vec<_>>()
624 .join(",")
625 )),
626 });
627 Ok(())
628 }
629
630 pub fn move_relationship_ids(
631 &mut self,
632 event_buffer: &mut EventBuffer,
633 id: &EntityId,
634 field: &EntityRelationshipField,
635 ids_to_move: &[EntityId],
636 new_index: i32,
637 ) -> Result<Vec<EntityId>, RepositoryError> {
638 let reordered = self
639 .table
640 .move_relationship_ids(id, field, ids_to_move, new_index)?;
641 event_buffer.push(Event {
642 origin: Origin::DirectAccess(DirectAccessEntity::Entity(EntityEvent::Updated)),
643 ids: vec![*id],
644 data: Some(format!(
645 "{}:{}",
646 field,
647 reordered
648 .iter()
649 .map(|id| id.to_string())
650 .collect::<Vec<_>>()
651 .join(",")
652 )),
653 });
654 Ok(reordered)
655 }
656 pub fn get_relationships_from_owner(
657 &self,
658 owner_id: &EntityId,
659 ) -> Result<Vec<EntityId>, RepositoryError> {
660 let repo = repository_factory::write::create_workspace_repository(self.transaction)?;
661 repo.get_relationship(owner_id, &WorkspaceRelationshipField::Entities)
662 }
663
664 pub fn set_relationships_in_owner(
665 &mut self,
666 event_buffer: &mut EventBuffer,
667 owner_id: &EntityId,
668 ids: &[EntityId],
669 ) -> Result<(), RepositoryError> {
670 let mut repo = repository_factory::write::create_workspace_repository(self.transaction)?;
671 repo.set_relationship(
672 event_buffer,
673 owner_id,
674 &WorkspaceRelationshipField::Entities,
675 ids,
676 )
677 }
678
679 pub fn snapshot(&self, ids: &[EntityId]) -> Result<EntityTreeSnapshot, RepositoryError> {
680 let store_snap = self.transaction.snapshot_store();
682 Ok(EntityTreeSnapshot {
683 store_snapshot: Some(store_snap),
684 root_ids: ids.to_vec(),
685 })
686 }
687
688 pub fn restore(
689 &mut self,
690 event_buffer: &mut EventBuffer,
691 snap: &EntityTreeSnapshot,
692 ) -> Result<(), RepositoryError> {
693 let store_snap = snap
694 .store_snapshot
695 .as_ref()
696 .ok_or_else(|| RepositoryError::Serialization("missing store snapshot".into()))?;
697 let snap_store = store_snap
698 .downcast_ref::<HashMapStoreSnapshot>()
699 .ok_or_else(|| RepositoryError::Serialization("snapshot type mismatch".into()))?;
700
701 let mut visited = std::collections::HashSet::new();
704 self.restore_subtree(event_buffer, snap_store, &snap.root_ids, &mut visited)?;
705
706 self.reconcile_backref_workspace_entities(event_buffer, snap_store, &snap.root_ids)?;
709
710 Ok(())
711 }
712
713 pub(crate) fn restore_subtree(
718 &self,
719 event_buffer: &mut EventBuffer,
720 snap: &HashMapStoreSnapshot,
721 ids: &[EntityId],
722 visited: &mut std::collections::HashSet<(&'static str, EntityId)>,
725 ) -> Result<(), RepositoryError> {
726 let ids: Vec<EntityId> = ids
727 .iter()
728 .copied()
729 .filter(|id| visited.insert(("entity", *id)))
730 .collect();
731 if ids.is_empty() {
732 return Ok(());
733 }
734
735 let store = self.transaction.get_store();
736
737 let mut to_create: Vec<EntityId> = Vec::new(); let mut to_update: Vec<EntityId> = Vec::new(); let mut to_delete: Vec<EntityId> = Vec::new(); {
742 let live = read_or_recover(&store.entities);
743 for id in &ids {
744 match (snap.entities.contains_key(id), live.contains_key(id)) {
745 (true, false) => to_create.push(*id),
746 (true, true) => to_update.push(*id),
747 (false, true) => to_delete.push(*id),
748 (false, false) => {}
749 }
750 }
751 }
752
753 {
756 let mut child_ids: Vec<EntityId> = Vec::new();
757 for id in to_create.iter().chain(to_update.iter()) {
758 if let Some(list) = snap.jn_field_from_entity_fields.get(id) {
759 child_ids.extend(list.iter().copied());
760 }
761 }
762 {
763 let live_jn = read_or_recover(&store.jn_field_from_entity_fields);
764 for id in &ids {
765 if let Some(list) = live_jn.get(id) {
766 child_ids.extend(list.iter().copied());
767 }
768 }
769 }
770 child_ids.sort();
771 child_ids.dedup();
772 if !child_ids.is_empty() {
773 repository_factory::write::create_field_repository(self.transaction)?
774 .restore_subtree(event_buffer, snap, &child_ids, visited)?;
775 }
776 }
777 {
778 let mut child_ids: Vec<EntityId> = Vec::new();
779 for id in to_create.iter().chain(to_update.iter()) {
780 if let Some(list) = snap.jn_relationship_from_entity_relationships.get(id) {
781 child_ids.extend(list.iter().copied());
782 }
783 }
784 {
785 let live_jn = read_or_recover(&store.jn_relationship_from_entity_relationships);
786 for id in &ids {
787 if let Some(list) = live_jn.get(id) {
788 child_ids.extend(list.iter().copied());
789 }
790 }
791 }
792 child_ids.sort();
793 child_ids.dedup();
794 if !child_ids.is_empty() {
795 repository_factory::write::create_relationship_repository(self.transaction)?
796 .restore_subtree(event_buffer, snap, &child_ids, visited)?;
797 }
798 }
799
800 {
802 let mut live = write_or_recover(&store.entities);
803 for id in to_create.iter().chain(to_update.iter()) {
804 if let Some(row) = snap.entities.get(id) {
805 live.insert(*id, row.clone());
806 }
807 }
808 for id in &to_delete {
809 live.remove(id);
810 }
811 }
812
813 {
816 let mut live_jn = write_or_recover(&store.jn_field_from_entity_fields);
817 for id in to_create.iter().chain(to_update.iter()) {
818 match snap.jn_field_from_entity_fields.get(id) {
819 Some(v) => {
820 live_jn.insert(*id, v.clone());
821 }
822 None => {
823 live_jn.remove(id);
824 }
825 }
826 }
827 for id in &to_delete {
828 live_jn.remove(id);
829 }
830 }
831 {
832 let mut live_jn = write_or_recover(&store.jn_entity_from_entity_inherits_from);
833 for id in to_create.iter().chain(to_update.iter()) {
834 match snap.jn_entity_from_entity_inherits_from.get(id) {
835 Some(v) => {
836 live_jn.insert(*id, v.clone());
837 }
838 None => {
839 live_jn.remove(id);
840 }
841 }
842 }
843 for id in &to_delete {
844 live_jn.remove(id);
845 }
846 }
847 {
848 let mut live_jn = write_or_recover(&store.jn_relationship_from_entity_relationships);
849 for id in to_create.iter().chain(to_update.iter()) {
850 match snap.jn_relationship_from_entity_relationships.get(id) {
851 Some(v) => {
852 live_jn.insert(*id, v.clone());
853 }
854 None => {
855 live_jn.remove(id);
856 }
857 }
858 }
859 for id in &to_delete {
860 live_jn.remove(id);
861 }
862 }
863
864 self.reconcile_backref_use_case_entities(event_buffer, snap, &ids)?;
866 self.reconcile_backref_field_entity(event_buffer, snap, &ids)?;
867 self.reconcile_backref_file_entity(event_buffer, snap, &ids)?;
868 self.reconcile_backref_entity_inherits_from(event_buffer, snap, &ids)?;
869 self.reconcile_backref_relationship_left_entity(event_buffer, snap, &ids)?;
870 self.reconcile_backref_relationship_right_entity(event_buffer, snap, &ids)?;
871
872 if !to_create.is_empty() {
874 event_buffer.push(Event {
875 origin: Origin::DirectAccess(DirectAccessEntity::Entity(EntityEvent::Created)),
876 ids: to_create.clone(),
877 data: None,
878 });
879 event_buffer.push(Event {
880 origin: Origin::DirectAccess(DirectAccessEntity::Entity(EntityEvent::Updated)),
881 ids: to_create.clone(),
882 data: None,
883 });
884 }
885 if !to_update.is_empty() {
886 event_buffer.push(Event {
887 origin: Origin::DirectAccess(DirectAccessEntity::Entity(EntityEvent::Updated)),
888 ids: to_update.clone(),
889 data: None,
890 });
891 }
892 if !to_delete.is_empty() {
893 event_buffer.push(Event {
894 origin: Origin::DirectAccess(DirectAccessEntity::Entity(EntityEvent::Removed)),
895 ids: to_delete.clone(),
896 data: None,
897 });
898 }
899
900 Ok(())
901 }
902
903 fn reconcile_backref_use_case_entities(
906 &self,
907 event_buffer: &mut EventBuffer,
908 snap: &HashMapStoreSnapshot,
909 scope_ids: &[EntityId],
910 ) -> Result<(), RepositoryError> {
911 let scope: std::collections::HashSet<EntityId> = scope_ids.iter().copied().collect();
912 if scope.is_empty() {
913 return Ok(());
914 }
915 let store = self.transaction.get_store();
916
917 let mut left_keys: std::collections::HashSet<EntityId> = std::collections::HashSet::new();
919 for (left, rights) in snap.jn_entity_from_use_case_entities.iter() {
920 if rights.iter().any(|rid| scope.contains(rid)) {
921 left_keys.insert(*left);
922 }
923 }
924 {
925 let live_jn = read_or_recover(&store.jn_entity_from_use_case_entities);
926 for (left, rights) in live_jn.iter() {
927 if rights.iter().any(|rid| scope.contains(rid)) {
928 left_keys.insert(*left);
929 }
930 }
931 }
932
933 for left in left_keys {
934 let snap_list: Vec<EntityId> = snap
935 .jn_entity_from_use_case_entities
936 .get(&left)
937 .cloned()
938 .unwrap_or_default();
939 let new_list = {
940 let live_jn = read_or_recover(&store.jn_entity_from_use_case_entities);
941 let live_list: Vec<EntityId> = live_jn.get(&left).cloned().unwrap_or_default();
942 let reconciled = crate::database::hashmap_store::reconcile_backref_list(
943 &live_list, &snap_list, &scope,
944 );
945 if reconciled == live_list {
946 None
947 } else {
948 Some(reconciled)
949 }
950 };
951 if let Some(reconciled) = new_list {
952 write_or_recover(&store.jn_entity_from_use_case_entities).insert(left, reconciled);
953 event_buffer.push(Event {
954 origin: Origin::DirectAccess(DirectAccessEntity::UseCase(EntityEvent::Updated)),
955 ids: vec![left],
956 data: None,
957 });
958 }
959 }
960 Ok(())
961 }
962
963 fn reconcile_backref_workspace_entities(
966 &self,
967 event_buffer: &mut EventBuffer,
968 snap: &HashMapStoreSnapshot,
969 scope_ids: &[EntityId],
970 ) -> Result<(), RepositoryError> {
971 let scope: std::collections::HashSet<EntityId> = scope_ids.iter().copied().collect();
972 if scope.is_empty() {
973 return Ok(());
974 }
975 let store = self.transaction.get_store();
976
977 let mut left_keys: std::collections::HashSet<EntityId> = std::collections::HashSet::new();
979 for (left, rights) in snap.jn_entity_from_workspace_entities.iter() {
980 if rights.iter().any(|rid| scope.contains(rid)) {
981 left_keys.insert(*left);
982 }
983 }
984 {
985 let live_jn = read_or_recover(&store.jn_entity_from_workspace_entities);
986 for (left, rights) in live_jn.iter() {
987 if rights.iter().any(|rid| scope.contains(rid)) {
988 left_keys.insert(*left);
989 }
990 }
991 }
992
993 for left in left_keys {
994 let snap_list: Vec<EntityId> = snap
995 .jn_entity_from_workspace_entities
996 .get(&left)
997 .cloned()
998 .unwrap_or_default();
999 let new_list = {
1000 let live_jn = read_or_recover(&store.jn_entity_from_workspace_entities);
1001 let live_list: Vec<EntityId> = live_jn.get(&left).cloned().unwrap_or_default();
1002 let reconciled = crate::database::hashmap_store::reconcile_backref_list(
1003 &live_list, &snap_list, &scope,
1004 );
1005 if reconciled == live_list {
1006 None
1007 } else {
1008 Some(reconciled)
1009 }
1010 };
1011 if let Some(reconciled) = new_list {
1012 write_or_recover(&store.jn_entity_from_workspace_entities).insert(left, reconciled);
1013 event_buffer.push(Event {
1014 origin: Origin::DirectAccess(DirectAccessEntity::Workspace(
1015 EntityEvent::Updated,
1016 )),
1017 ids: vec![left],
1018 data: None,
1019 });
1020 }
1021 }
1022 Ok(())
1023 }
1024
1025 fn reconcile_backref_field_entity(
1028 &self,
1029 event_buffer: &mut EventBuffer,
1030 snap: &HashMapStoreSnapshot,
1031 scope_ids: &[EntityId],
1032 ) -> Result<(), RepositoryError> {
1033 let scope: std::collections::HashSet<EntityId> = scope_ids.iter().copied().collect();
1034 if scope.is_empty() {
1035 return Ok(());
1036 }
1037 let store = self.transaction.get_store();
1038
1039 let mut left_keys: std::collections::HashSet<EntityId> = std::collections::HashSet::new();
1041 for (left, rights) in snap.jn_entity_from_field_entity.iter() {
1042 if rights.iter().any(|rid| scope.contains(rid)) {
1043 left_keys.insert(*left);
1044 }
1045 }
1046 {
1047 let live_jn = read_or_recover(&store.jn_entity_from_field_entity);
1048 for (left, rights) in live_jn.iter() {
1049 if rights.iter().any(|rid| scope.contains(rid)) {
1050 left_keys.insert(*left);
1051 }
1052 }
1053 }
1054
1055 for left in left_keys {
1056 let snap_list: Vec<EntityId> = snap
1057 .jn_entity_from_field_entity
1058 .get(&left)
1059 .cloned()
1060 .unwrap_or_default();
1061 let new_list = {
1062 let live_jn = read_or_recover(&store.jn_entity_from_field_entity);
1063 let live_list: Vec<EntityId> = live_jn.get(&left).cloned().unwrap_or_default();
1064 let reconciled = crate::database::hashmap_store::reconcile_backref_list(
1065 &live_list, &snap_list, &scope,
1066 );
1067 if reconciled == live_list {
1068 None
1069 } else {
1070 Some(reconciled)
1071 }
1072 };
1073 if let Some(reconciled) = new_list {
1074 write_or_recover(&store.jn_entity_from_field_entity).insert(left, reconciled);
1075 event_buffer.push(Event {
1076 origin: Origin::DirectAccess(DirectAccessEntity::Field(EntityEvent::Updated)),
1077 ids: vec![left],
1078 data: None,
1079 });
1080 }
1081 }
1082 Ok(())
1083 }
1084
1085 fn reconcile_backref_file_entity(
1088 &self,
1089 event_buffer: &mut EventBuffer,
1090 snap: &HashMapStoreSnapshot,
1091 scope_ids: &[EntityId],
1092 ) -> Result<(), RepositoryError> {
1093 let scope: std::collections::HashSet<EntityId> = scope_ids.iter().copied().collect();
1094 if scope.is_empty() {
1095 return Ok(());
1096 }
1097 let store = self.transaction.get_store();
1098
1099 let mut left_keys: std::collections::HashSet<EntityId> = std::collections::HashSet::new();
1101 for (left, rights) in snap.jn_entity_from_file_entity.iter() {
1102 if rights.iter().any(|rid| scope.contains(rid)) {
1103 left_keys.insert(*left);
1104 }
1105 }
1106 {
1107 let live_jn = read_or_recover(&store.jn_entity_from_file_entity);
1108 for (left, rights) in live_jn.iter() {
1109 if rights.iter().any(|rid| scope.contains(rid)) {
1110 left_keys.insert(*left);
1111 }
1112 }
1113 }
1114
1115 for left in left_keys {
1116 let snap_list: Vec<EntityId> = snap
1117 .jn_entity_from_file_entity
1118 .get(&left)
1119 .cloned()
1120 .unwrap_or_default();
1121 let new_list = {
1122 let live_jn = read_or_recover(&store.jn_entity_from_file_entity);
1123 let live_list: Vec<EntityId> = live_jn.get(&left).cloned().unwrap_or_default();
1124 let reconciled = crate::database::hashmap_store::reconcile_backref_list(
1125 &live_list, &snap_list, &scope,
1126 );
1127 if reconciled == live_list {
1128 None
1129 } else {
1130 Some(reconciled)
1131 }
1132 };
1133 if let Some(reconciled) = new_list {
1134 write_or_recover(&store.jn_entity_from_file_entity).insert(left, reconciled);
1135 event_buffer.push(Event {
1136 origin: Origin::DirectAccess(DirectAccessEntity::File(EntityEvent::Updated)),
1137 ids: vec![left],
1138 data: None,
1139 });
1140 }
1141 }
1142 Ok(())
1143 }
1144
1145 fn reconcile_backref_entity_inherits_from(
1148 &self,
1149 event_buffer: &mut EventBuffer,
1150 snap: &HashMapStoreSnapshot,
1151 scope_ids: &[EntityId],
1152 ) -> Result<(), RepositoryError> {
1153 let scope: std::collections::HashSet<EntityId> = scope_ids.iter().copied().collect();
1154 if scope.is_empty() {
1155 return Ok(());
1156 }
1157 let store = self.transaction.get_store();
1158
1159 let mut left_keys: std::collections::HashSet<EntityId> = std::collections::HashSet::new();
1161 for (left, rights) in snap.jn_entity_from_entity_inherits_from.iter() {
1162 if rights.iter().any(|rid| scope.contains(rid)) {
1163 left_keys.insert(*left);
1164 }
1165 }
1166 {
1167 let live_jn = read_or_recover(&store.jn_entity_from_entity_inherits_from);
1168 for (left, rights) in live_jn.iter() {
1169 if rights.iter().any(|rid| scope.contains(rid)) {
1170 left_keys.insert(*left);
1171 }
1172 }
1173 }
1174
1175 for left in left_keys {
1176 let snap_list: Vec<EntityId> = snap
1177 .jn_entity_from_entity_inherits_from
1178 .get(&left)
1179 .cloned()
1180 .unwrap_or_default();
1181 let new_list = {
1182 let live_jn = read_or_recover(&store.jn_entity_from_entity_inherits_from);
1183 let live_list: Vec<EntityId> = live_jn.get(&left).cloned().unwrap_or_default();
1184 let reconciled = crate::database::hashmap_store::reconcile_backref_list(
1185 &live_list, &snap_list, &scope,
1186 );
1187 if reconciled == live_list {
1188 None
1189 } else {
1190 Some(reconciled)
1191 }
1192 };
1193 if let Some(reconciled) = new_list {
1194 write_or_recover(&store.jn_entity_from_entity_inherits_from)
1195 .insert(left, reconciled);
1196 event_buffer.push(Event {
1197 origin: Origin::DirectAccess(DirectAccessEntity::Entity(EntityEvent::Updated)),
1198 ids: vec![left],
1199 data: None,
1200 });
1201 }
1202 }
1203 Ok(())
1204 }
1205
1206 fn reconcile_backref_relationship_left_entity(
1209 &self,
1210 event_buffer: &mut EventBuffer,
1211 snap: &HashMapStoreSnapshot,
1212 scope_ids: &[EntityId],
1213 ) -> Result<(), RepositoryError> {
1214 let scope: std::collections::HashSet<EntityId> = scope_ids.iter().copied().collect();
1215 if scope.is_empty() {
1216 return Ok(());
1217 }
1218 let store = self.transaction.get_store();
1219
1220 let mut left_keys: std::collections::HashSet<EntityId> = std::collections::HashSet::new();
1222 for (left, rights) in snap.jn_entity_from_relationship_left_entity.iter() {
1223 if rights.iter().any(|rid| scope.contains(rid)) {
1224 left_keys.insert(*left);
1225 }
1226 }
1227 {
1228 let live_jn = read_or_recover(&store.jn_entity_from_relationship_left_entity);
1229 for (left, rights) in live_jn.iter() {
1230 if rights.iter().any(|rid| scope.contains(rid)) {
1231 left_keys.insert(*left);
1232 }
1233 }
1234 }
1235
1236 for left in left_keys {
1237 let snap_list: Vec<EntityId> = snap
1238 .jn_entity_from_relationship_left_entity
1239 .get(&left)
1240 .cloned()
1241 .unwrap_or_default();
1242 let new_list = {
1243 let live_jn = read_or_recover(&store.jn_entity_from_relationship_left_entity);
1244 let live_list: Vec<EntityId> = live_jn.get(&left).cloned().unwrap_or_default();
1245 let reconciled = crate::database::hashmap_store::reconcile_backref_list(
1246 &live_list, &snap_list, &scope,
1247 );
1248 if reconciled == live_list {
1249 None
1250 } else {
1251 Some(reconciled)
1252 }
1253 };
1254 if let Some(reconciled) = new_list {
1255 write_or_recover(&store.jn_entity_from_relationship_left_entity)
1256 .insert(left, reconciled);
1257 event_buffer.push(Event {
1258 origin: Origin::DirectAccess(DirectAccessEntity::Relationship(
1259 EntityEvent::Updated,
1260 )),
1261 ids: vec![left],
1262 data: None,
1263 });
1264 }
1265 }
1266 Ok(())
1267 }
1268
1269 fn reconcile_backref_relationship_right_entity(
1272 &self,
1273 event_buffer: &mut EventBuffer,
1274 snap: &HashMapStoreSnapshot,
1275 scope_ids: &[EntityId],
1276 ) -> Result<(), RepositoryError> {
1277 let scope: std::collections::HashSet<EntityId> = scope_ids.iter().copied().collect();
1278 if scope.is_empty() {
1279 return Ok(());
1280 }
1281 let store = self.transaction.get_store();
1282
1283 let mut left_keys: std::collections::HashSet<EntityId> = std::collections::HashSet::new();
1285 for (left, rights) in snap.jn_entity_from_relationship_right_entity.iter() {
1286 if rights.iter().any(|rid| scope.contains(rid)) {
1287 left_keys.insert(*left);
1288 }
1289 }
1290 {
1291 let live_jn = read_or_recover(&store.jn_entity_from_relationship_right_entity);
1292 for (left, rights) in live_jn.iter() {
1293 if rights.iter().any(|rid| scope.contains(rid)) {
1294 left_keys.insert(*left);
1295 }
1296 }
1297 }
1298
1299 for left in left_keys {
1300 let snap_list: Vec<EntityId> = snap
1301 .jn_entity_from_relationship_right_entity
1302 .get(&left)
1303 .cloned()
1304 .unwrap_or_default();
1305 let new_list = {
1306 let live_jn = read_or_recover(&store.jn_entity_from_relationship_right_entity);
1307 let live_list: Vec<EntityId> = live_jn.get(&left).cloned().unwrap_or_default();
1308 let reconciled = crate::database::hashmap_store::reconcile_backref_list(
1309 &live_list, &snap_list, &scope,
1310 );
1311 if reconciled == live_list {
1312 None
1313 } else {
1314 Some(reconciled)
1315 }
1316 };
1317 if let Some(reconciled) = new_list {
1318 write_or_recover(&store.jn_entity_from_relationship_right_entity)
1319 .insert(left, reconciled);
1320 event_buffer.push(Event {
1321 origin: Origin::DirectAccess(DirectAccessEntity::Relationship(
1322 EntityEvent::Updated,
1323 )),
1324 ids: vec![left],
1325 data: None,
1326 });
1327 }
1328 }
1329 Ok(())
1330 }
1331}
1332
1333pub struct EntityRepositoryRO<'a> {
1334 table: Box<dyn EntityTableRO + 'a>,
1335}
1336impl<'a> EntityRepositoryRO<'a> {
1337 pub fn new(table: Box<dyn EntityTableRO + 'a>) -> Self {
1338 EntityRepositoryRO { table }
1339 }
1340 pub fn get(&self, id: &EntityId) -> Result<Option<Entity>, RepositoryError> {
1341 self.table.get(id)
1342 }
1343 pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Entity>>, RepositoryError> {
1344 self.table.get_multi(ids)
1345 }
1346 pub fn get_all(&self) -> Result<Vec<Entity>, RepositoryError> {
1347 self.table.get_all()
1348 }
1349 pub fn get_relationship(
1350 &self,
1351 id: &EntityId,
1352 field: &EntityRelationshipField,
1353 ) -> Result<Vec<EntityId>, RepositoryError> {
1354 self.table.get_relationship(id, field)
1355 }
1356 pub fn get_relationship_many(
1357 &self,
1358 ids: &[EntityId],
1359 field: &EntityRelationshipField,
1360 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
1361 self.table.get_relationship_many(ids, field)
1362 }
1363 pub fn get_relationship_count(
1364 &self,
1365 id: &EntityId,
1366 field: &EntityRelationshipField,
1367 ) -> Result<usize, RepositoryError> {
1368 self.table.get_relationship_count(id, field)
1369 }
1370 pub fn get_relationship_in_range(
1371 &self,
1372 id: &EntityId,
1373 field: &EntityRelationshipField,
1374 offset: usize,
1375 limit: usize,
1376 ) -> Result<Vec<EntityId>, RepositoryError> {
1377 self.table
1378 .get_relationship_in_range(id, field, offset, limit)
1379 }
1380 pub fn get_relationships_from_right_ids(
1381 &self,
1382 field: &EntityRelationshipField,
1383 right_ids: &[EntityId],
1384 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
1385 self.table
1386 .get_relationships_from_right_ids(field, right_ids)
1387 }
1388}