Skip to main content

text_document_common/direct_access/frame/
frame_repository.rs

1// Generated by Qleany v1.5.1 from common_entity_repository.tera
2
3use std::fmt::Display;
4
5use crate::{
6    database::transactions::Transaction,
7    direct_access::repository_factory,
8    entities::Frame,
9    event::{DirectAccessEntity, EntityEvent, Event, EventBuffer, Origin},
10    snapshot::EntityTreeSnapshot,
11    types::EntityId,
12};
13
14use crate::direct_access::document::DocumentRelationshipField;
15use crate::error::RepositoryError;
16use serde::{Deserialize, Serialize};
17
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
19pub enum FrameRelationshipField {
20    Blocks,
21    ParentFrame,
22    Table,
23}
24
25impl Display for FrameRelationshipField {
26    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
27        write!(f, "{:?}", self)
28    }
29}
30
31pub trait FrameTable {
32    fn create(&mut self, entity: &Frame) -> Result<Frame, RepositoryError>;
33    fn create_multi(&mut self, entities: &[Frame]) -> Result<Vec<Frame>, RepositoryError>;
34    fn get(&self, id: &EntityId) -> Result<Option<Frame>, RepositoryError>;
35    fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Frame>>, RepositoryError>;
36    fn get_all(&self) -> Result<Vec<Frame>, RepositoryError>;
37    fn update(&mut self, entity: &Frame) -> Result<Frame, RepositoryError>;
38    fn update_multi(&mut self, entities: &[Frame]) -> Result<Vec<Frame>, RepositoryError>;
39    fn update_with_relationships(&mut self, entity: &Frame) -> Result<Frame, RepositoryError>;
40    fn update_with_relationships_multi(
41        &mut self,
42        entities: &[Frame],
43    ) -> Result<Vec<Frame>, RepositoryError>;
44    fn remove(&mut self, id: &EntityId) -> Result<(), RepositoryError>;
45    fn remove_multi(&mut self, ids: &[EntityId]) -> Result<(), RepositoryError>;
46    fn get_relationship(
47        &self,
48        id: &EntityId,
49        field: &FrameRelationshipField,
50    ) -> Result<Vec<EntityId>, RepositoryError>;
51    fn get_relationship_many(
52        &self,
53        ids: &[EntityId],
54        field: &FrameRelationshipField,
55    ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
56    fn get_relationship_count(
57        &self,
58        id: &EntityId,
59        field: &FrameRelationshipField,
60    ) -> Result<usize, RepositoryError>;
61    fn get_relationship_in_range(
62        &self,
63        id: &EntityId,
64        field: &FrameRelationshipField,
65        offset: usize,
66        limit: usize,
67    ) -> Result<Vec<EntityId>, RepositoryError>;
68    fn get_relationships_from_right_ids(
69        &self,
70        field: &FrameRelationshipField,
71        right_ids: &[EntityId],
72    ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
73    fn set_relationship_multi(
74        &mut self,
75        field: &FrameRelationshipField,
76        relationships: Vec<(EntityId, Vec<EntityId>)>,
77    ) -> Result<(), RepositoryError>;
78    fn set_relationship(
79        &mut self,
80        id: &EntityId,
81        field: &FrameRelationshipField,
82        right_ids: &[EntityId],
83    ) -> Result<(), RepositoryError>;
84    fn move_relationship_ids(
85        &mut self,
86        id: &EntityId,
87        field: &FrameRelationshipField,
88        ids_to_move: &[EntityId],
89        new_index: i32,
90    ) -> Result<Vec<EntityId>, RepositoryError>;
91}
92
93pub trait FrameTableRO {
94    fn get(&self, id: &EntityId) -> Result<Option<Frame>, RepositoryError>;
95    fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Frame>>, RepositoryError>;
96    fn get_all(&self) -> Result<Vec<Frame>, RepositoryError>;
97    fn get_relationship(
98        &self,
99        id: &EntityId,
100        field: &FrameRelationshipField,
101    ) -> Result<Vec<EntityId>, RepositoryError>;
102    fn get_relationship_many(
103        &self,
104        ids: &[EntityId],
105        field: &FrameRelationshipField,
106    ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError>;
107    fn get_relationship_count(
108        &self,
109        id: &EntityId,
110        field: &FrameRelationshipField,
111    ) -> Result<usize, RepositoryError>;
112    fn get_relationship_in_range(
113        &self,
114        id: &EntityId,
115        field: &FrameRelationshipField,
116        offset: usize,
117        limit: usize,
118    ) -> Result<Vec<EntityId>, RepositoryError>;
119    fn get_relationships_from_right_ids(
120        &self,
121        field: &FrameRelationshipField,
122        right_ids: &[EntityId],
123    ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError>;
124}
125
126pub struct FrameRepository<'a> {
127    redb_table: Box<dyn FrameTable + 'a>,
128    transaction: &'a Transaction,
129}
130
131impl<'a> FrameRepository<'a> {
132    pub fn new(redb_table: Box<dyn FrameTable + 'a>, transaction: &'a Transaction) -> Self {
133        FrameRepository {
134            redb_table,
135            transaction,
136        }
137    }
138
139    pub fn create_orphan(
140        &mut self,
141        event_buffer: &mut EventBuffer,
142        entity: &Frame,
143    ) -> Result<Frame, RepositoryError> {
144        let new = self.redb_table.create(entity)?;
145        event_buffer.push(Event {
146            origin: Origin::DirectAccess(DirectAccessEntity::Frame(EntityEvent::Created)),
147            ids: vec![new.id],
148            data: None,
149        });
150        Ok(new)
151    }
152
153    pub fn create_orphan_multi(
154        &mut self,
155        event_buffer: &mut EventBuffer,
156        entities: &[Frame],
157    ) -> Result<Vec<Frame>, RepositoryError> {
158        let new_entities = self.redb_table.create_multi(entities)?;
159        event_buffer.push(Event {
160            origin: Origin::DirectAccess(DirectAccessEntity::Frame(EntityEvent::Created)),
161            ids: new_entities.iter().map(|e| e.id).collect(),
162            data: None,
163        });
164        Ok(new_entities)
165    }
166    pub fn create(
167        &mut self,
168        event_buffer: &mut EventBuffer,
169        entity: &Frame,
170        owner_id: EntityId,
171        index: i32,
172    ) -> Result<Frame, RepositoryError> {
173        let new = self.redb_table.create(entity)?;
174        let created_id = new.id;
175
176        let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
177        // Insert at index
178        if index >= 0 && (index as usize) < relationship_ids.len() {
179            relationship_ids.insert(index as usize, created_id);
180        } else {
181            relationship_ids.push(created_id);
182        }
183
184        self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
185        event_buffer.push(Event {
186            origin: Origin::DirectAccess(DirectAccessEntity::Frame(EntityEvent::Created)),
187            ids: vec![created_id],
188            data: None,
189        });
190        Ok(new)
191    }
192
193    pub fn create_multi(
194        &mut self,
195        event_buffer: &mut EventBuffer,
196        entities: &[Frame],
197        owner_id: EntityId,
198        index: i32,
199    ) -> Result<Vec<Frame>, RepositoryError> {
200        let new_entities = self.redb_table.create_multi(entities)?;
201        let created_ids: Vec<EntityId> = new_entities.iter().map(|e| e.id).collect();
202
203        let mut relationship_ids = self.get_relationships_from_owner(&owner_id)?;
204        if index >= 0 && (index as usize) < relationship_ids.len() {
205            for (i, id) in created_ids.iter().enumerate() {
206                relationship_ids.insert(index as usize + i, *id);
207            }
208        } else {
209            relationship_ids.extend(created_ids.iter());
210        }
211
212        self.set_relationships_in_owner(event_buffer, &owner_id, &relationship_ids)?;
213        event_buffer.push(Event {
214            origin: Origin::DirectAccess(DirectAccessEntity::Frame(EntityEvent::Created)),
215            ids: created_ids,
216            data: None,
217        });
218        Ok(new_entities)
219    }
220
221    pub fn get(&self, id: &EntityId) -> Result<Option<Frame>, RepositoryError> {
222        self.redb_table.get(id)
223    }
224    pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Frame>>, RepositoryError> {
225        self.redb_table.get_multi(ids)
226    }
227    pub fn get_all(&self) -> Result<Vec<Frame>, RepositoryError> {
228        self.redb_table.get_all()
229    }
230
231    pub fn update(
232        &mut self,
233        event_buffer: &mut EventBuffer,
234        entity: &Frame,
235    ) -> Result<Frame, RepositoryError> {
236        let updated = self.redb_table.update(entity)?;
237        event_buffer.push(Event {
238            origin: Origin::DirectAccess(DirectAccessEntity::Frame(EntityEvent::Updated)),
239            ids: vec![updated.id],
240            data: None,
241        });
242        Ok(updated)
243    }
244
245    pub fn update_multi(
246        &mut self,
247        event_buffer: &mut EventBuffer,
248        entities: &[Frame],
249    ) -> Result<Vec<Frame>, RepositoryError> {
250        let updated = self.redb_table.update_multi(entities)?;
251        event_buffer.push(Event {
252            origin: Origin::DirectAccess(DirectAccessEntity::Frame(EntityEvent::Updated)),
253            ids: updated.iter().map(|e| e.id).collect(),
254            data: None,
255        });
256        Ok(updated)
257    }
258
259    pub fn update_with_relationships(
260        &mut self,
261        event_buffer: &mut EventBuffer,
262        entity: &Frame,
263    ) -> Result<Frame, RepositoryError> {
264        let updated = self.redb_table.update_with_relationships(entity)?;
265        event_buffer.push(Event {
266            origin: Origin::DirectAccess(DirectAccessEntity::Frame(EntityEvent::Updated)),
267            ids: vec![updated.id],
268            data: None,
269        });
270        Ok(updated)
271    }
272
273    pub fn update_with_relationships_multi(
274        &mut self,
275        event_buffer: &mut EventBuffer,
276        entities: &[Frame],
277    ) -> Result<Vec<Frame>, RepositoryError> {
278        let updated = self.redb_table.update_with_relationships_multi(entities)?;
279        event_buffer.push(Event {
280            origin: Origin::DirectAccess(DirectAccessEntity::Frame(EntityEvent::Updated)),
281            ids: updated.iter().map(|e| e.id).collect(),
282            data: None,
283        });
284        Ok(updated)
285    }
286
287    pub fn remove(
288        &mut self,
289        event_buffer: &mut EventBuffer,
290        id: &EntityId,
291    ) -> Result<(), RepositoryError> {
292        let entity = match self.redb_table.get(id)? {
293            Some(e) => e,
294            None => return Ok(()),
295        };
296        // get all strong forward relationship fields
297
298        let blocks = entity.blocks.clone();
299
300        // remove all strong relationships, initiating a cascade remove
301
302        repository_factory::write::create_block_repository(self.transaction)
303            .remove_multi(event_buffer, &blocks)?;
304        // Before removal, find which owner(s) reference this entity
305        let affected_owner_ids: Vec<EntityId> = {
306            let owner_repo =
307                repository_factory::write::create_document_repository(self.transaction);
308            owner_repo
309                .get_relationships_from_right_ids(&DocumentRelationshipField::Frames, &[*id])?
310                .into_iter()
311                .map(|(owner_id, _)| owner_id)
312                .collect()
313        };
314        // Save each owner's current relationship IDs (properly ordered via get_relationships_from_owner)
315        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        // remove entity
322        self.redb_table.remove(id)?;
323        event_buffer.push(Event {
324            origin: Origin::DirectAccess(DirectAccessEntity::Frame(EntityEvent::Removed)),
325            ids: vec![*id],
326            data: None,
327        });
328        // Update each affected owner's relationship to exclude removed ID (emits Updated event)
329        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.redb_table.get_multi(ids)?;
346        if entities.is_empty() || entities.iter().all(|e| e.is_none()) {
347            return Ok(());
348        }
349
350        // get all strong forward relationship fields
351
352        let mut blocks_ids: Vec<EntityId> = entities
353            .iter()
354            .flat_map(|entity| entity.as_ref().map(|entity| entity.blocks.clone()))
355            .flatten()
356            .collect();
357        // remove duplicates
358        blocks_ids.sort();
359        blocks_ids.dedup();
360
361        // remove all strong relationships, initiating a cascade remove
362
363        repository_factory::write::create_block_repository(self.transaction)
364            .remove_multi(event_buffer, &blocks_ids)?;
365        // Before removal, find which owner(s) reference these entities
366        let affected_owner_ids: Vec<EntityId> = {
367            let owner_repo =
368                repository_factory::write::create_document_repository(self.transaction);
369            owner_repo
370                .get_relationships_from_right_ids(&DocumentRelationshipField::Frames, ids)?
371                .into_iter()
372                .map(|(owner_id, _)| owner_id)
373                .collect()
374        };
375        // Save each owner's current relationship IDs (properly ordered via get_relationships_from_owner)
376        let mut owner_rel_before: std::collections::HashMap<EntityId, Vec<EntityId>> =
377            std::collections::HashMap::new();
378        for owner_id in &affected_owner_ids {
379            owner_rel_before.insert(*owner_id, self.get_relationships_from_owner(owner_id)?);
380        }
381
382        self.redb_table.remove_multi(ids)?;
383        event_buffer.push(Event {
384            origin: Origin::DirectAccess(DirectAccessEntity::Frame(EntityEvent::Removed)),
385            ids: ids.into(),
386            data: None,
387        });
388        // Update each affected owner's relationship to exclude removed IDs (emits Updated event)
389        {
390            let removed_set: std::collections::HashSet<EntityId> = ids.iter().copied().collect();
391            for owner_id in &affected_owner_ids {
392                if let Some(rel_ids) = owner_rel_before.get(owner_id) {
393                    let updated: Vec<EntityId> = rel_ids
394                        .iter()
395                        .copied()
396                        .filter(|rid| !removed_set.contains(rid))
397                        .collect();
398                    self.set_relationships_in_owner(event_buffer, owner_id, &updated)?;
399                }
400            }
401        }
402
403        Ok(())
404    }
405    pub fn get_relationship(
406        &self,
407        id: &EntityId,
408        field: &FrameRelationshipField,
409    ) -> Result<Vec<EntityId>, RepositoryError> {
410        self.redb_table.get_relationship(id, field)
411    }
412    pub fn get_relationship_many(
413        &self,
414        ids: &[EntityId],
415        field: &FrameRelationshipField,
416    ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
417        self.redb_table.get_relationship_many(ids, field)
418    }
419    pub fn get_relationship_count(
420        &self,
421        id: &EntityId,
422        field: &FrameRelationshipField,
423    ) -> Result<usize, RepositoryError> {
424        self.redb_table.get_relationship_count(id, field)
425    }
426    pub fn get_relationship_in_range(
427        &self,
428        id: &EntityId,
429        field: &FrameRelationshipField,
430        offset: usize,
431        limit: usize,
432    ) -> Result<Vec<EntityId>, RepositoryError> {
433        self.redb_table
434            .get_relationship_in_range(id, field, offset, limit)
435    }
436    pub fn get_relationships_from_right_ids(
437        &self,
438        field: &FrameRelationshipField,
439        right_ids: &[EntityId],
440    ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
441        self.redb_table
442            .get_relationships_from_right_ids(field, right_ids)
443    }
444
445    pub fn set_relationship_multi(
446        &mut self,
447        event_buffer: &mut EventBuffer,
448        field: &FrameRelationshipField,
449        relationships: Vec<(EntityId, Vec<EntityId>)>,
450    ) -> Result<(), RepositoryError> {
451        // Validate that all right_ids exist
452        let all_right_ids: Vec<EntityId> = relationships
453            .iter()
454            .flat_map(|(_, ids)| ids.iter().copied())
455            .collect();
456        if !all_right_ids.is_empty() {
457            match field {
458                FrameRelationshipField::Blocks => {
459                    let child_repo =
460                        repository_factory::write::create_block_repository(self.transaction);
461                    let found = child_repo.get_multi(&all_right_ids)?;
462                    let missing: Vec<_> = all_right_ids
463                        .iter()
464                        .zip(found.iter())
465                        .filter(|(_, entity)| entity.is_none())
466                        .map(|(id, _)| *id)
467                        .collect();
468                    if !missing.is_empty() {
469                        return Err(RepositoryError::MissingRelationshipTarget {
470                            operation: "set_relationship_multi",
471                            ids: missing,
472                        });
473                    }
474                }
475                FrameRelationshipField::ParentFrame => {
476                    let child_repo =
477                        repository_factory::write::create_frame_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                FrameRelationshipField::Table => {
493                    let child_repo =
494                        repository_factory::write::create_table_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            }
510        }
511        self.redb_table
512            .set_relationship_multi(field, relationships.clone())?;
513        for (left_id, right_ids) in relationships {
514            event_buffer.push(Event {
515                origin: Origin::DirectAccess(DirectAccessEntity::Frame(EntityEvent::Updated)),
516                ids: vec![left_id],
517                data: Some(format!(
518                    "{}:{}",
519                    field,
520                    right_ids
521                        .iter()
522                        .map(|id| id.to_string())
523                        .collect::<Vec<_>>()
524                        .join(",")
525                )),
526            });
527        }
528        Ok(())
529    }
530
531    pub fn set_relationship(
532        &mut self,
533        event_buffer: &mut EventBuffer,
534        id: &EntityId,
535        field: &FrameRelationshipField,
536        right_ids: &[EntityId],
537    ) -> Result<(), RepositoryError> {
538        // Validate that all right_ids exist
539        if !right_ids.is_empty() {
540            match field {
541                FrameRelationshipField::Blocks => {
542                    let child_repo =
543                        repository_factory::write::create_block_repository(self.transaction);
544                    let found = child_repo.get_multi(right_ids)?;
545                    let missing: Vec<_> = right_ids
546                        .iter()
547                        .zip(found.iter())
548                        .filter(|(_, entity)| entity.is_none())
549                        .map(|(id, _)| *id)
550                        .collect();
551                    if !missing.is_empty() {
552                        return Err(RepositoryError::MissingRelationshipTarget {
553                            operation: "set_relationship",
554                            ids: missing,
555                        });
556                    }
557                }
558                FrameRelationshipField::ParentFrame => {
559                    let child_repo =
560                        repository_factory::write::create_frame_repository(self.transaction);
561                    let found = child_repo.get_multi(right_ids)?;
562                    let missing: Vec<_> = right_ids
563                        .iter()
564                        .zip(found.iter())
565                        .filter(|(_, entity)| entity.is_none())
566                        .map(|(id, _)| *id)
567                        .collect();
568                    if !missing.is_empty() {
569                        return Err(RepositoryError::MissingRelationshipTarget {
570                            operation: "set_relationship",
571                            ids: missing,
572                        });
573                    }
574                }
575                FrameRelationshipField::Table => {
576                    let child_repo =
577                        repository_factory::write::create_table_repository(self.transaction);
578                    let found = child_repo.get_multi(right_ids)?;
579                    let missing: Vec<_> = right_ids
580                        .iter()
581                        .zip(found.iter())
582                        .filter(|(_, entity)| entity.is_none())
583                        .map(|(id, _)| *id)
584                        .collect();
585                    if !missing.is_empty() {
586                        return Err(RepositoryError::MissingRelationshipTarget {
587                            operation: "set_relationship",
588                            ids: missing,
589                        });
590                    }
591                }
592            }
593        }
594        self.redb_table.set_relationship(id, field, right_ids)?;
595        event_buffer.push(Event {
596            origin: Origin::DirectAccess(DirectAccessEntity::Frame(EntityEvent::Updated)),
597            ids: vec![*id],
598            data: Some(format!(
599                "{}:{}",
600                field,
601                right_ids
602                    .iter()
603                    .map(|id| id.to_string())
604                    .collect::<Vec<_>>()
605                    .join(",")
606            )),
607        });
608        Ok(())
609    }
610
611    pub fn move_relationship_ids(
612        &mut self,
613        event_buffer: &mut EventBuffer,
614        id: &EntityId,
615        field: &FrameRelationshipField,
616        ids_to_move: &[EntityId],
617        new_index: i32,
618    ) -> Result<Vec<EntityId>, RepositoryError> {
619        let reordered = self
620            .redb_table
621            .move_relationship_ids(id, field, ids_to_move, new_index)?;
622        event_buffer.push(Event {
623            origin: Origin::DirectAccess(DirectAccessEntity::Frame(EntityEvent::Updated)),
624            ids: vec![*id],
625            data: Some(format!(
626                "{}:{}",
627                field,
628                reordered
629                    .iter()
630                    .map(|id| id.to_string())
631                    .collect::<Vec<_>>()
632                    .join(",")
633            )),
634        });
635        Ok(reordered)
636    }
637    pub fn get_relationships_from_owner(
638        &self,
639        owner_id: &EntityId,
640    ) -> Result<Vec<EntityId>, RepositoryError> {
641        let repo = repository_factory::write::create_document_repository(self.transaction);
642        repo.get_relationship(owner_id, &DocumentRelationshipField::Frames)
643    }
644
645    pub fn set_relationships_in_owner(
646        &mut self,
647        event_buffer: &mut EventBuffer,
648        owner_id: &EntityId,
649        ids: &[EntityId],
650    ) -> Result<(), RepositoryError> {
651        let mut repo = repository_factory::write::create_document_repository(self.transaction);
652        repo.set_relationship(
653            event_buffer,
654            owner_id,
655            &DocumentRelationshipField::Frames,
656            ids,
657        )
658    }
659
660    pub fn snapshot(&self, _ids: &[EntityId]) -> Result<EntityTreeSnapshot, RepositoryError> {
661        let store_snap = self.transaction.snapshot_store();
662        Ok(EntityTreeSnapshot {
663            store_snapshot: Some(store_snap),
664        })
665    }
666
667    pub fn restore(
668        &mut self,
669        event_buffer: &mut EventBuffer,
670        snap: &EntityTreeSnapshot,
671    ) -> Result<(), RepositoryError> {
672        let store_snap = snap
673            .store_snapshot
674            .as_ref()
675            .ok_or_else(|| RepositoryError::Serialization("missing store snapshot".into()))?;
676        self.transaction.restore_store(store_snap);
677
678        let store = self.transaction.get_store();
679
680        let mut emit = |entity: DirectAccessEntity, ids: Vec<EntityId>| {
681            if !ids.is_empty() {
682                event_buffer.push(Event {
683                    origin: Origin::DirectAccess(entity),
684                    ids,
685                    data: None,
686                });
687            }
688        };
689
690        // Frame: Created + Updated (has Blocks, ParentFrame, Table relationships)
691        let frame_ids: Vec<_> = store.frames.read().unwrap().keys().copied().collect();
692        emit(
693            DirectAccessEntity::Frame(EntityEvent::Created),
694            frame_ids.clone(),
695        );
696        emit(DirectAccessEntity::Frame(EntityEvent::Updated), frame_ids);
697
698        // Block: Created + Updated (strong child, has Elements, List relationships)
699        let block_ids: Vec<_> = store.blocks.read().unwrap().keys().copied().collect();
700        emit(
701            DirectAccessEntity::Block(EntityEvent::Created),
702            block_ids.clone(),
703        );
704        emit(DirectAccessEntity::Block(EntityEvent::Updated), block_ids);
705
706        // InlineElement: Created only (leaf, strong child of Block)
707        let elem_ids: Vec<_> = store
708            .inline_elements
709            .read()
710            .unwrap()
711            .keys()
712            .copied()
713            .collect();
714        emit(
715            DirectAccessEntity::InlineElement(EntityEvent::Created),
716            elem_ids,
717        );
718
719        Ok(())
720    }
721}
722
723pub struct FrameRepositoryRO<'a> {
724    redb_table: Box<dyn FrameTableRO + 'a>,
725}
726impl<'a> FrameRepositoryRO<'a> {
727    pub fn new(redb_table: Box<dyn FrameTableRO + 'a>) -> Self {
728        FrameRepositoryRO { redb_table }
729    }
730    pub fn get(&self, id: &EntityId) -> Result<Option<Frame>, RepositoryError> {
731        self.redb_table.get(id)
732    }
733    pub fn get_multi(&self, ids: &[EntityId]) -> Result<Vec<Option<Frame>>, RepositoryError> {
734        self.redb_table.get_multi(ids)
735    }
736    pub fn get_all(&self) -> Result<Vec<Frame>, RepositoryError> {
737        self.redb_table.get_all()
738    }
739    pub fn get_relationship(
740        &self,
741        id: &EntityId,
742        field: &FrameRelationshipField,
743    ) -> Result<Vec<EntityId>, RepositoryError> {
744        self.redb_table.get_relationship(id, field)
745    }
746    pub fn get_relationship_many(
747        &self,
748        ids: &[EntityId],
749        field: &FrameRelationshipField,
750    ) -> Result<std::collections::HashMap<EntityId, Vec<EntityId>>, RepositoryError> {
751        self.redb_table.get_relationship_many(ids, field)
752    }
753    pub fn get_relationship_count(
754        &self,
755        id: &EntityId,
756        field: &FrameRelationshipField,
757    ) -> Result<usize, RepositoryError> {
758        self.redb_table.get_relationship_count(id, field)
759    }
760    pub fn get_relationship_in_range(
761        &self,
762        id: &EntityId,
763        field: &FrameRelationshipField,
764        offset: usize,
765        limit: usize,
766    ) -> Result<Vec<EntityId>, RepositoryError> {
767        self.redb_table
768            .get_relationship_in_range(id, field, offset, limit)
769    }
770    pub fn get_relationships_from_right_ids(
771        &self,
772        field: &FrameRelationshipField,
773        right_ids: &[EntityId],
774    ) -> Result<Vec<(EntityId, Vec<EntityId>)>, RepositoryError> {
775        self.redb_table
776            .get_relationships_from_right_ids(field, right_ids)
777    }
778}