fix: make transcription cancellation slot-safe
This commit is contained in:
parent
3964690444
commit
87acd20811
@ -29,6 +29,8 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · versioned wi
|
||||
batch work is capped at two concurrent operations.
|
||||
- **Optional Background Transcription.** `/api/transcribe` now accepts `background: true` and exposes bounded job
|
||||
status/cancellation endpoints with timeout and failure states; existing synchronous callers remain compatible.
|
||||
- **STT Cancellation Safety.** Queued transcription cancels before consuming the single STT slot, and timed-out
|
||||
requests keep the device slot held until the underlying worker actually exits.
|
||||
- **API Boundary Hardening.** External API authentication is enabled by default, request and mutation limits are
|
||||
enforced, and settings responses redact provider credentials for non-browser callers.
|
||||
- **Server-side Provider Credentials.** Provider keys are now masked even for same-origin Settings responses, are
|
||||
|
||||
@ -50,12 +50,20 @@ def _stt_job_set(job_id: str, **fields) -> None:
|
||||
|
||||
|
||||
async def _run_stt_job(job_id: str, src: Path, settings: dict, backend: str) -> None:
|
||||
if _STT_JOBS.get(job_id, {}).get("cancel_requested"):
|
||||
_stt_job_set(job_id, stage="cancelled", detail="Cancelled", done=True, cancelled=True, error="Transcription cancelled")
|
||||
return
|
||||
_stt_job_set(job_id, stage="running", detail="Transcribing…")
|
||||
try:
|
||||
text, used_backend = await asyncio.wait_for(
|
||||
_bounded_stt_call(_transcribe_audio, src, settings, backend),
|
||||
timeout=_STT_JOB_TIMEOUT,
|
||||
)
|
||||
# Shield the worker task so wait_for timeout cannot cancel the
|
||||
# coroutine's finally block and release the semaphore while its
|
||||
# underlying to_thread operation is still using the device.
|
||||
call = asyncio.create_task(_bounded_stt_call(_transcribe_audio, src, settings, backend))
|
||||
try:
|
||||
text, used_backend = await asyncio.wait_for(asyncio.shield(call), timeout=_STT_JOB_TIMEOUT)
|
||||
except asyncio.TimeoutError:
|
||||
call.add_done_callback(lambda task: task.exception() if not task.cancelled() else None)
|
||||
raise
|
||||
if _STT_JOBS.get(job_id, {}).get("cancel_requested"):
|
||||
_stt_job_set(job_id, stage="cancelled", detail="Cancelled", done=True, cancelled=True, error="Transcription cancelled")
|
||||
else:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user