Repository navigation
Harden long-running servers and roll back secrets on failed saves - #763
Merged
Merged
Conversation
The Node SQLite client caches prepared statements for 10 minutes, but the cache kept a failed prepare for the same 10 minutes. A prepare that failed for a passing reason (a schema lock, or "no such table" while the separate CLI process is still migrating the shared database) then failed every later call of that statement until the entry expired. The cache's time to live now depends on the lookup result: a prepared statement keeps the configured TTL, a failure is not cached, so the next call prepares the statement again. GitManager's status cache already uses the same pattern. Port of pingdotgg/t3code#10584 (d06f0ff104). Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
The source control status poll fetches each repository's upstream remote in the background, and every fetch ends with `git maintenance run --auto`. When that gc fails, for example on a repository with missing objects, git retries it on the next fetch and leaves a full-size tmp_pack_* behind each time, so a node that polls for weeks can fill the disk. The status fetch now passes --no-auto-gc (git 2.23+, a synonym of --no-auto-maintenance) and -c maintenance.auto=false. The flag covers the fetch itself; the config reaches the submodule fetches it starts, which do not inherit the flag. User-initiated fetches and pulls keep git's normal maintenance. Port of pingdotgg/t3code#13812 (95030dc674), plus the submodule case. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Sensitive provider-instance environment variables live in the secret store, and an update set and removed their keys before settings.json was written. Only CLIProxyAPI hub keys were put back when that write (or a later step of the update) failed, so a failed save could lose a removed API key for good, keep a replaced one that settings.json no longer matched, or leave a new key behind. A hub refused later in the same update left the provider keys changed as well. The hub's staging is now shared by both: one set of secret changes per update stores keys at once and remembers what each replaced, `restore` puts those values back (or removes new keys) if any step before the completed write fails, and keys the written file no longer refers to are only removed after the write, where a failure is logged and leaves a harmless unused key. A key is recorded before it is written, since the store can fail after replacing it (chmod after rename). Port of pingdotgg/t3code#12487 (6d68677ff9). Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
sak0a
force-pushed
the
fix/long-running-server-hygiene
branch
from
October 23, 2026 15:24
27d825c to
16a380b
Compare
10 tasks done
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 Changed
-c maintenance.auto=falseand--no-auto-gc, so it never startsgit maintenance run --auto. The config setting also covers the submodule fetches it starts, which do not get the flag. Fetches and pulls the user starts are unchanged.Why
A server that runs for weeks hit three problems:
gc --auto. When that gc fails, for example on a repository with missing objects, git retries it on the next poll and leaves a full-sizetmp_pack_*behind each time. Port of fix(server): background git status fetches no longer fill the disk with failed repacks pingdotgg/t3code#13812 (95030dc674), plus the submodule case.The WAL size cap and bounded event log records already match the reference. Replay-marker pruning does not apply, because Ryco's server stores no DPoP replay markers on disk.
Testing
bun run check: formatting ok, 0 lint errors,typecheck:fast12/12 okRYCO_TEST_MAX_WORKERS=4 bun run --cwd apps/server test -- src/persistence/NodeSqliteClient.test.ts src/vcs/GitVcsDriverCore.test.ts src/serverSettings.test.ts: 3 files, 117 passedRYCO_TEST_MAX_WORKERS=4 bun run check:changed: typecheck ok, related ryco-cli tests ok, read-from-disk ryco-cli tests ok.valuespath.gc --autois due keeps its pack count afterrefreshStatusUpstream.Follow-ups
gc --autoon purpose. They run when the user acts, not on a timer.@effect/sql-sqlite-bun) is upstream code. It does not cache failed statements, so it was not changed.🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.