Sweep turn screenshots in every deployment, not only where a culler runs - #264
Open
zopeVaibhav wants to merge 1 commit into
Open
Sweep turn screenshots in every deployment, not only where a culler runs#264zopeVaibhav wants to merge 1 commit into
zopeVaibhav wants to merge 1 commit into
Conversation
zopeVaibhav
requested review from
MikeRyanDev,
davidmckayv,
guidovizoso and
tylerslaton
as code owners
August 26, 2026 16:28
zopeVaibhav
force-pushed
the
fix/page-frames-never-purged
branch
from
August 26, 2026 18:47
690c1e3 to
200c88e
Compare
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.
Closes #263.
What this changes
computer_page_frameis written on every navigation in every deployment, and its reaper had one caller:scripts/cull-idle-computers.ts, which refuses to run unless the provider issandboxand is scheduled only by the chart's culler CronJob, which renders only in that mode. So Compose, the all-in-one image and the chart's own default ofcomputers.mode: sharedwrote a row per navigation and removed none.The sweep moves to the server, onto the hourly timer that already removes old audit rows — one timer for both, which is the "second thing to get wrong" the cull script was right to avoid. It runs whether or not
AUDIT_RETENTION_DAYSis set, because the thirty-day window belongs to the store rather than to the audit policy, and gating it on that flag would leave most deployments exactly where they are.purgeis now batched. It was one statement withreturning, which is fine in a CronJob and not fine on an ordinary server.The culler no longer purges frames. The server does it there too, and one owner beats two.
The upgrade consequence, stated plainly because it is the one surprise here. Every deployment that is not
computers.mode: sandboxhas been keeping every screenshot since it was installed. The first sweep after this lands removes the ones older than thirty days, about a minute after the server starts. That is the window the store has always documented and the one sandbox deployments already enforce, but it has never been applied anywhere else. If it should be opt-in for existing installations rather than on, say so and I will put it behind a value — I have taken the view that a table nothing bounds is the worse default, and that reusingAUDIT_RETENTION_DAYSfor it would leave most deployments exactly where they are.Where it runs
delete ... where captured_at < now() - intervalrun twice removes the same rows once, which is the same reasoningcull-idle-computers.tsgives for why retention may run everywhere and suspension may not.Boundary and audit
page-frames-sweep-failedand leaves the rows, matching the audit sweep beside it.The append-only audit trigger is untouched — this table is not the audit trail and has no such trigger.
Changelog
CHANGELOG.mdunderUnreleased.Proof
Against a real database. One Bot, forty navigations a day for ninety days, 200 KB a frame — random bytes, because base64 of a real PNG is near-incompressible and a repeated string is not, which made a first attempt look twenty times smaller than the truth:
On
main, in a Compose-shaped deployment withAUDIT_RETENTION_DAYSunset:With this branch, same shape, same unset flag:
Batching, on the 734 MB table:
Repository checks:
bun run typecheckinserver/: clean.bunx biome checkon every touched file: clean.bun testover the retention, page-frame, audit and culler suites: 47 pass, 0 fail, run four times consecutively to be sure the polling test added here is not flaky.server/tests/page-frame-retention.integration.test.tsis new. Its first case passesundefinedfor the audit window, which is what a deployment that never configured retention has, and is the case that previously returned before starting a timer at all.