chore: правки пауз вне строк из main, чтобы ветку обновить слиянием

This commit is contained in:
GGlamer 2026-09-27 23:23:05 +03:00
commit 20acef6ad8
3 changed files with 12 additions and 13 deletions

View file

@ -111,10 +111,10 @@ class ActiveSessionOut(BaseModel):
dds_overdue_cards: int
dds_work_overdue_cards: int
dds_statuses: dict[str, str]
paused: bool = False
dds_snapshot: StationSnapshot | None = None
signals: list[Signal] = []
presence_known: bool = True
paused: bool = False
def _out(session) -> SessionOut:
@ -203,11 +203,10 @@ def _signals(
) -> list[Signal]:
"""Сигналы реестра: очередь, повторные отказы, курсант не на связи.
Пауза занятия (`session.pause`) их не трогает и ложных срабатываний не
даёт: очередь на паузе не выдаёт карточки, команды станции отклоняются,
поэтому счётчики стоят; присутствие сокета — факт и на паузе.
Присутствие — по наличию подписчика в хабе этого узла; окно нужно, чтобы
короткий разрыв соединения не сразу считался потерей связи курсанта.
Не завязаны на паузу занятия (`session.pause`, если появится) — очередь,
отказы и присутствие сокета не читают таймеры. Присутствие — по наличию
подписчика в хабе этого узла; окно нужно, чтобы короткий разрыв
соединения не сразу считался потерей связи курсанта.
`live=False` — снимок чужого узла: его сокеты здесь не видны, поэтому
присутствие неизвестно. Чтение реестра не меняет состояние занятия.
@ -331,10 +330,10 @@ async def active(
for card in state.desk.cards.values()
),
dds_statuses=latest_statuses,
paused=state.paused,
dds_snapshot=station,
signals=_signals(state, queue, now, live=state.session_id not in checkpoint_only),
presence_known=state.session_id not in checkpoint_only,
paused=state.paused,
))
return result

View file

@ -432,9 +432,6 @@ async def call(ws: WebSocket, session_id: UUID) -> None:
if hub.is_lease_fenced(session_id):
await close_fenced(ws)
return
# Каждый новый канал получает серверное состояние, включая снятую паузу:
# клиент мог потерять событие resume во время переподключения.
queue.put_nowait(SessionPaused(paused=state.paused))
if state.exercise is Exercise.CARD:
from app.api.ws.control import card_briefing
@ -468,6 +465,9 @@ async def call(ws: WebSocket, session_id: UUID) -> None:
if state.recorder is None:
state.recorder = start_recording(session_id)
_start_voice(session_id, state, initial_statement=False)
# Каждый новый канал получает серверное состояние, включая снятую паузу:
# клиент мог потерять событие resume во время переподключения.
queue.put_nowait(SessionPaused(paused=state.paused))
writer = asyncio.create_task(pump(ws, queue))
try:
while True:

View file

@ -160,14 +160,14 @@ def full_state() -> SessionState:
desk=desk,
resolved_outcome="справка",
resolve_comment="передано в другой регион",
paused=True,
paused_at=AT,
total_paused_ms=15_000,
processed_station_commands=[str(uuid4())],
text_revealed_facts={"f_address": "улица Ленина, 14"},
consecutive_refusals=2,
socket_last_seen_at=AT,
socket_connected_at_checkpoint=True,
paused=True,
paused_at=AT,
total_paused_ms=15_000,
)