Repository navigation
fix(agenda): stop dropping 15 s+ odroid renders and stop blaming the date range (HYP-1671) - #798
Merged
Merged
Conversation
…enders On the ODROID-N2+ every production render takes 6-15 s (most of the bot's memory sits in swap between renders). On 2026-10-12 18:00 UTC a daily agenda finished in 15 183 ms, two seconds after renderDirect stopped waiting at 15 000 ms, so the finished image was discarded. 45 s is 3x the slowest measured render and stays inside the 90 s AI turn in the common case. Refs HYP-1671 (task:HYP-1671)
/today, /tomorrow, /week and /month answered every render failure that was not an image-size error with 'Choose a shorter date range.', so the 2026-10-12 render timeout on a single day told the owner to shorten a one-day range. They now send the localized 'Image generation failed. Use text version above.' notice the callbacks already use (the text agenda is always sent first); size errors keep their own message. Refs HYP-1671 (task:HYP-1671)
The regression test now asserts the exact wait, so a lowered or raised budget fails. The comment states plainly that a render, like every tool, is not cut by the AI turn's between-rounds 90 s deadline. Refs HYP-1671 (task:HYP-1671)
…ies, not as-never type-bans blocks added 'as never' everywhere; the new /today and /month cases now go through one factory per file that keeps the test-only cast in one place (CLAUDE.md) and takes a real ImageRenderer. Refs HYP-1671 (task:HYP-1671)
Refs HYP-1671 (task:HYP-1671)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this fixes
On 2026-10-12 at 18:00:31 UTC the owner ran
/todayor/tomorrow(both log theevents_createfeature, at 18:00:29) and got «Agenda image could not be generated. Choose a shorter date range.» for a single day.Production log (odroidn2, image
c7f2ec0c):The worker finished the image 2 s after
RenderService.renderDirectstopped waiting (src/services/image/render-service.ts:5,23, fixed 15 swaitUntilFinished). The image was thrown away, and the command blamed the date range because every error it did not recognise got the «shorter date range» text (src/bot/commands/today.ts:126and the same line in tomorrow/week/month).Why renders are this slow now: every render in the current container's log takes 5.9–15.2 s (9924, 8155, 8113, 5944, 12403, 15183 ms). The same daily template renders in 0.8–1.8 s on a warm page inside the same container (one-off probe, 2026-10-12). The difference comes from the host: the bot's cgroup had 501 MB in swap (
memory.swap.current, zram plus a microSD swapfile; the bot's Bun process alone had 444 MB swapped out, with 985k major faults), so an idle Chromium and Bun heap have to be paged back in on every render. The 15 s budget was set on the DigitalOcean droplet.Changes
fix(image): wait 45 s for a render, about 3× the slowest measured production render. The wait is still bounded.fix(agenda): when a render fails for any reason other than image size,/today,/tomorrow,/weekand/monthsend the localized notice the callbacks already use, «test(image): the regression test asserts the exact 45 s wait.Tests (red → green)
test/services/image/render-service.test.ts: a worker that finishes at 15 183 ms must still be delivered. Red on main with the exact production errorJob wait render timed out … after 15000ms (id=539); green after change 1.test/bot/commands/{today,tomorrow,week,month}.test.ts: a non-size render failure (including the exact production timeout error) gets the honest localized notice, never the range advice. Red on main (received «…Choose a shorter date range.»); green after change 2.tsc --noEmitexit 0.bun run lintexit 0. At the final head: the 5 touched files gave 48 pass, tsc 0, lint 0.Review
AI review ran on every commit. One recurring finding was not acted on, for this reason: the AI agent checks its 90 s turn deadline only between rounds, and no tool is cut by it, so a render that starts late can end a turn past 90 s. The 15 s wait already allowed this; with 45 s the overrun can be longer. The turn's failure notice is only produced after the tool returns, so a photo can never arrive after a timeout notice. Discarding an image the worker already finished, which is what this incident was, is worse. The tradeoff is written down at the constant.
Refs HYP-1671