fix(harness): record postgres decision phases
This commit is contained in:
@@ -6,6 +6,7 @@ from sqlalchemy import create_engine, text
|
||||
from testcontainers.postgres import PostgresContainer
|
||||
|
||||
from tht.decisions import DecisionInput
|
||||
from tht.phase import effective_decisions
|
||||
from tht.session.models import PrincipalContext, SessionManifest
|
||||
from tht.session.store import SessionError
|
||||
|
||||
@@ -61,6 +62,27 @@ def test_owner_can_read_own_snapshot_but_not_another_owners(database_url):
|
||||
bob.get(session_id)
|
||||
|
||||
|
||||
def test_named_decision_is_stale_after_postgres_ledger_reopen(database_url):
|
||||
repository = _repository(database_url, "phase-owner")
|
||||
session_id = str(uuid.uuid4())
|
||||
repository.create(_manifest(session_id))
|
||||
for phase in range(1, 5):
|
||||
repository.append_decisions(session_id, [
|
||||
DecisionInput(type="phase_approved", subject=f"phase:{phase}")
|
||||
])
|
||||
repository.append_decisions(session_id, [
|
||||
DecisionInput(type="cte_approved", subject="named_cte")
|
||||
])
|
||||
repository.append_decisions(session_id, [
|
||||
DecisionInput(type="phase_reopened", subject="phase:3")
|
||||
])
|
||||
|
||||
snapshot = repository.get(session_id)
|
||||
named = next(item for item in snapshot.decisions if item.subject == "named_cte")
|
||||
assert named.phase == 5
|
||||
assert "named_cte" not in {item.subject for item in effective_decisions(snapshot)}
|
||||
|
||||
|
||||
def test_admin_can_read_another_owners_session(database_url):
|
||||
owner = _repository(database_url, "owner")
|
||||
admin = _repository(database_url, "admin", is_admin=True)
|
||||
|
||||
@@ -352,6 +352,20 @@ class PostgresSessionRepository:
|
||||
with self._transaction() as connection:
|
||||
self._lock_session(connection, session_id)
|
||||
self._require_session(connection, session_id)
|
||||
from tht.phase import current_phase
|
||||
|
||||
manifest = SessionManifest.model_validate(connection.execute(
|
||||
text("SELECT manifest FROM thoth_sessions.sessions WHERE id = :id"), {"id": session_id}
|
||||
).scalar_one())
|
||||
ledger = [
|
||||
DecisionRecord.model_validate(dict(item))
|
||||
for item in connection.execute(
|
||||
text("SELECT seq, ts, phase, type, subject, detail, rationale, retracts "
|
||||
"FROM thoth_sessions.review_decisions WHERE session_id = :id ORDER BY seq"),
|
||||
{"id": session_id},
|
||||
).mappings()
|
||||
]
|
||||
phase = current_phase(SessionSnapshot(manifest=manifest, decisions=ledger))
|
||||
next_seq = connection.execute(
|
||||
text(
|
||||
"SELECT COALESCE(MAX(seq), 0) + 1 FROM thoth_sessions.review_decisions "
|
||||
@@ -361,7 +375,7 @@ class PostgresSessionRepository:
|
||||
).scalar_one()
|
||||
now = datetime.now(UTC)
|
||||
records = [
|
||||
DecisionRecord(seq=next_seq + offset, ts=now, phase=None, **item.model_dump())
|
||||
DecisionRecord(seq=next_seq + offset, ts=now, phase=phase, **item.model_dump())
|
||||
for offset, item in enumerate(inputs)
|
||||
]
|
||||
connection.execute(
|
||||
|
||||
Reference in New Issue
Block a user