1use std::fmt::Display;
4
5use crate::{
6 database::transactions::Transaction,
7 direct_access::repository_factory,
8 entities::System,
9 event::{DirectAccessEntity, EntityEvent, Event, EventBuffer, Origin},
10 snapshot::EntityTreeSnapshot,
11 types::EntityId,
12};
13
14use crate::direct_access::root::RootRelationshipField;
15use crate::error::RepositoryError;
16use serde::{Deserialize, Serialize};
17
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
19pub enum SystemRelationshipField {
20 Files,
21}
22
23impl Display for SystemRelationshipField {
24 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
25 write!(f, "{:?}", self)
26 }
27}
28
29pub trait SystemTable {
30 fn create(&mut self, entity: &System) -> Result<System, RepositoryError>;
31 fn create_multi(&mut self, entities: &[System]) -> Result<Vec<System>, RepositoryError>;
32 fn get(&self, id: &EntityId) -> Result<Option<System>, RepositoryError>;
33 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<System>>, RepositoryError>;
34 fn get_all(&self) -> Result<Vec<System>, RepositoryError>;
35 fn update(&mut self, entity: &System) -> Result<System, RepositoryError>;
36 fn update_multi(&mut self, entities: &[System]) -> Result<Vec<System>, RepositoryError>;
37 fn update_with_relationships(&mut self, entity: &System) -> Result<System, RepositoryError>;
38 fn update_with_relationships_multi(
39 &mut self,
40 entities: &[System],
41 ) -> Result<Vec<System>, RepositoryError>;
42 fn remove(&mut self, id: &EntityId) -> Result<(), RepositoryError>;
43 fn remove_multi(&mut self, ids: &[EntityId]) -> Result<(), RepositoryError>;
44 fn get_relationship(
45 &self,
46 id: &EntityId,
47 field: &SystemRelationshipField,
48 ) -> Result<Vec<EntityId>, RepositoryError>;
49 fn get_relationship_many(
50 &self,
51 ids: &[EntityId],
52 field: &SystemRelationshipField,
53 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
54 fn get_relationship_count(
55 &self,
56 id: &EntityId,
57 field: &SystemRelationshipField,
58 ) -> Result<usize, RepositoryError>;
59 fn get_relationship_in_range(
60 &self,
61 id: &EntityId,
62 field: &SystemRelationshipField,
63 offset: usize,
64 limit: usize,
65 ) -> Result<Vec<EntityId>, RepositoryError>;
66 fn get_relationships_from_right_ids(
67 &self,
68 field: &SystemRelationshipField,
69 right_ids: &[EntityId],
70 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
71 fn set_relationship_multi(
72 &mut self,
73 field: &SystemRelationshipField,
74 relationships: Vec<(EntityId, Vec<EntityId>)>,
75 ) -> Result<(), RepositoryError>;
76 fn set_relationship(
77 &mut self,
78 id: &EntityId,
79 field: &SystemRelationshipField,
80 right_ids: &[EntityId],
81 ) -> Result<(), RepositoryError>;
82 fn move_relationship_ids(
83 &mut self,
84 id: &EntityId,
85 field: &SystemRelationshipField,
86 ids_to_move: &[EntityId],
87 new_index: i32,
88 ) -> Result<Vec<EntityId>, RepositoryError>;
89}
90
91pub trait SystemTableRO {
92 fn get(&self, id: &EntityId) -> Result<Option<System>, RepositoryError>;
93 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<System>>, RepositoryError>;
94 fn get_all(&self) -> Result<Vec<System>, RepositoryError>;
95 fn get_relationship(
96 &self,
97 id: &EntityId,
98 field: &SystemRelationshipField,
99 ) -> Result<Vec<EntityId>, RepositoryError>;
100 fn get_relationship_many(
101 &self,
102 ids: &[EntityId],
103 field: &SystemRelationshipField,
104 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
105 fn get_relationship_count(
106 &self,
107 id: &EntityId,
108 field: &SystemRelationshipField,
109 ) -> Result<usize, RepositoryError>;
110 fn get_relationship_in_range(
111 &self,
112 id: &EntityId,
113 field: &SystemRelationshipField,
114 offset: usize,
115 limit: usize,
116 ) -> Result<Vec<EntityId>, RepositoryError>;
117 fn get_relationships_from_right_ids(
118 &self,
119 field: &SystemRelationshipField,
120 right_ids: &[EntityId],
121 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
122}
123
124pub struct SystemRepository<'a> {
125 table: Box<dyn SystemTable + 'a>,
126 transaction: &'a Transaction,
127}
128
129impl<'a> SystemRepository<'a> {
130 pub fn new(table: Box<dyn SystemTable + 'a>, transaction: &'a Transaction) -> Self {
131 SystemRepository { table, transaction }
132 }
133
134 pub fn create_orphan(
135 &mut self,
136 event_buffer: &mut EventBuffer,
137 entity: &System,
138 ) -> Result<System, RepositoryError> {
139 let new = self.table.create(entity)?;
140 event_buffer.push(Event {
141 origin: Origin::DirectAccess(DirectAccessEntity::System(EntityEvent::Created)),
142 ids: vec![new.id],
143 data: None,
144 });
145 Ok(new)
146 }
147
148 pub fn create_orphan_multi(
149 &mut self,
150 event_buffer: &mut EventBuffer,
151 entities: &[System],
152 ) -> Result<Vec<System>, RepositoryError> {
153 let new_entities = self.table.create_multi(entities)?;
154 event_buffer.push(Event {
155 origin: Origin::DirectAccess(DirectAccessEntity::System(EntityEvent::Created)),
156 ids: new_entities.iter().map(|e| e.id).collect(),
157 data: None,
158 });
159 Ok(new_entities)
160 }
161 pub fn create(
162 &mut self,
163 event_buffer: &mut EventBuffer,
164 entity: &System,
165 owner_id: EntityId,
166 _index: i32,
167 ) -> Result<System, RepositoryError> {
168 let new = self.table.create(entity)?;
169 let created_id = new.id;
170
171 let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
172 if relationship_ids.is_empty() {
173 relationship_ids = vec![created_id];
174 } else {
175 self.remove_multi(event_buffer, &relationship_ids)?;
177 relationship_ids = vec![created_id];
178 }
179
180 self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
181 event_buffer.push(Event {
182 origin: Origin::DirectAccess(DirectAccessEntity::System(EntityEvent::Created)),
183 ids: vec![created_id],
184 data: None,
185 });
186 Ok(new)
187 }
188
189 pub fn create_multi(
190 &mut self,
191 event_buffer: &mut EventBuffer,
192 entities: &[System],
193 owner_id: EntityId,
194 _index: i32,
195 ) -> Result<Vec<System>, RepositoryError> {
196 let new_entities = self.table.create_multi(entities)?;
197 let created_ids: Vec<EntityId> = new_entities.iter().map(|e| e.id).collect();
198
199 let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
200 if relationship_ids.is_empty() {
201 relationship_ids = created_ids.clone();
202 } else {
203 self.remove_multi(event_buffer, &relationship_ids)?;
204 relationship_ids = created_ids.clone();
205 }
206
207 self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
208 event_buffer.push(Event {
209 origin: Origin::DirectAccess(DirectAccessEntity::System(EntityEvent::Created)),
210 ids: created_ids,
211 data: None,
212 });
213 Ok(new_entities)
214 }
215
216 pub fn get(&self, id: &EntityId) -> Result<Option<System>, RepositoryError> {
217 self.table.get(id)
218 }
219 pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<System>>, RepositoryError> {
220 self.table.get_multi(ids)
221 }
222 pub fn get_all(&self) -> Result<Vec<System>, RepositoryError> {
223 self.table.get_all()
224 }
225
226 pub fn update(
227 &mut self,
228 event_buffer: &mut EventBuffer,
229 entity: &System,
230 ) -> Result<System, RepositoryError> {
231 let updated = self.table.update(entity)?;
232 event_buffer.push(Event {
233 origin: Origin::DirectAccess(DirectAccessEntity::System(EntityEvent::Updated)),
234 ids: vec![updated.id],
235 data: None,
236 });
237 Ok(updated)
238 }
239
240 pub fn update_multi(
241 &mut self,
242 event_buffer: &mut EventBuffer,
243 entities: &[System],
244 ) -> Result<Vec<System>, RepositoryError> {
245 let updated = self.table.update_multi(entities)?;
246 event_buffer.push(Event {
247 origin: Origin::DirectAccess(DirectAccessEntity::System(EntityEvent::Updated)),
248 ids: updated.iter().map(|e| e.id).collect(),
249 data: None,
250 });
251 Ok(updated)
252 }
253
254 pub fn update_with_relationships(
255 &mut self,
256 event_buffer: &mut EventBuffer,
257 entity: &System,
258 ) -> Result<System, RepositoryError> {
259 let updated = self.table.update_with_relationships(entity)?;
260 event_buffer.push(Event {
261 origin: Origin::DirectAccess(DirectAccessEntity::System(EntityEvent::Updated)),
262 ids: vec![updated.id],
263 data: None,
264 });
265 Ok(updated)
266 }
267
268 pub fn update_with_relationships_multi(
269 &mut self,
270 event_buffer: &mut EventBuffer,
271 entities: &[System],
272 ) -> Result<Vec<System>, RepositoryError> {
273 let updated = self.table.update_with_relationships_multi(entities)?;
274 event_buffer.push(Event {
275 origin: Origin::DirectAccess(DirectAccessEntity::System(EntityEvent::Updated)),
276 ids: updated.iter().map(|e| e.id).collect(),
277 data: None,
278 });
279 Ok(updated)
280 }
281
282 pub fn remove(
283 &mut self,
284 event_buffer: &mut EventBuffer,
285 id: &EntityId,
286 ) -> Result<(), RepositoryError> {
287 let entity = match self.table.get(id)? {
288 Some(e) => e,
289 None => return Ok(()),
290 };
291 let files = entity.files.clone();
294
295 repository_factory::write::create_file_repository(self.transaction)?
298 .remove_multi(event_buffer, &files)?;
299 let affected_owner_ids: Vec<EntityId> = {
301 let owner_repo = repository_factory::write::create_root_repository(self.transaction)?;
302 owner_repo
303 .get_relationships_from_right_ids(&RootRelationshipField::System, &[*id])?
304 .into_iter()
305 .map(|(owner_id, _)| owner_id)
306 .collect()
307 };
308 let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
310 std::collections::HashMap::new();
311 for owner_id in &affected_owner_ids {
312 owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
313 }
314
315 self.table.remove(id)?;
317 event_buffer.push(Event {
318 origin: Origin::DirectAccess(DirectAccessEntity::System(EntityEvent::Removed)),
319 ids: vec![*id],
320 data: None,
321 });
322 for owner_id in &affected_owner_ids {
324 if let Some(rel_ids) = owner_rel_before.get(owner_id) {
325 let updated: Vec<EntityId> =
326 rel_ids.iter().copied().filter(|rid| *rid != *id).collect();
327 self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
328 }
329 }
330
331 Ok(())
332 }
333
334 pub fn remove_multi(
335 &mut self,
336 event_buffer: &mut EventBuffer,
337 ids: &[EntityId],
338 ) -> Result<(), RepositoryError> {
339 let entities = self.table.get_multi(ids)?;
340 if entities.is_empty() || entities.iter().all(|e| e.is_none()) {
341 return Ok(());
342 }
343
344 let mut files_ids: Vec<EntityId> = entities
347 .iter()
348 .flat_map(|entity| entity.as_ref().map(|entity| entity.files.clone()))
349 .flatten()
350 .collect();
351 files_ids.sort();
353 files_ids.dedup();
354
355 repository_factory::write::create_file_repository(self.transaction)?
358 .remove_multi(event_buffer, &files_ids)?;
359 let affected_owner_ids: Vec<EntityId> = {
361 let owner_repo = repository_factory::write::create_root_repository(self.transaction)?;
362 owner_repo
363 .get_relationships_from_right_ids(&RootRelationshipField::System, ids)?
364 .into_iter()
365 .map(|(owner_id, _)| owner_id)
366 .collect()
367 };
368 let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
370 std::collections::HashMap::new();
371 for owner_id in &affected_owner_ids {
372 owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
373 }
374
375 self.table.remove_multi(ids)?;
376 event_buffer.push(Event {
377 origin: Origin::DirectAccess(DirectAccessEntity::System(EntityEvent::Removed)),
378 ids: ids.into(),
379 data: None,
380 });
381 {
383 let removed_set: std::collections::HashSet<EntityId> = ids.iter().copied().collect();
384 for owner_id in &affected_owner_ids {
385 if let Some(rel_ids) = owner_rel_before.get(owner_id) {
386 let updated: Vec<EntityId> = rel_ids
387 .iter()
388 .copied()
389 .filter(|rid| !removed_set.contains(rid))
390 .collect();
391 self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
392 }
393 }
394 }
395
396 Ok(())
397 }
398 pub fn get_relationship(
399 &self,
400 id: &EntityId,
401 field: &SystemRelationshipField,
402 ) -> Result<Vec<EntityId>, RepositoryError> {
403 self.table.get_relationship(id, field)
404 }
405 pub fn get_relationship_many(
406 &self,
407 ids: &[EntityId],
408 field: &SystemRelationshipField,
409 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
410 self.table.get_relationship_many(ids, field)
411 }
412 pub fn get_relationship_count(
413 &self,
414 id: &EntityId,
415 field: &SystemRelationshipField,
416 ) -> Result<usize, RepositoryError> {
417 self.table.get_relationship_count(id, field)
418 }
419 pub fn get_relationship_in_range(
420 &self,
421 id: &EntityId,
422 field: &SystemRelationshipField,
423 offset: usize,
424 limit: usize,
425 ) -> Result<Vec<EntityId>, RepositoryError> {
426 self.table
427 .get_relationship_in_range(id, field, offset, limit)
428 }
429 pub fn get_relationships_from_right_ids(
430 &self,
431 field: &SystemRelationshipField,
432 right_ids: &[EntityId],
433 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
434 self.table
435 .get_relationships_from_right_ids(field, right_ids)
436 }
437
438 pub fn set_relationship_multi(
439 &mut self,
440 event_buffer: &mut EventBuffer,
441 field: &SystemRelationshipField,
442 relationships: Vec<(EntityId, Vec<EntityId>)>,
443 ) -> Result<(), RepositoryError> {
444 let all_right_ids: Vec<EntityId> = relationships
446 .iter()
447 .flat_map(|(_, ids)| ids.iter().copied())
448 .collect();
449 if !all_right_ids.is_empty() {
450 match field {
451 SystemRelationshipField::Files => {
452 let child_repo =
453 repository_factory::write::create_file_repository(self.transaction)?;
454 let found = child_repo.get_multi(&all_right_ids)?;
455 let missing: Vec<_> = all_right_ids
456 .iter()
457 .zip(found.iter())
458 .filter(|(_, entity)| entity.is_none())
459 .map(|(id, _)| *id)
460 .collect();
461 if !missing.is_empty() {
462 return Err(RepositoryError::MissingRelationshipTarget {
463 operation: "set_relationship_multi",
464 ids: missing,
465 });
466 }
467 }
468 }
469 }
470 self.table
471 .set_relationship_multi(field, relationships.clone())?;
472 for (left_id, right_ids) in relationships {
473 event_buffer.push(Event {
474 origin: Origin::DirectAccess(DirectAccessEntity::System(EntityEvent::Updated)),
475 ids: vec![left_id],
476 data: Some(format!(
477 "{}:{}",
478 field,
479 right_ids
480 .iter()
481 .map(|id| id.to_string())
482 .collect::<Vec<_>>()
483 .join(",")
484 )),
485 });
486 }
487 Ok(())
488 }
489
490 pub fn set_relationship(
491 &mut self,
492 event_buffer: &mut EventBuffer,
493 id: &EntityId,
494 field: &SystemRelationshipField,
495 right_ids: &[EntityId],
496 ) -> Result<(), RepositoryError> {
497 if !right_ids.is_empty() {
499 match field {
500 SystemRelationshipField::Files => {
501 let child_repo =
502 repository_factory::write::create_file_repository(self.transaction)?;
503 let found = child_repo.get_multi(right_ids)?;
504 let missing: Vec<_> = right_ids
505 .iter()
506 .zip(found.iter())
507 .filter(|(_, entity)| entity.is_none())
508 .map(|(id, _)| *id)
509 .collect();
510 if !missing.is_empty() {
511 return Err(RepositoryError::MissingRelationshipTarget {
512 operation: "set_relationship",
513 ids: missing,
514 });
515 }
516 }
517 }
518 }
519 self.table.set_relationship(id, field, right_ids)?;
520 event_buffer.push(Event {
521 origin: Origin::DirectAccess(DirectAccessEntity::System(EntityEvent::Updated)),
522 ids: vec![*id],
523 data: Some(format!(
524 "{}:{}",
525 field,
526 right_ids
527 .iter()
528 .map(|id| id.to_string())
529 .collect::<Vec<_>>()
530 .join(",")
531 )),
532 });
533 Ok(())
534 }
535
536 pub fn move_relationship_ids(
537 &mut self,
538 event_buffer: &mut EventBuffer,
539 id: &EntityId,
540 field: &SystemRelationshipField,
541 ids_to_move: &[EntityId],
542 new_index: i32,
543 ) -> Result<Vec<EntityId>, RepositoryError> {
544 let reordered = self
545 .table
546 .move_relationship_ids(id, field, ids_to_move, new_index)?;
547 event_buffer.push(Event {
548 origin: Origin::DirectAccess(DirectAccessEntity::System(EntityEvent::Updated)),
549 ids: vec![*id],
550 data: Some(format!(
551 "{}:{}",
552 field,
553 reordered
554 .iter()
555 .map(|id| id.to_string())
556 .collect::<Vec<_>>()
557 .join(",")
558 )),
559 });
560 Ok(reordered)
561 }
562 pub fn get_relationships_from_owner(
563 &self,
564 owner_id: &EntityId,
565 ) -> Result<Vec<EntityId>, RepositoryError> {
566 let repo = repository_factory::write::create_root_repository(self.transaction)?;
567 repo.get_relationship(owner_id, &RootRelationshipField::System)
568 }
569
570 pub fn set_relationships_in_owner(
571 &mut self,
572 event_buffer: &mut EventBuffer,
573 owner_id: &EntityId,
574 ids: &[EntityId],
575 ) -> Result<(), RepositoryError> {
576 let mut repo = repository_factory::write::create_root_repository(self.transaction)?;
577 repo.set_relationship(event_buffer, owner_id, &RootRelationshipField::System, ids)
578 }
579
580 pub fn snapshot(&self, _ids: &[EntityId]) -> Result<EntityTreeSnapshot, RepositoryError> {
581 let store_snap = self.transaction.snapshot_store();
582 Ok(EntityTreeSnapshot {
583 store_snapshot: Some(store_snap),
584 })
585 }
586
587 pub fn restore(
588 &mut self,
589 event_buffer: &mut EventBuffer,
590 snap: &EntityTreeSnapshot,
591 ) -> Result<(), RepositoryError> {
592 let store_snap = snap
593 .store_snapshot
594 .as_ref()
595 .ok_or_else(|| RepositoryError::Serialization("missing store snapshot".into()))?;
596 self.transaction.restore_store(store_snap);
597
598 let store = self.transaction.get_store();
599
600 let mut emit = |entity: DirectAccessEntity, ids: Vec<EntityId>| {
601 if !ids.is_empty() {
602 event_buffer.push(Event {
603 origin: Origin::DirectAccess(entity),
604 ids,
605 data: None,
606 });
607 }
608 };
609
610 let system_ids: Vec<_> = store.systems.read().unwrap().keys().copied().collect();
612 emit(
613 DirectAccessEntity::System(EntityEvent::Created),
614 system_ids.clone(),
615 );
616 emit(DirectAccessEntity::System(EntityEvent::Updated), system_ids);
617
618 {
621 let child_ids: Vec<_> = store.files.read().unwrap().keys().copied().collect();
622 emit(
623 DirectAccessEntity::File(EntityEvent::Created),
624 child_ids.clone(),
625 );
626 emit(DirectAccessEntity::File(EntityEvent::Updated), child_ids);
627 }
628
629 Ok(())
630 }
631}
632
633pub struct SystemRepositoryRO<'a> {
634 table: Box<dyn SystemTableRO + 'a>,
635}
636impl<'a> SystemRepositoryRO<'a> {
637 pub fn new(table: Box<dyn SystemTableRO + 'a>) -> Self {
638 SystemRepositoryRO { table }
639 }
640 pub fn get(&self, id: &EntityId) -> Result<Option<System>, RepositoryError> {
641 self.table.get(id)
642 }
643 pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<System>>, RepositoryError> {
644 self.table.get_multi(ids)
645 }
646 pub fn get_all(&self) -> Result<Vec<System>, RepositoryError> {
647 self.table.get_all()
648 }
649 pub fn get_relationship(
650 &self,
651 id: &EntityId,
652 field: &SystemRelationshipField,
653 ) -> Result<Vec<EntityId>, RepositoryError> {
654 self.table.get_relationship(id, field)
655 }
656 pub fn get_relationship_many(
657 &self,
658 ids: &[EntityId],
659 field: &SystemRelationshipField,
660 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
661 self.table.get_relationship_many(ids, field)
662 }
663 pub fn get_relationship_count(
664 &self,
665 id: &EntityId,
666 field: &SystemRelationshipField,
667 ) -> Result<usize, RepositoryError> {
668 self.table.get_relationship_count(id, field)
669 }
670 pub fn get_relationship_in_range(
671 &self,
672 id: &EntityId,
673 field: &SystemRelationshipField,
674 offset: usize,
675 limit: usize,
676 ) -> Result<Vec<EntityId>, RepositoryError> {
677 self.table
678 .get_relationship_in_range(id, field, offset, limit)
679 }
680 pub fn get_relationships_from_right_ids(
681 &self,
682 field: &SystemRelationshipField,
683 right_ids: &[EntityId],
684 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
685 self.table
686 .get_relationships_from_right_ids(field, right_ids)
687 }
688}