Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions detectmatelibrary_tests/test_utils/test_persistency_saver.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,23 @@ def test_auto_load_on_init_no_state_starts_fresh(self):
assert saver is not None


class TestPersistencySaverGetStatus:
def test_config_fields(self):
p = EventPersistency(event_data_class=EventDataFrame)
cfg = PersistencySaverConfig(
path="memory://status_test3/state",
save_interval_seconds=120,
events_until_save=500,
auto_load=True,
)
saver = PersistencySaver(p, cfg)
status = saver.get_status()
assert status["path"] == "memory://status_test3/state"
assert status["save_interval_seconds"] == 120
assert status["events_until_save"] == 500
assert status["auto_load"] is True


class TestPersistencySaverIntegration:
def test_full_cycle_dataframe_backend(self):
"""Train → save → restore → verify data identical."""
Expand Down
5 changes: 5 additions & 0 deletions src/detectmatelibrary/utils/persistency/event_persistency.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ def ingest_event(
data = data_structure.to_data(all_variables)
data_structure.add_data(data)

@property
def events_since_save(self) -> int:
"""Number of events ingested since the last successful save."""
return self._events_since_save

def reset_events_since_save(self) -> None:
"""Reset the events-since-save counter after a successful save."""
self._events_since_save = 0
Expand Down
27 changes: 27 additions & 0 deletions src/detectmatelibrary/utils/persistency/persistency_saver.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,33 @@ def stop(self) -> None:
atexit.unregister(self.stop)
self.save()

def get_status(self) -> dict[str, Any]:
"""Return a snapshot of the current persistency state.

Reads last_saved_at from metadata.json if present. A missing or
unreadable metadata file is tolerated
"""
ep = self._persistency
last_saved_at: str | None = None
try:
meta_path = f"{self._root}/metadata.json"
if self._fs.exists(meta_path):
with self._fs.open(meta_path, "r") as f:
meta = json.load(f)
last_saved_at = meta.get("saved_at")
except Exception as e:
logger.warning(f"PersistencySaver.get_status: could not read metadata.json — {e}")
return {
"path": self._config.path,
"save_interval_seconds": self._config.save_interval_seconds,
"events_until_save": self._config.events_until_save,
"auto_load": self._config.auto_load,
"events_seen_count": len(ep.get_events_seen()),
"events_with_data_count": len(ep.get_events_data()),
"events_since_save": ep.events_since_save,
"last_saved_at": last_saved_at,
}

def _safe_event_data_kwargs(self) -> dict[str, Any]:
"""Return event_data_kwargs with non-JSON-serializable values
excluded."""
Expand Down
Loading