Return specific codes when results are unavailable (not started vs in progress vs ended empty), block duplicate starts with SURGERY_ALREADY_RECORDING, and show text/video/total durations in the demo client. Co-authored-by: Cursor <cursoragent@cursor.com>
73 lines
2.0 KiB
Python
73 lines
2.0 KiB
Python
"""离线 batch 各阶段耗时(进程内缓存,供 demo 客户端轮询)。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from threading import Lock
|
|
from typing import Literal
|
|
|
|
VideoStatus = Literal["skipped", "pending", "ready", "failed"]
|
|
|
|
|
|
@dataclass
|
|
class OfflineBatchTimingRecord:
|
|
surgery_id: str
|
|
text_duration_sec: float
|
|
video_status: VideoStatus = "skipped"
|
|
video_duration_sec: float | None = None
|
|
|
|
@property
|
|
def total_duration_sec(self) -> float:
|
|
total = self.text_duration_sec
|
|
if self.video_duration_sec is not None:
|
|
total += self.video_duration_sec
|
|
return total
|
|
|
|
|
|
_lock = Lock()
|
|
_records: dict[str, OfflineBatchTimingRecord] = {}
|
|
|
|
|
|
def set_text_timing(*, surgery_id: str, text_duration_sec: float, include_video: bool) -> None:
|
|
with _lock:
|
|
_records[surgery_id] = OfflineBatchTimingRecord(
|
|
surgery_id=surgery_id,
|
|
text_duration_sec=text_duration_sec,
|
|
video_status="pending" if include_video else "skipped",
|
|
)
|
|
|
|
|
|
def mark_video_ready(*, surgery_id: str, video_duration_sec: float) -> None:
|
|
with _lock:
|
|
rec = _records.get(surgery_id)
|
|
if rec is None:
|
|
return
|
|
rec.video_status = "ready"
|
|
rec.video_duration_sec = video_duration_sec
|
|
|
|
|
|
def mark_video_failed(*, surgery_id: str) -> None:
|
|
with _lock:
|
|
rec = _records.get(surgery_id)
|
|
if rec is None:
|
|
return
|
|
rec.video_status = "failed"
|
|
|
|
|
|
def get_timing(surgery_id: str) -> OfflineBatchTimingRecord | None:
|
|
with _lock:
|
|
rec = _records.get(surgery_id)
|
|
if rec is None:
|
|
return None
|
|
return OfflineBatchTimingRecord(
|
|
surgery_id=rec.surgery_id,
|
|
text_duration_sec=rec.text_duration_sec,
|
|
video_status=rec.video_status,
|
|
video_duration_sec=rec.video_duration_sec,
|
|
)
|
|
|
|
|
|
def clear_timing(surgery_id: str) -> None:
|
|
with _lock:
|
|
_records.pop(surgery_id, None)
|