diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-09-19 13:24:53 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-09-19 13:24:53 +0200 |
| commit | eca01c7f970d2d3ab2298f934da9776fe01179c6 (patch) | |
| tree | 4a106ec9fd13bb91eed236c07d821ab50747d5cc /packages/meshbay-node/tests/test_tmdb_show_director.py | |
| parent | 5d5d55b588401cdd304922b58e2af2fb18c63648 (diff) | |
| download | meshbay-eca01c7f970d2d3ab2298f934da9776fe01179c6.tar.gz | |
fix(node): bound what a transcode may produce, and read ffmpeg's output off the loop
Two things about the same three functions, which write to a temp file with ffmpeg
and then read it back.
**The read was on the event loop.** These files are ffmpeg's own, under
`tempfile.mkstemp` on the system disk, so they are not a group root and there is
no spun-down platter to serialise against — which is why they go through
`asyncio.to_thread` and not `roots.off_disk`. But a whole transcode read inline is
still tens of megabytes of blocking read while nothing else in the node is served.
The AST guard now covers the module with no exemption at all, and a second check
refuses a direct call to the reading helper: passed to `to_thread` it appears in
the syntax tree as a name, called inline it appears as a call.
**The audio transcode had no size ceiling**, where the subtitle path beside it
has had one all along. The bound is the media cache's rather than memory's:
`put_thumb` writes one SQLite row, and the store is 512 MB with least-recently-used
eviction, sized for thumbnails, posters and short transcodes. At 192 kbit/s a
three-hour source is ~260 MB — one row that evicts most of the cache to fit and is
evicted again by the next few thumbnails. Not a size this store can hold usefully.
64 MiB, about forty-five minutes: past any track, any single piece, most sets.
It takes away nothing that worked. `AUDIO_TRANSCODE_TIMEOUT_SECS` is 120, so a
source long enough to reach this was already liable to be killed mid-transcode;
what changes is that the refusal now names the limit it met and the size that met
it. Serving audio of that length properly means streaming the conversion instead
of buffering it, which is a different feature — recorded in §9.8 rather than left
as an implied promise.
The stat comes before the read, so an oversized result costs a stat rather than
the read and the memory behind it.
Twelve `test_sticky_header.py[firefox]` setup errors again: Firefox is still open
on this machine, and its `[chrome]` half passes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-node/tests/test_tmdb_show_director.py')
0 files changed, 0 insertions, 0 deletions