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::File,
16 event::{DirectAccessEntity, EntityEvent, Event, EventBuffer, Origin},
17 snapshot::EntityTreeSnapshot,
18 types::EntityId,
19};
20
21use crate::direct_access::system::SystemRelationshipField;
22use crate::error::RepositoryError;
23use serde::{Deserialize, Serialize};
24
25#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
26pub enum FileRelationshipField {
27 Entity,
28 Feature,
29 Field,
30 UseCase,
31}
32
33impl Display for FileRelationshipField {
34 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
35 write!(f, "{:?}", self)
36 }
37}
38
39pub trait FileTable {
40 fn create(&mut self, entity: &File) -> Result<File, RepositoryError>;
41 fn create_multi(&mut self, entities: &[File]) -> Result<Vec<File>, RepositoryError>;
42 fn get(&self, id: &EntityId) -> Result<Option<File>, RepositoryError>;
43 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<File>>, RepositoryError>;
44 fn get_all(&self) -> Result<Vec<File>, RepositoryError>;
45 fn update(&mut self, entity: &File) -> Result<File, RepositoryError>;
46 fn update_multi(&mut self, entities: &[File]) -> Result<Vec<File>, RepositoryError>;
47 fn update_with_relationships(&mut self, entity: &File) -> Result<File, RepositoryError>;
48 fn update_with_relationships_multi(
49 &mut self,
50 entities: &[File],
51 ) -> Result<Vec<File>, RepositoryError>;
52 fn remove(&mut self, id: &EntityId) -> Result<(), RepositoryError>;
53 fn remove_multi(&mut self, ids: &[EntityId]) -> Result<(), RepositoryError>;
54 fn get_relationship(
55 &self,
56 id: &EntityId,
57 field: &FileRelationshipField,
58 ) -> Result<Vec<EntityId>, RepositoryError>;
59 fn get_relationship_many(
60 &self,
61 ids: &[EntityId],
62 field: &FileRelationshipField,
63 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
64 fn get_relationship_count(
65 &self,
66 id: &EntityId,
67 field: &FileRelationshipField,
68 ) -> Result<usize, RepositoryError>;
69 fn get_relationship_in_range(
70 &self,
71 id: &EntityId,
72 field: &FileRelationshipField,
73 offset: usize,
74 limit: usize,
75 ) -> Result<Vec<EntityId>, RepositoryError>;
76 fn get_relationships_from_right_ids(
77 &self,
78 field: &FileRelationshipField,
79 right_ids: &[EntityId],
80 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
81 fn set_relationship_multi(
82 &mut self,
83 field: &FileRelationshipField,
84 relationships: Vec<(EntityId, Vec<EntityId>)>,
85 ) -> Result<(), RepositoryError>;
86 fn set_relationship(
87 &mut self,
88 id: &EntityId,
89 field: &FileRelationshipField,
90 right_ids: &[EntityId],
91 ) -> Result<(), RepositoryError>;
92 fn move_relationship_ids(
93 &mut self,
94 id: &EntityId,
95 field: &FileRelationshipField,
96 ids_to_move: &[EntityId],
97 new_index: i32,
98 ) -> Result<Vec<EntityId>, RepositoryError>;
99}
100
101pub trait FileTableRO {
102 fn get(&self, id: &EntityId) -> Result<Option<File>, RepositoryError>;
103 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<File>>, RepositoryError>;
104 fn get_all(&self) -> Result<Vec<File>, RepositoryError>;
105 fn get_relationship(
106 &self,
107 id: &EntityId,
108 field: &FileRelationshipField,
109 ) -> Result<Vec<EntityId>, RepositoryError>;
110 fn get_relationship_many(
111 &self,
112 ids: &[EntityId],
113 field: &FileRelationshipField,
114 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
115 fn get_relationship_count(
116 &self,
117 id: &EntityId,
118 field: &FileRelationshipField,
119 ) -> Result<usize, RepositoryError>;
120 fn get_relationship_in_range(
121 &self,
122 id: &EntityId,
123 field: &FileRelationshipField,
124 offset: usize,
125 limit: usize,
126 ) -> Result<Vec<EntityId>, RepositoryError>;
127 fn get_relationships_from_right_ids(
128 &self,
129 field: &FileRelationshipField,
130 right_ids: &[EntityId],
131 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
132}
133
134pub struct FileRepository<'a> {
135 table: Box<dyn FileTable + 'a>,
136 transaction: &'a Transaction,
137}
138
139impl<'a> FileRepository<'a> {
140 pub fn new(table: Box<dyn FileTable + 'a>, transaction: &'a Transaction) -> Self {
141 FileRepository { table, transaction }
142 }
143
144 pub fn create_orphan(
145 &mut self,
146 event_buffer: &mut EventBuffer,
147 entity: &File,
148 ) -> Result<File, RepositoryError> {
149 let new = self.table.create(entity)?;
150 event_buffer.push(Event {
151 origin: Origin::DirectAccess(DirectAccessEntity::File(EntityEvent::Created)),
152 ids: vec![new.id],
153 data: None,
154 });
155 Ok(new)
156 }
157
158 pub fn create_orphan_multi(
159 &mut self,
160 event_buffer: &mut EventBuffer,
161 entities: &[File],
162 ) -> Result<Vec<File>, RepositoryError> {
163 let new_entities = self.table.create_multi(entities)?;
164 event_buffer.push(Event {
165 origin: Origin::DirectAccess(DirectAccessEntity::File(EntityEvent::Created)),
166 ids: new_entities.iter().map(|e| e.id).collect(),
167 data: None,
168 });
169 Ok(new_entities)
170 }
171 pub fn create(
172 &mut self,
173 event_buffer: &mut EventBuffer,
174 entity: &File,
175 owner_id: EntityId,
176 index: i32,
177 ) -> Result<File, RepositoryError> {
178 let new = self.table.create(entity)?;
179 let created_id = new.id;
180
181 let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
182 if index >= 0 && (index as usize) < relationship_ids.len() {
184 relationship_ids.insert(index as usize, created_id);
185 } else {
186 relationship_ids.push(created_id);
187 }
188
189 self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
190 event_buffer.push(Event {
191 origin: Origin::DirectAccess(DirectAccessEntity::File(EntityEvent::Created)),
192 ids: vec![created_id],
193 data: None,
194 });
195 Ok(new)
196 }
197
198 pub fn create_multi(
199 &mut self,
200 event_buffer: &mut EventBuffer,
201 entities: &[File],
202 owner_id: EntityId,
203 index: i32,
204 ) -> Result<Vec<File>, RepositoryError> {
205 let new_entities = self.table.create_multi(entities)?;
206 let created_ids: Vec<EntityId> = new_entities.iter().map(|e| e.id).collect();
207
208 let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
209 if index >= 0 && (index as usize) < relationship_ids.len() {
210 for (i, id) in created_ids.iter().enumerate() {
211 relationship_ids.insert(index as usize + i, *id);
212 }
213 } else {
214 relationship_ids.extend(created_ids.iter());
215 }
216
217 self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
218 event_buffer.push(Event {
219 origin: Origin::DirectAccess(DirectAccessEntity::File(EntityEvent::Created)),
220 ids: created_ids,
221 data: None,
222 });
223 Ok(new_entities)
224 }
225
226 pub fn get(&self, id: &EntityId) -> Result<Option<File>, RepositoryError> {
227 self.table.get(id)
228 }
229 pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<File>>, RepositoryError> {
230 self.table.get_multi(ids)
231 }
232 pub fn get_all(&self) -> Result<Vec<File>, RepositoryError> {
233 self.table.get_all()
234 }
235
236 pub fn update(
237 &mut self,
238 event_buffer: &mut EventBuffer,
239 entity: &File,
240 ) -> Result<File, RepositoryError> {
241 let updated = self.table.update(entity)?;
242 event_buffer.push(Event {
243 origin: Origin::DirectAccess(DirectAccessEntity::File(EntityEvent::Updated)),
244 ids: vec![updated.id],
245 data: None,
246 });
247 Ok(updated)
248 }
249
250 pub fn update_multi(
251 &mut self,
252 event_buffer: &mut EventBuffer,
253 entities: &[File],
254 ) -> Result<Vec<File>, RepositoryError> {
255 let updated = self.table.update_multi(entities)?;
256 event_buffer.push(Event {
257 origin: Origin::DirectAccess(DirectAccessEntity::File(EntityEvent::Updated)),
258 ids: updated.iter().map(|e| e.id).collect(),
259 data: None,
260 });
261 Ok(updated)
262 }
263
264 pub fn update_with_relationships(
265 &mut self,
266 event_buffer: &mut EventBuffer,
267 entity: &File,
268 ) -> Result<File, RepositoryError> {
269 let updated = self.table.update_with_relationships(entity)?;
270 event_buffer.push(Event {
271 origin: Origin::DirectAccess(DirectAccessEntity::File(EntityEvent::Updated)),
272 ids: vec![updated.id],
273 data: None,
274 });
275 Ok(updated)
276 }
277
278 pub fn update_with_relationships_multi(
279 &mut self,
280 event_buffer: &mut EventBuffer,
281 entities: &[File],
282 ) -> Result<Vec<File>, RepositoryError> {
283 let updated = self.table.update_with_relationships_multi(entities)?;
284 event_buffer.push(Event {
285 origin: Origin::DirectAccess(DirectAccessEntity::File(EntityEvent::Updated)),
286 ids: updated.iter().map(|e| e.id).collect(),
287 data: None,
288 });
289 Ok(updated)
290 }
291
292 pub fn remove(
293 &mut self,
294 event_buffer: &mut EventBuffer,
295 id: &EntityId,
296 ) -> Result<(), RepositoryError> {
297 let _entity = match self.table.get(id)? {
298 Some(e) => e,
299 None => return Ok(()),
300 };
301 let affected_owner_ids: Vec<EntityId> = {
307 let owner_repo = repository_factory::write::create_system_repository(self.transaction)?;
308 owner_repo
309 .get_relationships_from_right_ids(&SystemRelationshipField::Files, &[*id])?
310 .into_iter()
311 .map(|(owner_id, _)| owner_id)
312 .collect()
313 };
314 let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
316 std::collections::HashMap::new();
317 for owner_id in &affected_owner_ids {
318 owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
319 }
320
321 self.table.remove(id)?;
323 event_buffer.push(Event {
324 origin: Origin::DirectAccess(DirectAccessEntity::File(EntityEvent::Removed)),
325 ids: vec![*id],
326 data: None,
327 });
328 for owner_id in &affected_owner_ids {
330 if let Some(rel_ids) = owner_rel_before.get(owner_id) {
331 let updated: Vec<EntityId> =
332 rel_ids.iter().copied().filter(|rid| *rid != *id).collect();
333 self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
334 }
335 }
336
337 Ok(())
338 }
339
340 pub fn remove_multi(
341 &mut self,
342 event_buffer: &mut EventBuffer,
343 ids: &[EntityId],
344 ) -> Result<(), RepositoryError> {
345 let entities = self.table.get_multi(ids)?;
346 if entities.is_empty() || entities.iter().all(|e| e.is_none()) {
347 return Ok(());
348 }
349
350 let affected_owner_ids: Vec<EntityId> = {
356 let owner_repo = repository_factory::write::create_system_repository(self.transaction)?;
357 owner_repo
358 .get_relationships_from_right_ids(&SystemRelationshipField::Files, ids)?
359 .into_iter()
360 .map(|(owner_id, _)| owner_id)
361 .collect()
362 };
363 let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
365 std::collections::HashMap::new();
366 for owner_id in &affected_owner_ids {
367 owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
368 }
369
370 self.table.remove_multi(ids)?;
371 event_buffer.push(Event {
372 origin: Origin::DirectAccess(DirectAccessEntity::File(EntityEvent::Removed)),
373 ids: ids.into(),
374 data: None,
375 });
376 {
378 let removed_set: std::collections::HashSet<EntityId> = ids.iter().copied().collect();
379 for owner_id in &affected_owner_ids {
380 if let Some(rel_ids) = owner_rel_before.get(owner_id) {
381 let updated: Vec<EntityId> = rel_ids
382 .iter()
383 .copied()
384 .filter(|rid| !removed_set.contains(rid))
385 .collect();
386 self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
387 }
388 }
389 }
390
391 Ok(())
392 }
393 pub fn get_relationship(
394 &self,
395 id: &EntityId,
396 field: &FileRelationshipField,
397 ) -> Result<Vec<EntityId>, RepositoryError> {
398 self.table.get_relationship(id, field)
399 }
400 pub fn get_relationship_many(
401 &self,
402 ids: &[EntityId],
403 field: &FileRelationshipField,
404 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
405 self.table.get_relationship_many(ids, field)
406 }
407 pub fn get_relationship_count(
408 &self,
409 id: &EntityId,
410 field: &FileRelationshipField,
411 ) -> Result<usize, RepositoryError> {
412 self.table.get_relationship_count(id, field)
413 }
414 pub fn get_relationship_in_range(
415 &self,
416 id: &EntityId,
417 field: &FileRelationshipField,
418 offset: usize,
419 limit: usize,
420 ) -> Result<Vec<EntityId>, RepositoryError> {
421 self.table
422 .get_relationship_in_range(id, field, offset, limit)
423 }
424 pub fn get_relationships_from_right_ids(
425 &self,
426 field: &FileRelationshipField,
427 right_ids: &[EntityId],
428 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
429 self.table
430 .get_relationships_from_right_ids(field, right_ids)
431 }
432
433 pub fn set_relationship_multi(
434 &mut self,
435 event_buffer: &mut EventBuffer,
436 field: &FileRelationshipField,
437 relationships: Vec<(EntityId, Vec<EntityId>)>,
438 ) -> Result<(), RepositoryError> {
439 let all_right_ids: Vec<EntityId> = relationships
441 .iter()
442 .flat_map(|(_, ids)| ids.iter().copied())
443 .collect();
444 if !all_right_ids.is_empty() {
445 match field {
446 FileRelationshipField::Entity => {
447 let child_repo =
448 repository_factory::write::create_entity_repository(self.transaction)?;
449 let found = child_repo.get_multi(&all_right_ids)?;
450 let missing: Vec<_> = all_right_ids
451 .iter()
452 .zip(found.iter())
453 .filter(|(_, entity)| entity.is_none())
454 .map(|(id, _)| *id)
455 .collect();
456 if !missing.is_empty() {
457 return Err(RepositoryError::MissingRelationshipTarget {
458 operation: "set_relationship_multi",
459 ids: missing,
460 });
461 }
462 }
463 FileRelationshipField::Feature => {
464 let child_repo =
465 repository_factory::write::create_feature_repository(self.transaction)?;
466 let found = child_repo.get_multi(&all_right_ids)?;
467 let missing: Vec<_> = all_right_ids
468 .iter()
469 .zip(found.iter())
470 .filter(|(_, entity)| entity.is_none())
471 .map(|(id, _)| *id)
472 .collect();
473 if !missing.is_empty() {
474 return Err(RepositoryError::MissingRelationshipTarget {
475 operation: "set_relationship_multi",
476 ids: missing,
477 });
478 }
479 }
480 FileRelationshipField::Field => {
481 let child_repo =
482 repository_factory::write::create_field_repository(self.transaction)?;
483 let found = child_repo.get_multi(&all_right_ids)?;
484 let missing: Vec<_> = all_right_ids
485 .iter()
486 .zip(found.iter())
487 .filter(|(_, entity)| entity.is_none())
488 .map(|(id, _)| *id)
489 .collect();
490 if !missing.is_empty() {
491 return Err(RepositoryError::MissingRelationshipTarget {
492 operation: "set_relationship_multi",
493 ids: missing,
494 });
495 }
496 }
497 FileRelationshipField::UseCase => {
498 let child_repo =
499 repository_factory::write::create_use_case_repository(self.transaction)?;
500 let found = child_repo.get_multi(&all_right_ids)?;
501 let missing: Vec<_> = all_right_ids
502 .iter()
503 .zip(found.iter())
504 .filter(|(_, entity)| entity.is_none())
505 .map(|(id, _)| *id)
506 .collect();
507 if !missing.is_empty() {
508 return Err(RepositoryError::MissingRelationshipTarget {
509 operation: "set_relationship_multi",
510 ids: missing,
511 });
512 }
513 }
514 }
515 }
516 self.table
517 .set_relationship_multi(field, relationships.clone())?;
518 for (left_id, right_ids) in relationships {
519 event_buffer.push(Event {
520 origin: Origin::DirectAccess(DirectAccessEntity::File(EntityEvent::Updated)),
521 ids: vec![left_id],
522 data: Some(format!(
523 "{}:{}",
524 field,
525 right_ids
526 .iter()
527 .map(|id| id.to_string())
528 .collect::<Vec<_>>()
529 .join(",")
530 )),
531 });
532 }
533 Ok(())
534 }
535
536 pub fn set_relationship(
537 &mut self,
538 event_buffer: &mut EventBuffer,
539 id: &EntityId,
540 field: &FileRelationshipField,
541 right_ids: &[EntityId],
542 ) -> Result<(), RepositoryError> {
543 if !right_ids.is_empty() {
545 match field {
546 FileRelationshipField::Entity => {
547 let child_repo =
548 repository_factory::write::create_entity_repository(self.transaction)?;
549 let found = child_repo.get_multi(right_ids)?;
550 let missing: Vec<_> = right_ids
551 .iter()
552 .zip(found.iter())
553 .filter(|(_, entity)| entity.is_none())
554 .map(|(id, _)| *id)
555 .collect();
556 if !missing.is_empty() {
557 return Err(RepositoryError::MissingRelationshipTarget {
558 operation: "set_relationship",
559 ids: missing,
560 });
561 }
562 }
563 FileRelationshipField::Feature => {
564 let child_repo =
565 repository_factory::write::create_feature_repository(self.transaction)?;
566 let found = child_repo.get_multi(right_ids)?;
567 let missing: Vec<_> = right_ids
568 .iter()
569 .zip(found.iter())
570 .filter(|(_, entity)| entity.is_none())
571 .map(|(id, _)| *id)
572 .collect();
573 if !missing.is_empty() {
574 return Err(RepositoryError::MissingRelationshipTarget {
575 operation: "set_relationship",
576 ids: missing,
577 });
578 }
579 }
580 FileRelationshipField::Field => {
581 let child_repo =
582 repository_factory::write::create_field_repository(self.transaction)?;
583 let found = child_repo.get_multi(right_ids)?;
584 let missing: Vec<_> = right_ids
585 .iter()
586 .zip(found.iter())
587 .filter(|(_, entity)| entity.is_none())
588 .map(|(id, _)| *id)
589 .collect();
590 if !missing.is_empty() {
591 return Err(RepositoryError::MissingRelationshipTarget {
592 operation: "set_relationship",
593 ids: missing,
594 });
595 }
596 }
597 FileRelationshipField::UseCase => {
598 let child_repo =
599 repository_factory::write::create_use_case_repository(self.transaction)?;
600 let found = child_repo.get_multi(right_ids)?;
601 let missing: Vec<_> = right_ids
602 .iter()
603 .zip(found.iter())
604 .filter(|(_, entity)| entity.is_none())
605 .map(|(id, _)| *id)
606 .collect();
607 if !missing.is_empty() {
608 return Err(RepositoryError::MissingRelationshipTarget {
609 operation: "set_relationship",
610 ids: missing,
611 });
612 }
613 }
614 }
615 }
616 self.table.set_relationship(id, field, right_ids)?;
617 event_buffer.push(Event {
618 origin: Origin::DirectAccess(DirectAccessEntity::File(EntityEvent::Updated)),
619 ids: vec![*id],
620 data: Some(format!(
621 "{}:{}",
622 field,
623 right_ids
624 .iter()
625 .map(|id| id.to_string())
626 .collect::<Vec<_>>()
627 .join(",")
628 )),
629 });
630 Ok(())
631 }
632
633 pub fn move_relationship_ids(
634 &mut self,
635 event_buffer: &mut EventBuffer,
636 id: &EntityId,
637 field: &FileRelationshipField,
638 ids_to_move: &[EntityId],
639 new_index: i32,
640 ) -> Result<Vec<EntityId>, RepositoryError> {
641 let reordered = self
642 .table
643 .move_relationship_ids(id, field, ids_to_move, new_index)?;
644 event_buffer.push(Event {
645 origin: Origin::DirectAccess(DirectAccessEntity::File(EntityEvent::Updated)),
646 ids: vec![*id],
647 data: Some(format!(
648 "{}:{}",
649 field,
650 reordered
651 .iter()
652 .map(|id| id.to_string())
653 .collect::<Vec<_>>()
654 .join(",")
655 )),
656 });
657 Ok(reordered)
658 }
659 pub fn get_relationships_from_owner(
660 &self,
661 owner_id: &EntityId,
662 ) -> Result<Vec<EntityId>, RepositoryError> {
663 let repo = repository_factory::write::create_system_repository(self.transaction)?;
664 repo.get_relationship(owner_id, &SystemRelationshipField::Files)
665 }
666
667 pub fn set_relationships_in_owner(
668 &mut self,
669 event_buffer: &mut EventBuffer,
670 owner_id: &EntityId,
671 ids: &[EntityId],
672 ) -> Result<(), RepositoryError> {
673 let mut repo = repository_factory::write::create_system_repository(self.transaction)?;
674 repo.set_relationship(event_buffer, owner_id, &SystemRelationshipField::Files, ids)
675 }
676
677 pub fn snapshot(&self, ids: &[EntityId]) -> Result<EntityTreeSnapshot, RepositoryError> {
678 let store_snap = self.transaction.snapshot_store();
680 Ok(EntityTreeSnapshot {
681 store_snapshot: Some(store_snap),
682 root_ids: ids.to_vec(),
683 })
684 }
685
686 pub fn restore(
687 &mut self,
688 event_buffer: &mut EventBuffer,
689 snap: &EntityTreeSnapshot,
690 ) -> Result<(), RepositoryError> {
691 let store_snap = snap
692 .store_snapshot
693 .as_ref()
694 .ok_or_else(|| RepositoryError::Serialization("missing store snapshot".into()))?;
695 let snap_store = store_snap
696 .downcast_ref::<HashMapStoreSnapshot>()
697 .ok_or_else(|| RepositoryError::Serialization("snapshot type mismatch".into()))?;
698
699 let mut visited = std::collections::HashSet::new();
702 self.restore_subtree(event_buffer, snap_store, &snap.root_ids, &mut visited)?;
703
704 self.reconcile_backref_system_files(event_buffer, snap_store, &snap.root_ids)?;
707
708 Ok(())
709 }
710
711 pub(crate) fn restore_subtree(
716 &self,
717 event_buffer: &mut EventBuffer,
718 snap: &HashMapStoreSnapshot,
719 ids: &[EntityId],
720 visited: &mut std::collections::HashSet<(&'static str, EntityId)>,
723 ) -> Result<(), RepositoryError> {
724 let ids: Vec<EntityId> = ids
725 .iter()
726 .copied()
727 .filter(|id| visited.insert(("file", *id)))
728 .collect();
729 if ids.is_empty() {
730 return Ok(());
731 }
732
733 let store = self.transaction.get_store();
734
735 let mut to_create: Vec<EntityId> = Vec::new(); let mut to_update: Vec<EntityId> = Vec::new(); let mut to_delete: Vec<EntityId> = Vec::new(); {
740 let live = read_or_recover(&store.files);
741 for id in &ids {
742 match (snap.files.contains_key(id), live.contains_key(id)) {
743 (true, false) => to_create.push(*id),
744 (true, true) => to_update.push(*id),
745 (false, true) => to_delete.push(*id),
746 (false, false) => {}
747 }
748 }
749 }
750
751 {
756 let mut live = write_or_recover(&store.files);
757 for id in to_create.iter().chain(to_update.iter()) {
758 if let Some(row) = snap.files.get(id) {
759 live.insert(*id, row.clone());
760 }
761 }
762 for id in &to_delete {
763 live.remove(id);
764 }
765 }
766
767 {
770 let mut live_jn = write_or_recover(&store.jn_entity_from_file_entity);
771 for id in to_create.iter().chain(to_update.iter()) {
772 match snap.jn_entity_from_file_entity.get(id) {
773 Some(v) => {
774 live_jn.insert(*id, v.clone());
775 }
776 None => {
777 live_jn.remove(id);
778 }
779 }
780 }
781 for id in &to_delete {
782 live_jn.remove(id);
783 }
784 }
785 {
786 let mut live_jn = write_or_recover(&store.jn_feature_from_file_feature);
787 for id in to_create.iter().chain(to_update.iter()) {
788 match snap.jn_feature_from_file_feature.get(id) {
789 Some(v) => {
790 live_jn.insert(*id, v.clone());
791 }
792 None => {
793 live_jn.remove(id);
794 }
795 }
796 }
797 for id in &to_delete {
798 live_jn.remove(id);
799 }
800 }
801 {
802 let mut live_jn = write_or_recover(&store.jn_field_from_file_field);
803 for id in to_create.iter().chain(to_update.iter()) {
804 match snap.jn_field_from_file_field.get(id) {
805 Some(v) => {
806 live_jn.insert(*id, v.clone());
807 }
808 None => {
809 live_jn.remove(id);
810 }
811 }
812 }
813 for id in &to_delete {
814 live_jn.remove(id);
815 }
816 }
817 {
818 let mut live_jn = write_or_recover(&store.jn_use_case_from_file_use_case);
819 for id in to_create.iter().chain(to_update.iter()) {
820 match snap.jn_use_case_from_file_use_case.get(id) {
821 Some(v) => {
822 live_jn.insert(*id, v.clone());
823 }
824 None => {
825 live_jn.remove(id);
826 }
827 }
828 }
829 for id in &to_delete {
830 live_jn.remove(id);
831 }
832 }
833
834 if !to_create.is_empty() {
838 event_buffer.push(Event {
839 origin: Origin::DirectAccess(DirectAccessEntity::File(EntityEvent::Created)),
840 ids: to_create.clone(),
841 data: None,
842 });
843 event_buffer.push(Event {
844 origin: Origin::DirectAccess(DirectAccessEntity::File(EntityEvent::Updated)),
845 ids: to_create.clone(),
846 data: None,
847 });
848 }
849 if !to_update.is_empty() {
850 event_buffer.push(Event {
851 origin: Origin::DirectAccess(DirectAccessEntity::File(EntityEvent::Updated)),
852 ids: to_update.clone(),
853 data: None,
854 });
855 }
856 if !to_delete.is_empty() {
857 event_buffer.push(Event {
858 origin: Origin::DirectAccess(DirectAccessEntity::File(EntityEvent::Removed)),
859 ids: to_delete.clone(),
860 data: None,
861 });
862 }
863
864 Ok(())
865 }
866
867 fn reconcile_backref_system_files(
870 &self,
871 event_buffer: &mut EventBuffer,
872 snap: &HashMapStoreSnapshot,
873 scope_ids: &[EntityId],
874 ) -> Result<(), RepositoryError> {
875 let scope: std::collections::HashSet<EntityId> = scope_ids.iter().copied().collect();
876 if scope.is_empty() {
877 return Ok(());
878 }
879 let store = self.transaction.get_store();
880
881 let mut left_keys: std::collections::HashSet<EntityId> = std::collections::HashSet::new();
883 for (left, rights) in snap.jn_file_from_system_files.iter() {
884 if rights.iter().any(|rid| scope.contains(rid)) {
885 left_keys.insert(*left);
886 }
887 }
888 {
889 let live_jn = read_or_recover(&store.jn_file_from_system_files);
890 for (left, rights) in live_jn.iter() {
891 if rights.iter().any(|rid| scope.contains(rid)) {
892 left_keys.insert(*left);
893 }
894 }
895 }
896
897 for left in left_keys {
898 let snap_list: Vec<EntityId> = snap
899 .jn_file_from_system_files
900 .get(&left)
901 .cloned()
902 .unwrap_or_default();
903 let new_list = {
904 let live_jn = read_or_recover(&store.jn_file_from_system_files);
905 let live_list: Vec<EntityId> = live_jn.get(&left).cloned().unwrap_or_default();
906 let reconciled = crate::database::hashmap_store::reconcile_backref_list(
907 &live_list, &snap_list, &scope,
908 );
909 if reconciled == live_list {
910 None
911 } else {
912 Some(reconciled)
913 }
914 };
915 if let Some(reconciled) = new_list {
916 write_or_recover(&store.jn_file_from_system_files).insert(left, reconciled);
917 event_buffer.push(Event {
918 origin: Origin::DirectAccess(DirectAccessEntity::System(EntityEvent::Updated)),
919 ids: vec![left],
920 data: None,
921 });
922 }
923 }
924 Ok(())
925 }
926}
927
928pub struct FileRepositoryRO<'a> {
929 table: Box<dyn FileTableRO + 'a>,
930}
931impl<'a> FileRepositoryRO<'a> {
932 pub fn new(table: Box<dyn FileTableRO + 'a>) -> Self {
933 FileRepositoryRO { table }
934 }
935 pub fn get(&self, id: &EntityId) -> Result<Option<File>, RepositoryError> {
936 self.table.get(id)
937 }
938 pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<File>>, RepositoryError> {
939 self.table.get_multi(ids)
940 }
941 pub fn get_all(&self) -> Result<Vec<File>, RepositoryError> {
942 self.table.get_all()
943 }
944 pub fn get_relationship(
945 &self,
946 id: &EntityId,
947 field: &FileRelationshipField,
948 ) -> Result<Vec<EntityId>, RepositoryError> {
949 self.table.get_relationship(id, field)
950 }
951 pub fn get_relationship_many(
952 &self,
953 ids: &[EntityId],
954 field: &FileRelationshipField,
955 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
956 self.table.get_relationship_many(ids, field)
957 }
958 pub fn get_relationship_count(
959 &self,
960 id: &EntityId,
961 field: &FileRelationshipField,
962 ) -> Result<usize, RepositoryError> {
963 self.table.get_relationship_count(id, field)
964 }
965 pub fn get_relationship_in_range(
966 &self,
967 id: &EntityId,
968 field: &FileRelationshipField,
969 offset: usize,
970 limit: usize,
971 ) -> Result<Vec<EntityId>, RepositoryError> {
972 self.table
973 .get_relationship_in_range(id, field, offset, limit)
974 }
975 pub fn get_relationships_from_right_ids(
976 &self,
977 field: &FileRelationshipField,
978 right_ids: &[EntityId],
979 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
980 self.table
981 .get_relationships_from_right_ids(field, right_ids)
982 }
983}