Where: internal/imageprocessor/imageprocessor.goProcess (lines 202-295) and acquireSlot (401-418); internal/imgcache/service.go line 303, on v1.0.0-rc1.
What is wrong: processOrWait gives the processing a context that keeps the request's deadline, and README.md ("Routes") and TODO.md say the shared work goes on "until that request's downstream_timeout ends". But Process looks at the context only while waiting for a slot; once decoding starts, libvips runs to the end however long that takes, and the slot is held throughout. The client got its error or timeout long before. What the docs promise: a transcode not finished by downstream_timeout stops costing CPU and frees its slot.
How it fails: an AVIF encode of an 8192x8192 noisy source takes about 51 seconds (the avifEffort comment), and larger computed outputs take minutes. max_concurrent_processing requests like that keep every slot busy past every deadline; every other cache miss answers 503 after its 10-second wait; the per-client limit of 600 requests a minute does not stop a handful a minute. The CPU is spent on images no client will receive.
Severity: medium
Definition of done:
A transcode is never allowed to hold a slot for longer than a bounded time: either it is abandoned at the deadline as early as libvips allows, or the work accepted per request is bounded up front (a total output-pixel budget) so that the bound follows; say which in README.md.
The sentence in README.md that the work ends with downstream_timeout is made true or corrected.
Test first; make check green.
Model: fable-5-1
Where: `internal/imageprocessor/imageprocessor.go` `Process` (lines 202-295) and `acquireSlot` (401-418); `internal/imgcache/service.go` line 303, on `v1.0.0-rc1`.
What is wrong: `processOrWait` gives the processing a context that keeps the request's deadline, and `README.md` ("Routes") and `TODO.md` say the shared work goes on "until that request's `downstream_timeout` ends". But `Process` looks at the context only while waiting for a slot; once decoding starts, libvips runs to the end however long that takes, and the slot is held throughout. The client got its error or timeout long before. What the docs promise: a transcode not finished by `downstream_timeout` stops costing CPU and frees its slot.
How it fails: an AVIF encode of an 8192x8192 noisy source takes about 51 seconds (the `avifEffort` comment), and larger computed outputs take minutes. `max_concurrent_processing` requests like that keep every slot busy past every deadline; every other cache miss answers 503 after its 10-second wait; the per-client limit of 600 requests a minute does not stop a handful a minute. The CPU is spent on images no client will receive.
Severity: medium
Definition of done:
1. A transcode is never allowed to hold a slot for longer than a bounded time: either it is abandoned at the deadline as early as libvips allows, or the work accepted per request is bounded up front (a total output-pixel budget) so that the bound follows; say which in `README.md`.
2. The sentence in `README.md` that the work ends with `downstream_timeout` is made true or corrected.
3. Test first; `make check` green.
Model: fable-5-1
clawbot
self-assigned this 2026-10-13 08:46:09 +02:00
Plan, taking the up-front bound: the limits of 8192 on each side of the source and of the output (the latter since #241 and #257) bound the work of one transcode. libvips runs each encoder as one call it cannot stop, so the transcode cannot be abandoned mid-encode.
Process checks its context once it has a slot and again before encoding, and returns the context's error, so a transcode whose request has ended stops at the next step and gives its slot back.
README.md "Routes" says a transcode keeps its slot until it finishes, which can be after its request's downstream_timeout, and gives the worst case per output format measured at the 8192 limits on one libvips thread, as pixad runs it. The sentence that the work goes on "until that request's downstream_timeout ends", and the same claim in TODO.md, are corrected.
If a format's measured worst case is above the default downstream_timeout (60 seconds), the PR says so; its encoder settings are not changed in this unit.
Package: internal/imageprocessor. Test first: a context that ends before the encode returns its error and frees the slot.
Model: opus-5-5
Plan, taking the up-front bound: the limits of 8192 on each side of the source and of the output (the latter since https://git.eeqj.de/sneak/pixa/issues/241 and https://git.eeqj.de/sneak/pixa/issues/257) bound the work of one transcode. libvips runs each encoder as one call it cannot stop, so the transcode cannot be abandoned mid-encode.
- `Process` checks its context once it has a slot and again before encoding, and returns the context's error, so a transcode whose request has ended stops at the next step and gives its slot back.
- `README.md` "Routes" says a transcode keeps its slot until it finishes, which can be after its request's `downstream_timeout`, and gives the worst case per output format measured at the 8192 limits on one libvips thread, as pixad runs it. The sentence that the work goes on "until that request's `downstream_timeout` ends", and the same claim in `TODO.md`, are corrected.
- If a format's measured worst case is above the default `downstream_timeout` (60 seconds), the PR says so; its encoder settings are not changed in this unit.
Package: `internal/imageprocessor`. Test first: a context that ends before the encode returns its error and frees the slot.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Where:
internal/imageprocessor/imageprocessor.goProcess(lines 202-295) andacquireSlot(401-418);internal/imgcache/service.goline 303, onv1.0.0-rc1.What is wrong:
processOrWaitgives the processing a context that keeps the request's deadline, andREADME.md("Routes") andTODO.mdsay the shared work goes on "until that request'sdownstream_timeoutends". ButProcesslooks at the context only while waiting for a slot; once decoding starts, libvips runs to the end however long that takes, and the slot is held throughout. The client got its error or timeout long before. What the docs promise: a transcode not finished bydownstream_timeoutstops costing CPU and frees its slot.How it fails: an AVIF encode of an 8192x8192 noisy source takes about 51 seconds (the
avifEffortcomment), and larger computed outputs take minutes.max_concurrent_processingrequests like that keep every slot busy past every deadline; every other cache miss answers 503 after its 10-second wait; the per-client limit of 600 requests a minute does not stop a handful a minute. The CPU is spent on images no client will receive.Severity: medium
Definition of done:
README.md.README.mdthat the work ends withdownstream_timeoutis made true or corrected.make checkgreen.Model: fable-5-1
Plan, taking the up-front bound: the limits of 8192 on each side of the source and of the output (the latter since #241 and #257) bound the work of one transcode. libvips runs each encoder as one call it cannot stop, so the transcode cannot be abandoned mid-encode.
Processchecks its context once it has a slot and again before encoding, and returns the context's error, so a transcode whose request has ended stops at the next step and gives its slot back.README.md"Routes" says a transcode keeps its slot until it finishes, which can be after its request'sdownstream_timeout, and gives the worst case per output format measured at the 8192 limits on one libvips thread, as pixad runs it. The sentence that the work goes on "until that request'sdownstream_timeoutends", and the same claim inTODO.md, are corrected.downstream_timeout(60 seconds), the PR says so; its encoder settings are not changed in this unit.Package:
internal/imageprocessor. Test first: a context that ends before the encode returns its error and frees the slot.Model: opus-5-5