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,
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 System,
20 Workspace,
21}
22
23impl Display for RootRelationshipField {
24 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
25 write!(f, "{:?}", self)
26 }
27}
28
29pub trait RootTable {
30 fn create(&mut self, entity: &Root) -> Result<Root, RepositoryError>;
31 fn create_multi(&mut self, entities: &[Root]) -> Result<Vec<Root>, RepositoryError>;
32 fn get(&self, id: &EntityId) -> Result<Option<Root>, RepositoryError>;
33 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Root>>, RepositoryError>;
34 fn get_all(&self) -> Result<Vec<Root>, RepositoryError>;
35 fn update(&mut self, entity: &Root) -> Result<Root, RepositoryError>;
36 fn update_multi(&mut self, entities: &[Root]) -> Result<Vec<Root>, RepositoryError>;
37 fn update_with_relationships(&mut self, entity: &Root) -> Result<Root, RepositoryError>;
38 fn update_with_relationships_multi(
39 &mut self,
40 entities: &[Root],
41 ) -> Result<Vec<Root>, 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: &RootRelationshipField,
48 ) -> Result<Vec<EntityId>, RepositoryError>;
49 fn get_relationship_many(
50 &self,
51 ids: &[EntityId],
52 field: &RootRelationshipField,
53 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
54 fn get_relationship_count(
55 &self,
56 id: &EntityId,
57 field: &RootRelationshipField,
58 ) -> Result<usize, RepositoryError>;
59 fn get_relationship_in_range(
60 &self,
61 id: &EntityId,
62 field: &RootRelationshipField,
63 offset: usize,
64 limit: usize,
65 ) -> Result<Vec<EntityId>, RepositoryError>;
66 fn get_relationships_from_right_ids(
67 &self,
68 field: &RootRelationshipField,
69 right_ids: &[EntityId],
70 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
71 fn set_relationship_multi(
72 &mut self,
73 field: &RootRelationshipField,
74 relationships: Vec<(EntityId, Vec<EntityId>)>,
75 ) -> Result<(), RepositoryError>;
76 fn set_relationship(
77 &mut self,
78 id: &EntityId,
79 field: &RootRelationshipField,
80 right_ids: &[EntityId],
81 ) -> Result<(), RepositoryError>;
82 fn move_relationship_ids(
83 &mut self,
84 id: &EntityId,
85 field: &RootRelationshipField,
86 ids_to_move: &[EntityId],
87 new_index: i32,
88 ) -> Result<Vec<EntityId>, RepositoryError>;
89}
90
91pub trait RootTableRO {
92 fn get(&self, id: &EntityId) -> Result<Option<Root>, RepositoryError>;
93 fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Root>>, RepositoryError>;
94 fn get_all(&self) -> Result<Vec<Root>, RepositoryError>;
95 fn get_relationship(
96 &self,
97 id: &EntityId,
98 field: &RootRelationshipField,
99 ) -> Result<Vec<EntityId>, RepositoryError>;
100 fn get_relationship_many(
101 &self,
102 ids: &[EntityId],
103 field: &RootRelationshipField,
104 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
105 fn get_relationship_count(
106 &self,
107 id: &EntityId,
108 field: &RootRelationshipField,
109 ) -> Result<usize, RepositoryError>;
110 fn get_relationship_in_range(
111 &self,
112 id: &EntityId,
113 field: &RootRelationshipField,
114 offset: usize,
115 limit: usize,
116 ) -> Result<Vec<EntityId>, RepositoryError>;
117 fn get_relationships_from_right_ids(
118 &self,
119 field: &RootRelationshipField,
120 right_ids: &[EntityId],
121 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
122}
123
124pub struct RootRepository<'a> {
125 table: Box<dyn RootTable + 'a>,
126 transaction: &'a Transaction,
127}
128
129impl<'a> RootRepository<'a> {
130 pub fn new(table: Box<dyn RootTable + 'a>, transaction: &'a Transaction) -> Self {
131 RootRepository { table, transaction }
132 }
133
134 pub fn create_orphan(
135 &mut self,
136 event_buffer: &mut EventBuffer,
137 entity: &Root,
138 ) -> Result<Root, RepositoryError> {
139 let new = self.table.create(entity)?;
140 event_buffer.push(Event {
141 origin: Origin::DirectAccess(DirectAccessEntity::Root(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: &[Root],
152 ) -> Result<Vec<Root>, RepositoryError> {
153 let new_entities = self.table.create_multi(entities)?;
154 event_buffer.push(Event {
155 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Created)),
156 ids: new_entities.iter().map(|e| e.id).collect(),
157 data: None,
158 });
159 Ok(new_entities)
160 }
161
162 pub fn get(&self, id: &EntityId) -> Result<Option<Root>, RepositoryError> {
163 self.table.get(id)
164 }
165 pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Root>>, RepositoryError> {
166 self.table.get_multi(ids)
167 }
168 pub fn get_all(&self) -> Result<Vec<Root>, RepositoryError> {
169 self.table.get_all()
170 }
171
172 pub fn update(
173 &mut self,
174 event_buffer: &mut EventBuffer,
175 entity: &Root,
176 ) -> Result<Root, RepositoryError> {
177 let updated = self.table.update(entity)?;
178 event_buffer.push(Event {
179 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
180 ids: vec![updated.id],
181 data: None,
182 });
183 Ok(updated)
184 }
185
186 pub fn update_multi(
187 &mut self,
188 event_buffer: &mut EventBuffer,
189 entities: &[Root],
190 ) -> Result<Vec<Root>, RepositoryError> {
191 let updated = self.table.update_multi(entities)?;
192 event_buffer.push(Event {
193 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
194 ids: updated.iter().map(|e| e.id).collect(),
195 data: None,
196 });
197 Ok(updated)
198 }
199
200 pub fn update_with_relationships(
201 &mut self,
202 event_buffer: &mut EventBuffer,
203 entity: &Root,
204 ) -> Result<Root, RepositoryError> {
205 let updated = self.table.update_with_relationships(entity)?;
206 event_buffer.push(Event {
207 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
208 ids: vec![updated.id],
209 data: None,
210 });
211 Ok(updated)
212 }
213
214 pub fn update_with_relationships_multi(
215 &mut self,
216 event_buffer: &mut EventBuffer,
217 entities: &[Root],
218 ) -> Result<Vec<Root>, RepositoryError> {
219 let updated = self.table.update_with_relationships_multi(entities)?;
220 event_buffer.push(Event {
221 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
222 ids: updated.iter().map(|e| e.id).collect(),
223 data: None,
224 });
225 Ok(updated)
226 }
227
228 pub fn remove(
229 &mut self,
230 event_buffer: &mut EventBuffer,
231 id: &EntityId,
232 ) -> Result<(), RepositoryError> {
233 let entity = match self.table.get(id)? {
234 Some(e) => e,
235 None => return Ok(()),
236 };
237 let workspace = entity.workspace;
240 let system = entity.system;
241
242 if let Some(workspace_id) = workspace {
245 repository_factory::write::create_workspace_repository(self.transaction)?
246 .remove(event_buffer, &workspace_id)?;
247 }
248 if let Some(system_id) = system {
249 repository_factory::write::create_system_repository(self.transaction)?
250 .remove(event_buffer, &system_id)?;
251 }
252
253 self.table.remove(id)?;
255 event_buffer.push(Event {
256 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Removed)),
257 ids: vec![*id],
258 data: None,
259 });
260
261 Ok(())
262 }
263
264 pub fn remove_multi(
265 &mut self,
266 event_buffer: &mut EventBuffer,
267 ids: &[EntityId],
268 ) -> Result<(), RepositoryError> {
269 let entities = self.table.get_multi(ids)?;
270 if entities.is_empty() || entities.iter().all(|e| e.is_none()) {
271 return Ok(());
272 }
273
274 let workspace_ids: Vec<EntityId> = entities
277 .iter()
278 .filter_map(|entity| entity.as_ref().and_then(|entity| entity.workspace))
279 .collect();
280 let system_ids: Vec<EntityId> = entities
281 .iter()
282 .filter_map(|entity| entity.as_ref().and_then(|entity| entity.system))
283 .collect();
284
285 repository_factory::write::create_workspace_repository(self.transaction)?
288 .remove_multi(event_buffer, &workspace_ids)?;
289 repository_factory::write::create_system_repository(self.transaction)?
290 .remove_multi(event_buffer, &system_ids)?;
291
292 self.table.remove_multi(ids)?;
293 event_buffer.push(Event {
294 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Removed)),
295 ids: ids.into(),
296 data: None,
297 });
298
299 Ok(())
300 }
301 pub fn get_relationship(
302 &self,
303 id: &EntityId,
304 field: &RootRelationshipField,
305 ) -> Result<Vec<EntityId>, RepositoryError> {
306 self.table.get_relationship(id, field)
307 }
308 pub fn get_relationship_many(
309 &self,
310 ids: &[EntityId],
311 field: &RootRelationshipField,
312 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
313 self.table.get_relationship_many(ids, field)
314 }
315 pub fn get_relationship_count(
316 &self,
317 id: &EntityId,
318 field: &RootRelationshipField,
319 ) -> Result<usize, RepositoryError> {
320 self.table.get_relationship_count(id, field)
321 }
322 pub fn get_relationship_in_range(
323 &self,
324 id: &EntityId,
325 field: &RootRelationshipField,
326 offset: usize,
327 limit: usize,
328 ) -> Result<Vec<EntityId>, RepositoryError> {
329 self.table
330 .get_relationship_in_range(id, field, offset, limit)
331 }
332 pub fn get_relationships_from_right_ids(
333 &self,
334 field: &RootRelationshipField,
335 right_ids: &[EntityId],
336 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
337 self.table
338 .get_relationships_from_right_ids(field, right_ids)
339 }
340
341 pub fn set_relationship_multi(
342 &mut self,
343 event_buffer: &mut EventBuffer,
344 field: &RootRelationshipField,
345 relationships: Vec<(EntityId, Vec<EntityId>)>,
346 ) -> Result<(), RepositoryError> {
347 let all_right_ids: Vec<EntityId> = relationships
349 .iter()
350 .flat_map(|(_, ids)| ids.iter().copied())
351 .collect();
352 if !all_right_ids.is_empty() {
353 match field {
354 RootRelationshipField::System => {
355 let child_repo =
356 repository_factory::write::create_system_repository(self.transaction)?;
357 let found = child_repo.get_multi(&all_right_ids)?;
358 let missing: Vec<_> = all_right_ids
359 .iter()
360 .zip(found.iter())
361 .filter(|(_, entity)| entity.is_none())
362 .map(|(id, _)| *id)
363 .collect();
364 if !missing.is_empty() {
365 return Err(RepositoryError::MissingRelationshipTarget {
366 operation: "set_relationship_multi",
367 ids: missing,
368 });
369 }
370 }
371 RootRelationshipField::Workspace => {
372 let child_repo =
373 repository_factory::write::create_workspace_repository(self.transaction)?;
374 let found = child_repo.get_multi(&all_right_ids)?;
375 let missing: Vec<_> = all_right_ids
376 .iter()
377 .zip(found.iter())
378 .filter(|(_, entity)| entity.is_none())
379 .map(|(id, _)| *id)
380 .collect();
381 if !missing.is_empty() {
382 return Err(RepositoryError::MissingRelationshipTarget {
383 operation: "set_relationship_multi",
384 ids: missing,
385 });
386 }
387 }
388 }
389 }
390 self.table
391 .set_relationship_multi(field, relationships.clone())?;
392 for (left_id, right_ids) in relationships {
393 event_buffer.push(Event {
394 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
395 ids: vec![left_id],
396 data: Some(format!(
397 "{}:{}",
398 field,
399 right_ids
400 .iter()
401 .map(|id| id.to_string())
402 .collect::<Vec<_>>()
403 .join(",")
404 )),
405 });
406 }
407 Ok(())
408 }
409
410 pub fn set_relationship(
411 &mut self,
412 event_buffer: &mut EventBuffer,
413 id: &EntityId,
414 field: &RootRelationshipField,
415 right_ids: &[EntityId],
416 ) -> Result<(), RepositoryError> {
417 if !right_ids.is_empty() {
419 match field {
420 RootRelationshipField::System => {
421 let child_repo =
422 repository_factory::write::create_system_repository(self.transaction)?;
423 let found = child_repo.get_multi(right_ids)?;
424 let missing: Vec<_> = right_ids
425 .iter()
426 .zip(found.iter())
427 .filter(|(_, entity)| entity.is_none())
428 .map(|(id, _)| *id)
429 .collect();
430 if !missing.is_empty() {
431 return Err(RepositoryError::MissingRelationshipTarget {
432 operation: "set_relationship",
433 ids: missing,
434 });
435 }
436 }
437 RootRelationshipField::Workspace => {
438 let child_repo =
439 repository_factory::write::create_workspace_repository(self.transaction)?;
440 let found = child_repo.get_multi(right_ids)?;
441 let missing: Vec<_> = right_ids
442 .iter()
443 .zip(found.iter())
444 .filter(|(_, entity)| entity.is_none())
445 .map(|(id, _)| *id)
446 .collect();
447 if !missing.is_empty() {
448 return Err(RepositoryError::MissingRelationshipTarget {
449 operation: "set_relationship",
450 ids: missing,
451 });
452 }
453 }
454 }
455 }
456 self.table.set_relationship(id, field, right_ids)?;
457 event_buffer.push(Event {
458 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
459 ids: vec![*id],
460 data: Some(format!(
461 "{}:{}",
462 field,
463 right_ids
464 .iter()
465 .map(|id| id.to_string())
466 .collect::<Vec<_>>()
467 .join(",")
468 )),
469 });
470 Ok(())
471 }
472
473 pub fn move_relationship_ids(
474 &mut self,
475 event_buffer: &mut EventBuffer,
476 id: &EntityId,
477 field: &RootRelationshipField,
478 ids_to_move: &[EntityId],
479 new_index: i32,
480 ) -> Result<Vec<EntityId>, RepositoryError> {
481 let reordered = self
482 .table
483 .move_relationship_ids(id, field, ids_to_move, new_index)?;
484 event_buffer.push(Event {
485 origin: Origin::DirectAccess(DirectAccessEntity::Root(EntityEvent::Updated)),
486 ids: vec![*id],
487 data: Some(format!(
488 "{}:{}",
489 field,
490 reordered
491 .iter()
492 .map(|id| id.to_string())
493 .collect::<Vec<_>>()
494 .join(",")
495 )),
496 });
497 Ok(reordered)
498 }
499
500 pub fn snapshot(&self, _ids: &[EntityId]) -> Result<EntityTreeSnapshot, RepositoryError> {
501 let store_snap = self.transaction.snapshot_store();
502 Ok(EntityTreeSnapshot {
503 store_snapshot: Some(store_snap),
504 })
505 }
506
507 pub fn restore(
508 &mut self,
509 event_buffer: &mut EventBuffer,
510 snap: &EntityTreeSnapshot,
511 ) -> Result<(), RepositoryError> {
512 let store_snap = snap
513 .store_snapshot
514 .as_ref()
515 .ok_or_else(|| RepositoryError::Serialization("missing store snapshot".into()))?;
516 self.transaction.restore_store(store_snap);
517
518 let store = self.transaction.get_store();
519
520 let mut emit = |entity: DirectAccessEntity, ids: Vec<EntityId>| {
521 if !ids.is_empty() {
522 event_buffer.push(Event {
523 origin: Origin::DirectAccess(entity),
524 ids,
525 data: None,
526 });
527 }
528 };
529
530 let root_ids: Vec<_> = store.roots.read().unwrap().keys().copied().collect();
532 emit(
533 DirectAccessEntity::Root(EntityEvent::Created),
534 root_ids.clone(),
535 );
536 emit(DirectAccessEntity::Root(EntityEvent::Updated), root_ids);
537
538 {
541 let child_ids: Vec<_> = store.workspaces.read().unwrap().keys().copied().collect();
542 emit(
543 DirectAccessEntity::Workspace(EntityEvent::Created),
544 child_ids.clone(),
545 );
546 emit(
547 DirectAccessEntity::Workspace(EntityEvent::Updated),
548 child_ids,
549 );
550 }
551 {
552 let child_ids: Vec<_> = store.systems.read().unwrap().keys().copied().collect();
553 emit(
554 DirectAccessEntity::System(EntityEvent::Created),
555 child_ids.clone(),
556 );
557 emit(DirectAccessEntity::System(EntityEvent::Updated), child_ids);
558 }
559
560 Ok(())
561 }
562}
563
564pub struct RootRepositoryRO<'a> {
565 table: Box<dyn RootTableRO + 'a>,
566}
567impl<'a> RootRepositoryRO<'a> {
568 pub fn new(table: Box<dyn RootTableRO + 'a>) -> Self {
569 RootRepositoryRO { table }
570 }
571 pub fn get(&self, id: &EntityId) -> Result<Option<Root>, RepositoryError> {
572 self.table.get(id)
573 }
574 pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Root>>, RepositoryError> {
575 self.table.get_multi(ids)
576 }
577 pub fn get_all(&self) -> Result<Vec<Root>, RepositoryError> {
578 self.table.get_all()
579 }
580 pub fn get_relationship(
581 &self,
582 id: &EntityId,
583 field: &RootRelationshipField,
584 ) -> Result<Vec<EntityId>, RepositoryError> {
585 self.table.get_relationship(id, field)
586 }
587 pub fn get_relationship_many(
588 &self,
589 ids: &[EntityId],
590 field: &RootRelationshipField,
591 ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
592 self.table.get_relationship_many(ids, field)
593 }
594 pub fn get_relationship_count(
595 &self,
596 id: &EntityId,
597 field: &RootRelationshipField,
598 ) -> Result<usize, RepositoryError> {
599 self.table.get_relationship_count(id, field)
600 }
601 pub fn get_relationship_in_range(
602 &self,
603 id: &EntityId,
604 field: &RootRelationshipField,
605 offset: usize,
606 limit: usize,
607 ) -> Result<Vec<EntityId>, RepositoryError> {
608 self.table
609 .get_relationship_in_range(id, field, offset, limit)
610 }
611 pub fn get_relationships_from_right_ids(
612 &self,
613 field: &RootRelationshipField,
614 right_ids: &[EntityId],
615 ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
616 self.table
617 .get_relationships_from_right_ids(field, right_ids)
618 }
619}