chore: bound the caches and maps that never evict #445
Labels
No labels
backend
bug
chore
duplication
effort:complex
effort:medium
effort:trivial
enhancement
frontend
fullstack
priority:high
ready-for-agent
refactor
security
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
dries/ocman#445
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Code-quality audit (P2). Seven in-memory caches/maps grow for the process lifetime with no eviction path. Individually small, collectively a slow leak in a long-running daemon; the git diff cache is the largest single offender.
Sites
internal/git/diff.go:124— package-leveldiffCacheStorage map[string]diffEntry.lookupCachedreturnsnilfor a stale entry but leaves the row in place. Each value is a*Diffcapped attotalDiffCap(2 MB), retained forever. Every worktree is a distinct key, so/wtusage multiplies the key count. Same shape (smaller values) atinternal/git/info.go:68-119—cache.entriesis only pruned by the explicitinvalidate(dir)after a checkout.internal/platforms/opencode/portdiscovery.go:42—sessionPortAffinity sync.Map. Written byrememberSessionPorton every port resolution (portdiscovery.go:542,operations.go:61), removed only by an explicitforgetSessionPort. Retains every session ID ever touched, including deleted ones.internal/platforms/opencode/live_prompts.go:113-127—ObservePromptResolveddeletes theentriesrow and then writes a newchanged[key].changedis only pruned inClearPromptsForPort(:209-212), and only for keys still present inentries— which this path just removed. Net effect: every permission/question the user answers adds a permanent entry.internal/platforms/opencode/httpcache.go:123-137—invalidatePorthas zero production callers (onlyhttpcache_test.go:150), yet its doc comment asserts the mechanism is wired to port disappearance. Nothing prunes by port andgetnever deletes expired entries.ocruntime.AllocateLoopbackPorthands each managed relaunch a fresh random port, so every project restart adds a key set that is never reclaimed.internal/workflows/service.go:1866,1878—ownedRuns/reconciledRuns. Repo-wide grep finds nodelete(for either. One entry per workflow run, forever.internal/autoapprove/statemachine.go:147—autoApprovedeliberately retains recorded verdicts (if st.verdict == "" { delete(...) }) so REST resurrection can replay them: one entry per (session, permission) forever.:366—safeCommandCachekeeps a per-session map of every safe command hash, no eviction.internal/queuesvc/service.go:120—lockForstores a*sync.Mutexper session ID that ever enqueues/flushes/sweeps; nothing removes them.Suggested fix
Per site, whichever is smallest:
git/diff.go,git/info.go,httpcache.get).sessionPortAffinity), run terminal state (ownedRuns/reconciledRuns), session idle+empty (queuesvc.locks).live_prompts: also deletechanged[key]inClearPromptsForPortfor keys whose entry is already gone, or age outchangedby version.httpcache: either wireinvalidatePortinto port-disappearance detection or delete it and fix the doc comment. Add a size cap.Acceptance criteria
invalidatePort's doc comment matches reality (wired or removed).Effort: S each.