mirror of
https://github.com/jamiepine/voicebox.git
synced 2026-09-17 05:40:42 -07:00
fix(captures): Play As autoplay + default voice + orphan recovery
- Hand /generate ids to the global SSE watcher so playback fires on completion. The mutation onSuccess was checking audio_path on a queued row, which is always empty — autoplay never ran. - Bind the Play As voice selection to capture_settings.default_playback_voice_id, kept in sync with the Settings → Captures and Settings → MCP pickers. Picking from the split-button dropdown writes back to settings. - Extract AudioBars from HistoryTable into a shared component; use it for the Play As generating state in place of Loader2. - Stop the active-state hover from flashing white text when the button is in its lighter accent/10 fill. - Drop the gradient avatar swatches from the Settings → Captures voice dropdown. - Backend: when the gen worker exits without writing a terminal status (e.g. SQLite lock racing the failed-status write inside its own exception handler), the cancel endpoint now flips the row to failed instead of 409-ing. Worker also force-fails on its way out as a belt-and-suspenders.
This commit is contained in:
@@ -56,12 +56,43 @@ async def _generation_worker():
|
||||
raise
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
await _force_fail_if_active(
|
||||
job.generation_id,
|
||||
"Worker exited without writing terminal status",
|
||||
)
|
||||
finally:
|
||||
_running_generation_tasks.pop(job.generation_id, None)
|
||||
_queued_generation_ids.discard(job.generation_id)
|
||||
_generation_queue.task_done()
|
||||
|
||||
|
||||
async def _force_fail_if_active(generation_id: str, error: str) -> None:
|
||||
"""Best-effort recovery — flip an active row to failed if the worker
|
||||
bailed before writing a terminal status. Catches the case where the gen
|
||||
coroutine's own status-write raised (e.g. SQLite lock contention)."""
|
||||
try:
|
||||
from ..database import Generation as DBGeneration, get_db
|
||||
from . import history
|
||||
|
||||
db = next(get_db())
|
||||
try:
|
||||
gen = db.query(DBGeneration).filter_by(id=generation_id).first()
|
||||
if gen is None:
|
||||
return
|
||||
if (gen.status or "completed") not in ("loading_model", "generating"):
|
||||
return
|
||||
await history.update_generation_status(
|
||||
generation_id=generation_id,
|
||||
status="failed",
|
||||
db=db,
|
||||
error=error,
|
||||
)
|
||||
finally:
|
||||
db.close()
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
|
||||
|
||||
def enqueue_generation(generation_id: str, coro):
|
||||
"""Add a generation coroutine to the serial queue."""
|
||||
if _generation_queue is None:
|
||||
|
||||
Reference in New Issue
Block a user