test 7
This commit is contained in:
@@ -1991,6 +1991,7 @@ class VmixAgentHub:
|
||||
tournament_external_id: str = "",
|
||||
device_id: str = "",
|
||||
operator_session_token: str = "",
|
||||
wait_for_mapping: bool = True,
|
||||
) -> dict[str, Any] | None:
|
||||
"""Assign a match to exactly one Agent. Never broadcast to all active Agents."""
|
||||
game_external_id = str(game_external_id or "").strip()
|
||||
@@ -2094,7 +2095,17 @@ class VmixAgentHub:
|
||||
)
|
||||
payload["delivered"] = delivered
|
||||
if delivered:
|
||||
payload["mapping_apply"] = await self.apply_mapping_to_device(resolved_device_id, reason="match_assigned")
|
||||
if wait_for_mapping:
|
||||
payload["mapping_apply"] = await self.apply_mapping_to_device(
|
||||
resolved_device_id, reason="match_assigned"
|
||||
)
|
||||
else:
|
||||
payload["mapping_apply"] = {
|
||||
"ok": True,
|
||||
"deferred": True,
|
||||
"reason": "match_assigned",
|
||||
"device_id": resolved_device_id,
|
||||
}
|
||||
return payload
|
||||
|
||||
async def select_device_for_session(
|
||||
|
||||
@@ -5,7 +5,7 @@ from datetime import date
|
||||
from time import perf_counter
|
||||
from typing import Any, Callable
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, Request
|
||||
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Query, Request
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
from sqlalchemy import text
|
||||
|
||||
@@ -1149,6 +1149,7 @@ def create_hockey_router(
|
||||
@router.post("/sessions")
|
||||
async def open_session(
|
||||
payload: SessionPayload,
|
||||
background_tasks: BackgroundTasks,
|
||||
user: HockeyUser = Depends(auth_dependency),
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
@@ -1169,7 +1170,18 @@ def create_hockey_router(
|
||||
tournament_external_id=str(result.get("tournament_external_id") or ""),
|
||||
device_id=vmix_device_id,
|
||||
operator_session_token=str(result.get("token") or ""),
|
||||
# BUILD109: selecting a match must not wait for a full
|
||||
# Mapping push to vMix. The Agent receives match.assign
|
||||
# immediately; Mapping starts only after the HTTP response.
|
||||
wait_for_mapping=False,
|
||||
)
|
||||
assignment = result.get("agent_assignment") or {}
|
||||
if assignment.get("delivered") and assignment.get("device_id"):
|
||||
background_tasks.add_task(
|
||||
agent_hub.apply_mapping_to_device,
|
||||
str(assignment.get("device_id")),
|
||||
reason="match_assigned",
|
||||
)
|
||||
except Exception as agent_error:
|
||||
# The match/session must remain usable even when a browser
|
||||
# carries a stale Agent id from another WFL account.
|
||||
|
||||
@@ -368,7 +368,9 @@
|
||||
return payload;
|
||||
} catch (error) {
|
||||
if (error?.name === "AbortError") {
|
||||
throw new Error("Превышено время ожидания ответа Stat2TV");
|
||||
// BUILD109: this helper is used for local DB/session/Agent endpoints too.
|
||||
// Calling every HTTP timeout a Stat2TV timeout hides the real subsystem.
|
||||
throw new Error("Превышено время ожидания ответа сервера");
|
||||
}
|
||||
throw error;
|
||||
} finally {
|
||||
@@ -1529,27 +1531,20 @@ function gameCard(game) {
|
||||
);
|
||||
state.selectedGame = discovered.game;
|
||||
state.selectedMatchDetails = discovered.details || null;
|
||||
} else if (scheduleGame) {
|
||||
// BUILD109: the card the operator clicked is already a complete local
|
||||
// schedule snapshot. Opening the workspace must be immediate; cached
|
||||
// details/full match data are optional enrichment and are loaded below.
|
||||
state.selectedGame = scheduleGame;
|
||||
state.selectedMatchDetails = null;
|
||||
} else {
|
||||
try {
|
||||
const cached = await request(
|
||||
`/api/hockey/games/${encodeURIComponent(id)}/details?language=${encodeURIComponent(state.language)}`,
|
||||
{ timeoutMs: 5000 }
|
||||
);
|
||||
state.selectedGame = cached.game;
|
||||
state.selectedMatchDetails = cached.details || null;
|
||||
} catch (_) {
|
||||
try {
|
||||
state.selectedGame = await request(
|
||||
`/api/hockey/games/${encodeURIComponent(id)}?language=${encodeURIComponent(state.language)}`,
|
||||
{ timeoutMs: 5000 }
|
||||
);
|
||||
state.selectedMatchDetails = null;
|
||||
} catch (baseError) {
|
||||
if (!scheduleGame) throw baseError;
|
||||
state.selectedGame = scheduleGame;
|
||||
state.selectedMatchDetails = null;
|
||||
}
|
||||
}
|
||||
// Defensive fallback for a stale DOM/list state. This path is local DB
|
||||
// only and is not used for the normal visible match-card click.
|
||||
state.selectedGame = await request(
|
||||
`/api/hockey/games/${encodeURIComponent(id)}?language=${encodeURIComponent(state.language)}`,
|
||||
{ timeoutMs: 5000 }
|
||||
);
|
||||
state.selectedMatchDetails = null;
|
||||
}
|
||||
|
||||
const actualTournamentId = String(
|
||||
|
||||
Reference in New Issue
Block a user