Files
roboco/tests/unit/db/test_respawn_tracker_table.py
T

53 lines
1.5 KiB
Python
Raw Normal View History

"""The respawn_tracker table — durable backing for the PM-respawn counter.
Mirrors WaitingRecordTable: a composite-PK row per (agent_slug, task_id) the
orchestrator's loop-breaker counter is keyed on, so it survives a restart
instead of resetting to count=1 and re-burning the strike threshold.
"""
from __future__ import annotations
from typing import TYPE_CHECKING, cast
from roboco.db.tables import RespawnTrackerTable
if TYPE_CHECKING:
from sqlalchemy import Table
_TABLE = cast("Table", RespawnTrackerTable.__table__)
def test_table_name() -> None:
assert RespawnTrackerTable.__tablename__ == "respawn_tracker"
def test_composite_primary_key_is_agent_slug_and_task_id() -> None:
pk_cols = {col.name for col in _TABLE.primary_key.columns}
assert pk_cols == {"agent_slug", "task_id"}
def test_payload_columns_present() -> None:
cols = set(_TABLE.columns.keys())
assert {
"agent_slug",
"task_id",
"count",
"last_status",
"last_check",
"tracing_resets",
"notified",
"updated_at",
} <= cols
def test_task_id_has_no_foreign_key() -> None:
# Deliberately NOT a FK to tasks: the startup loader validates against live
# tasks instead, so a cascade can never silently resurrect/erase a counter.
task_id = _TABLE.columns["task_id"]
assert task_id.foreign_keys == set()
def test_last_check_index_present() -> None:
index_names = {idx.name for idx in _TABLE.indexes}
assert "ix_respawn_tracker_last_check" in index_names