refactor: запись хода занятия — один commit SessionStore на операцию вместо журнала и checkpoint

Правка балла с пульта и из отчёта идёт одной доменной операцией: раньше WS-путь не обновлял full_report живой сессии.
This commit is contained in:
gglamer 2026-09-26 22:48:24 +00:00
commit 47cb85ee02
30 changed files with 1406 additions and 1161 deletions

View file

@ -23,6 +23,7 @@ from app.session import timers as timers_module
from app.session.checkpoint import dump_state, load_state
from app.session.dds import prepare_handoff_queue, prepare_queue
from app.session.hub import hub
from app.session.store import MemorySessionStore
from app.session.state import SessionState
from app.session.timers import now_utc
@ -30,6 +31,12 @@ LIBRARY = Path(__file__).resolve().parents[2] / "scenarios"
_events = TypeAdapter(StationToServer)
async def finish_in_operation(state):
"""finish() пишет оценку в commit операции, завершившей занятие."""
async with hub.operation(state.session_id):
await finish_module.finish(state.session_id, state)
@pytest.fixture(autouse=True)
def offline_finish(monkeypatch):
class NoCoaching:
@ -40,7 +47,7 @@ def offline_finish(monkeypatch):
return NoCoaching()
monkeypatch.setattr(finish_module, "coach", no_coach)
monkeypatch.setattr(hub, "journal", None)
monkeypatch.setattr(hub, "store", MemorySessionStore())
def fire():
@ -150,7 +157,7 @@ def test_call_checkpoint_keeps_dispatcher_work_on_shared_timers():
assert snapshot.queue_cards == []
state.ended_at = now_utc()
asyncio.run(finish_module.finish(state.session_id, state))
asyncio.run(finish_in_operation(state))
crew = next(item for item in state.score["metrics"] if item["key"] == "dds_crew")
assert crew["passed"] and crew["fact"] == card.crew_selected
@ -189,7 +196,7 @@ def test_finish_scores_every_card_without_switching_active(name):
unscored = {card.card_id for card in state.desk.cards.values()}
state.ended_at = now_utc()
asyncio.run(finish_module.finish(state.session_id, state))
asyncio.run(finish_in_operation(state))
assert state.desk.active is active
assert {record.card_id for record in state.desk.completed} == unscored