Changeset ea28ca0 in flexoentity


Ignore:
Timestamp:
12/05/25 12:01:08 (6 weeks ago)
Author:
Enrico Schwass <ennoausberlin@…>
Branches:
master
Children:
1f5bf2d
Parents:
753855a
Message:

use InMemoryBackend as read cache for CompositeBackends as default

Files:
8 edited

Legend:

Unmodified
Added
Removed
  • flexoentity/composite_backend.py

    r753855a rea28ca0  
    1111    """
    1212
    13     def __init__(self, entity_class, *backends):
    14         if not issubclass(entity_class, FlexoEntity):
     13    def __init__(self, authoritative_backend, sync_backends):
     14        if not issubclass(authoritative_backend.entity_class, FlexoEntity):
    1515            raise TypeError("entity_class must be a subclass of FlexOEntity")
    1616
    17         self.entity_class = entity_class
     17        self._primary = authoritative_backend
    1818
     19        self.read_backend = InMemoryBackend(self.primary.entity_class)
    1920        # Default: create an in-memory backend as the primary backend
    20         if not backends:
    21             backends = (InMemoryBackend(entity_class),)
     21
     22        if sync_backends is None:
     23            self.sync_backends = []
     24        else:
     25            self.sync_backends = sync_backends
    2226
    2327        # Validate all backends
    24         for b in backends:
    25             if getattr(b, "entity_class", None) != entity_class:
     28        for b in self.sync_backends:
     29            if b.entity_class != self.primary.entity_class:
    2630                raise TypeError(
    27                     f"Backend {b} does not match entity_class={entity_class.__name__}"
     31                    f"Backend {b} does not match entity_class={self.entity_class.__name__}"
    2832                )
    29 
    30         self.backends = list(backends)
    3133
    3234    @property
    3335    def primary(self):
    3436        """The backend used for all read operations."""
    35         return self.backends[0]
     37        return self._primary
     38
     39    @primary.setter
     40    def primary(self, new_primary):
     41        self._primary = new_primary   
    3642
    3743    def add_backend(self, backend, clear=False):
     
    4046        If clear=True, backend is wiped before syncing.
    4147        """
    42         if backend.entity_class != self.entity_class:
     48        if backend.entity_class != self.primary.entity_class:
    4349            raise TypeError("Backend entity_class mismatch")
    4450
     
    5056            backend.save(entity)
    5157
    52         self.backends.append(backend)
     58        self.sync_backends.append(backend)
    5359
    5460    def remove_backend(self, backend):
     
    5864        if backend is self.primary:
    5965            raise ValueError("Cannot remove the primary backend")
    60         self.backends.remove(backend)           
     66        self.sync_backends.remove(backend)
    6167    # ---------------------------------------------------------
    6268    # Write operations propagate to *all* backends
     
    6470
    6571    def save(self, entity):
    66         for b in self.backends:
     72        self.primary.save(entity)
     73        for b in self.sync_backends:
    6774            b.save(entity)
    6875
    6976    def update(self, entity):
    70         for b in self.backends:
     77        for b in self.sync_backends:
    7178            b.update(entity)
    7279
    7380    def delete(self, flexo_id: str):
    74         for b in self.backends:
     81        for b in self.sync_backends:
    7582            b.delete(flexo_id)
    7683
     
    94101        Useful if secondary backends were empty initially.
    95102        """
    96         primary = self.backends[0]
    97103        for entity in primary.load_all():
    98             for b in self.backends[1:]:
     104            for b in self.sync_backends:
    99105                b.save(entity)
    100106
    101107    def clear(self):
    102         for b in self.backends:
     108        self.primary.clear()
     109        for b in self.sync_backends:
    103110            if hasattr(b, "clear"):
    104111                b.clear()
     
    107114
    108115    def __repr__(self):
    109         names = ", ".join(b.__class__.__name__ for b in self.backends)
     116        names = ", ".join(b.__class__.__name__ for b in self.sync_backends)
    110117        return f"<CompositeBackend [{names}]>"
  • flexoentity/domain_manager.py

    r753855a rea28ca0  
    3939
    4040        self._rebuild_index()
     41
     42    def refresh(self):
     43        self._rebuild_index
    4144
    4245    # ------------------------------------------------------------
     
    128131    def __repr__(self):
    129132        return f"<DomainManager domains={self.all_domain_ids()}>"
    130 
  • flexoentity/in_memory_backend.py

    r753855a rea28ca0  
    1717            raise TypeError("entity_class must be a subclass of FlexOEntity")
    1818
    19         self.entity_class = entity_class
     19        super().__init__(entity_class = entity_class)
    2020        self._storage = storage if storage is not None else {}
    2121
  • flexoentity/persistance_backend.py

    r753855a rea28ca0  
    66    """
    77
    8     def save(self, entity_dict: dict) -> None:
     8    def __init__(self, entity_class):
     9        self._entity_class = entity_class
     10
     11    @property
     12    def entity_class(self):
     13        return self._entity_class
     14
     15    @entity_class.setter
     16    def entity_class(self, a_class):
     17        self._entity_class = a_class
     18
     19    def save(self, flexo_entity) -> None:
    920        raise NotImplementedError
    1021
    11     def update(self, entity_dict: dict) -> None:
     22    def update(self, flexo_entity) -> None:
    1223        raise NotImplementedError
    1324
  • flexoentity/sqlite_entity_backend.py

    r753855a rea28ca0  
    1010
    1111    def __init__(self, entity_class, conn, table_name):
     12        super().__init__(entity_class)
    1213        self.entity_class = entity_class
    1314        self.conn = conn
    1415        self.table = table_name
    1516        self._init_schema()
     17
    1618
    1719    def _init_schema(self):
  • tests/conftest.py

    r753855a rea28ca0  
    3333
    3434@pytest.fixture
    35 def sample_domain_manager():
    36     return DomainManager(CompositeBackend(Domain), EntityRegistry())
     35def sample_domain_manager(backend):
     36    return DomainManager(CompositeBackend(authoritative_backend=backend,
     37                                          sync_backends=None), EntityRegistry())
    3738
    3839# ─────────────────────────────────────────────────────────────
  • tests/test_composite_backend.py

    r753855a rea28ca0  
    88    secondary = InMemoryBackend(Domain)
    99
    10     backend = CompositeBackend(Domain, primary, secondary)
     10    backend = CompositeBackend(authoritative_backend=primary, sync_backends=[secondary])
    1111
    1212    backend.save(sample_domain)
     
    2323    secondary = InMemoryBackend(Domain)
    2424
    25     backend = CompositeBackend(Domain, primary, secondary)
     25    backend = CompositeBackend(authoritative_backend=primary, sync_backends=[secondary])
    2626
    2727    primary.save(sample_domain)
     
    3737    secondary = InMemoryBackend(Domain)
    3838
    39     backend = CompositeBackend(Domain, primary, secondary)
     39    backend = CompositeBackend(authoritative_backend=primary, sync_backends=[secondary])
    4040
    4141    backend.save(sample_domain)
  • tests/test_persistance_integrity.py

    r753855a rea28ca0  
    4949    file = tmp_path / "question.json"
    5050    json_str = approved_domain.to_json()
    51     print("JSON", json_str)
    5251    file.write_text(json_str)
    5352
Note: See TracChangeset for help on using the changeset viewer.