[Hardening] Stop on_ready audio_temp cleanup from deleting recordings queued for processing #85
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
The bot wipes the shared
audio_tempvolume on startup to clear orphans from a crashed run:on_ready(bot/questboard_bot/main.py:61-63) calls_cleanup_audio_temp(defined atmain.py:229), whose loop atmain.py:257-260shutil.rmtrees every subdirectory ofaudio_temp.The problem:
on_readyfires on every gateway reconnect/resume, not just at process start. Discord reconnects are routine (network blips, Discord-side resumes).Current behavior
Two races, both destroying live data:
_process(bot/questboard_bot/cogs/recording.py:523) writes per-speaker WAV files andspeakers.jsoninto a per-session directory on the volume. A gateway reconnect during a recording/processing deletes another (or the same) session's directory mid-write.post_audio_tracks(recording.py:595), the backend endpoint (webapp/backend/app/routers/bot.py:698-705) only queues a Celeryprocess_audiotask that reads the directory later. A reconnect between upload-ack and the worker actually reading the files silently destroys the recording; the Celery task then fails on a missing directory. Hours of session audio are unrecoverable.Fix / Spec
_cleanup_audio_temp(...)call out ofon_ready(main.py:63) intosetup_hook(main.py:55), which runs exactly once per process — or guard it with a "ran once" flag. Reconnects must not trigger cleanup._cleanup_audio_temp: only remove subdirectories whose mtime is older than a threshold (e.g. 60 minutes). A dir younger than the threshold at process start could belong to an upload the backend hasn't consumed yet (worker backlog across a bot restart).process_audioalready deletes the dir on success; if it does, say so in the comment.)bot/tests/covering: a fresh dir survives cleanup, an old dir is removed.Acceptance criteria
on_ready(simulated reconnect) does not remove any session directory that is being written or was just uploaded.References
bot/questboard_bot/main.py:55(setup_hook),:61-63(on_ready→ cleanup call),:229(_cleanup_audio_temp),:257-260(unconditionalrmtreeloop)bot/questboard_bot/cogs/recording.py:523(_processwrites tracks),:595(post_audio_tracks)webapp/backend/app/routers/bot.py:698-705(upload endpoint queuesprocess_audio— deferred read)Filed from the July 2026 full-project review.
Picking this up as part of a v3.3.0 push. Landing on branch
hardening/bottogether with #83, #94, and #111 (grouped by component to keep the diffs reviewable).Fixed on
main(commitse62f5c8+f52ae01, merged viacd315d6).The cleanup call moved from
on_ready(fires on every gateway reconnect) tosetup_hook(once per process), and is now age-gated.Scope note — the issue's premise was incomplete, and this went further than the original spec. While implementing, we verified the backend
process_audiotask's own docstring: "The session directory is NEVER deleted here — it stays until a GM approves it." Deletion only happens later incleanup_trashed_audiofor GM-trashed sessions after a retention window (default 7 days). So session directories legitimately live on the volume for days, and an age gate alone would still let a real bot restart (deploy/crash/reboot) delete backend-owned audio. Fixed properly with a handoff marker: the bot writes.handed-offinto the session dir on a successful upload ack, and the startup sweep skips any marked dir regardless of age. Only unmarked dirs (a crashed recording that never reached the backend) are subject to the age gate. Tests cover marked-survives-when-old, unmarked-old-removed, unmarked-fresh-survives, marker-written-on-success/absent-on-failure. Bot suite green (158 passed).