fix: add idle-timeout Instance disposal for serve mode memory#16616
fix: add idle-timeout Instance disposal for serve mode memory#16616sjawhar wants to merge 2 commits intoanomalyco:devfrom
Conversation
|
The following comment was made by an LLM, it may be inaccurate: Potential Duplicate/Related PRs Found:
These are related to memory/disposal management but have different scopes. #16616 (current PR) appears to be the most comprehensive solution targeting the specific serve mode instance caching issue with idle-timeout disposal. |
|
Why does yours have 58 files to fix this? Majority being MD? |
b2326b3 to
2b44b94
Compare
|
Good catch — those were internal tooling files (.sisyphus/) that shouldn't have been tracked. Cleaned up, the diff now only contains the 2 relevant source files (instance.ts + flag.ts) plus the test file. |
2b44b94 to
677af75
Compare
677af75 to
1f4520d
Compare
Addresses the remaining memory leaks identified in anomalyco#16697 by consolidating the best fixes from 23+ open community PRs into a single coherent changeset. Fixes consolidated from PRs: anomalyco#16695, anomalyco#16346, anomalyco#14650, anomalyco#15646, anomalyco#13186, anomalyco#10392, anomalyco#7914, anomalyco#9145, anomalyco#9146, anomalyco#7049, anomalyco#16616, anomalyco#16241 - Plugin subscriber stacking: unsub before re-subscribing in init() - Subagent deallocation: Session.remove() after task completion - SSE stream cleanup: centralized cleanup with done guard (3 endpoints) - Compaction data trimming: clear output/attachments on prune - Process exit cleanup: Instance.disposeAll() with 5s timeout - Serve cmd: graceful shutdown instead of blocking forever - Bash tool: ring buffer with 10MB cap instead of O(n²) concat - LSP index teardown: clear clients/broken/spawning on dispose - LSP open-files cap: evict oldest when >1000 tracked files - Format subscription: store and cleanup unsub handle - Permission/Question clearSession: reject pending on session delete - Session.remove() cleanup chain: FileTime, Permission, Question - ShareNext subscription cleanup: store unsub handles, cleanup on dispose - OAuth transport: close existing before replacing Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Issue for this PR
Fixes #13041
Type of change
What does this PR do?
In serve mode, each unique workspace directory creates an
Instancethat spawns LSP servers, MCP clients, file watchers, and ~26 state entries. These are cached forever and never cleaned up, even after all sessions disconnect — causing unbounded memory growth (2.9GB+ per session as reported in #13041).This PR adds automatic idle-timeout disposal:
Instance idle-timeout disposal (
instance.ts):acquire()/release()tracks activeprovide()calls per directoryOPENCODE_IDLE_TIMEOUTms (default 5 min)provide()calls cancel any pending idle timerInstance.list()returns cached instances with ref counts for observabilityInstance.disposeByDirectory(dir)for API-driven disposalRace condition fix (
state.ts):Configuration (
flag.ts):OPENCODE_IDLE_TIMEOUTenv var (ms, default 300000 = 5 min, set to 0 to disable)API endpoints (
routes/global.ts):GET /global/instances— list cached instances with ref countsPOST /global/instances/dispose— dispose a specific instance by directoryTests (
instance-idle.test.ts):How did you verify your code works?
bun run typecheckpassesChecklist