fix(sessions): report bulk-delete rows skipped for a live turn
delete_sessions(exclude_active_write_guards=True) dropped guarded rows silently: the web bulk-delete endpoint returned only a count and the dashboard removed every selected row optimistically, so refused rows reappeared on the next reload with no explanation. The store now appends refused ids to an optional skipped_ids list inside the same write transaction, the endpoint returns them as skipped_active, and SessionsPage keeps those rows listed. Also hoists the SessionActiveWriteGuardError imports to module top (hermes_state_errors is stdlib-only) and drops the assertion-less lineage comment in the test.
This commit is contained in:
@@ -15,6 +15,7 @@ from agent.session_activity import (
|
||||
ActivityProvenance, bound_activity_description, normalize_activity_provenance,
|
||||
)
|
||||
from hermes_startup_watchdog import report_startup_progress
|
||||
from hermes_state_errors import SessionActiveWriteGuardError
|
||||
from hermes_state_common import (
|
||||
_LISTABLE_CHILD_SQL, _PREVIEW_ELIGIBLE_SQL, _PREVIEW_RAW_SELECT, _RECOVERABLE_END_REASONS,
|
||||
_RECOVERABLE_END_REASONS_SQL, _RESET_CHILD_SQL, _RESET_END_REASONS, _legacy_reset_child_sql, _non_continuation_child_sql,
|
||||
@@ -1570,7 +1571,6 @@ class SessionSessionsMixin:
|
||||
transcript drift. Both checks run inside the same write transaction as deletion.
|
||||
With ``exclude_active_write_guards``, raises :class:`SessionActiveWriteGuardError` if the row
|
||||
is protected by an active turn lease or compression lock."""
|
||||
from hermes_state_errors import SessionActiveWriteGuardError
|
||||
removed_ids: List[str] = []
|
||||
expected_ids = set(expected_delete_ids) if expected_delete_ids is not None else None
|
||||
def _do(conn):
|
||||
@@ -1632,11 +1632,12 @@ class SessionSessionsMixin:
|
||||
|
||||
def delete_sessions(
|
||||
self, session_ids: List[str], sessions_dir: Optional[Path] = None,
|
||||
exclude_active_write_guards: bool = False,
|
||||
exclude_active_write_guards: bool = False, skipped_ids: Optional[List[str]] = None,
|
||||
) -> int:
|
||||
"""Bulk delete with :meth:`delete_session` semantics per row, in ONE transaction. Unknown ids
|
||||
are skipped (UI selection can race another tab's delete). With ``exclude_active_write_guards``,
|
||||
rows protected by an active turn lease or compression lock are skipped. Returns the number deleted."""
|
||||
rows protected by an active turn lease or compression lock are skipped and, when given, appended
|
||||
to ``skipped_ids`` so callers can tell the user. Returns the number deleted."""
|
||||
unique_ids = list({sid for sid in session_ids or () if isinstance(sid, str) and sid})
|
||||
if not unique_ids:
|
||||
return 0
|
||||
@@ -1650,6 +1651,8 @@ class SessionSessionsMixin:
|
||||
if exclude_active_write_guards:
|
||||
active_ids = {sid for sid in existing if self._write_guards_reject(conn, sid)}
|
||||
existing = [sid for sid in existing if sid not in active_ids]
|
||||
if skipped_ids is not None:
|
||||
skipped_ids.extend(sorted(active_ids))
|
||||
if not existing:
|
||||
return 0
|
||||
removed_ids.extend(_delete_delegate_children(conn, existing))
|
||||
|
||||
Reference in New Issue
Block a user