тест 9

This commit is contained in:
2026-08-24 18:38:12 +03:00
parent aac9e5b8bc
commit 10a65e4d47
6 changed files with 233 additions and 22 deletions

View File

@@ -2001,6 +2001,7 @@ class VmixAgentHub:
return None
now = _utcnow()
with self.database.session() as session:
device = None
if requested_device_id:
requested_device_id = self.normalise_device_id(requested_device_id)
device = session.scalar(
@@ -2012,9 +2013,12 @@ class VmixAgentHub:
)
)
)
else:
# Legacy/single-Agent fallback only. If several devices are enabled,
# routing must be explicit so a browser cannot control the wrong vMix.
if device is None:
# BUILD111: a browser may keep a stale localStorage device id after
# reconnect/update. Do not silently leave the new match unassigned.
# Automatic fallback is allowed only when routing is unambiguous:
# exactly one live active Agent, or exactly one active Agent total.
candidates = list(session.scalars(
select(VmixDevice)
.where(
@@ -2025,7 +2029,12 @@ class VmixAgentHub:
)
.order_by(desc(VmixDevice.last_seen_at))
))
device = candidates[0] if len(candidates) == 1 else None
live_candidates = [item for item in candidates if item.device_uuid in self._live]
if len(live_candidates) == 1:
device = live_candidates[0]
elif len(candidates) == 1:
device = candidates[0]
if device is None:
return None
@@ -2114,6 +2123,7 @@ class VmixAgentHub:
user: HockeyUser,
*,
session_token: str = "",
wait_for_mapping: bool = True,
) -> dict[str, Any]:
"""Bind this browser/operator session to one enabled Agent."""
device_id = self.normalise_device_id(device_id)
@@ -2152,6 +2162,7 @@ class VmixAgentHub:
tournament_external_id=tournament_id,
device_id=device_id,
operator_session_token=session_token,
wait_for_mapping=bool(wait_for_mapping),
)
return {
"ok": True,
@@ -3978,6 +3989,9 @@ class RuntimeVmixSequencePayload(BaseModel):
class SelectSessionDevicePayload(BaseModel):
session_token: str = Field(default="", max_length=128)
# Runtime match switching can assign immediately and apply Mapping only
# after the new roster has been loaded. Existing Agent UI keeps True.
apply_mapping: bool = True
class MappingTestValuePayload(BaseModel):
@@ -4243,7 +4257,12 @@ def create_hockey_agent_router(
payload: SelectSessionDevicePayload,
user: HockeyUser = Depends(auth_dependency),
) -> dict[str, Any]:
return await hub.select_device_for_session(device_id, user, session_token=payload.session_token)
return await hub.select_device_for_session(
device_id,
user,
session_token=payload.session_token,
wait_for_mapping=bool(payload.apply_mapping),
)
@router.delete("/api/hockey/agents/devices/{device_id}/pair")
async def unpair_device(