Files
picpeak/backend/__tests__/utils
Paul Nothaft a5e797e5db fix(gallery): bound and reclaim storage reads in the guest download routes (stable) (#1416)
Backport of the main-branch fix. Both guest-facing download routes append one
storage read per photo and hand them to archiver, which drains them one at a
time — so every read past the one being written parks an S3 socket holding
unread bytes, and nothing reclaims them. archiver's abort() does not touch its
source streams, and the SDK arms its socket timeout on a 3s delay then clears
it as soon as response headers land, so a fast response never gets one.

This is the mechanism behind the incident reported against the cached-zip
builder: pooled sockets held with unread bytes, uploads and gallery reads
starved behind them, a process restart the only way out. These two routes need
no admin credentials to reach — any gallery guest can trigger them, and closing
the tab mid-download was enough to strand every appended-but-undrained read.

utils/archiveStreamGuard caps reads in flight at 2 and destroys whatever is
still open on every exit, including the client disconnect. A cancelled download
returns without reaching finalize(), which would otherwise reject with ABORTED
and make the catch send JSON over a response whose ZIP headers had already
gone out. A read that dies while still queued is reported so the archive is
aborted rather than hanging when it reaches a dead stream.

downloadZipService still has the same pattern on this branch and is deliberately
untouched here — that is the cached-zip builder, whose fix is a separate PR on
main and not yet backported.

Local-filesystem installs are unaffected: they take archiver's file-path branch
and open no sockets.

Relates to issue 1399

Co-authored-by: Paul Nothaft <paul@MacStudio-von-Paul.local>
2026-09-11 12:06:48 +02:00
..