diff --git a/reme/components/file_store/local_file_store.py b/reme/components/file_store/local_file_store.py index 37bdb0fc..757b7038 100644 --- a/reme/components/file_store/local_file_store.py +++ b/reme/components/file_store/local_file_store.py @@ -103,8 +103,12 @@ class LocalFileStore(BaseFileStore): # Dependencies are closed separately by Application (reverse # topological order) or BaseComponent (owned standalone dependencies). # Persist only this store's local state here so each component writes - # exactly once during shutdown. - await self._dump_owned_state() + # exactly once during shutdown. Preserve the historical dump() hook for + # third-party subclasses that override it to write additional state. + if type(self).dump is LocalFileStore.dump: + await self._dump_owned_state() + else: + await self.dump() self.file_chunks.clear() await super()._close() diff --git a/tests/unit/test_file_store_consistency.py b/tests/unit/test_file_store_consistency.py index d7fdda97..eb693bdb 100644 --- a/tests/unit/test_file_store_consistency.py +++ b/tests/unit/test_file_store_consistency.py @@ -319,6 +319,34 @@ def test_close_persists_each_component_once(monkeypatch): run(go()) +def test_close_preserves_subclass_dump_override(): + """Third-party stores using the historical dump hook still persist sidecars.""" + + class SidecarFileStore(LocalFileStore): + """Local store extension that persists an additional sidecar.""" + + def __init__(self): + super().__init__(name="t_sidecar_dump", embedding_store="") + self.dump_calls = 0 + self.sidecar_path = self.component_metadata_path / "sidecar.txt" + + async def dump(self) -> None: + self.dump_calls += 1 + await super().dump() + self.sidecar_path.write_text("persisted", encoding="utf-8") + + async def go(): + with tempfile.TemporaryDirectory() as tmp, temp_chdir(tmp): + store = SidecarFileStore() + await store.start() + await store.close() + + assert store.dump_calls == 1 + assert store.sidecar_path.read_text(encoding="utf-8") == "persisted" + + run(go()) + + def test_start_does_not_health_check_embedding_without_backfill(): """Hot startup keeps local vector retrieval independent of provider health."""