Skip to content

Conversation

@sauerdaniel
Copy link
Contributor

@sauerdaniel sauerdaniel commented Jan 17, 2026

Summary

Complete the Instance disposal chain to ensure plugins and cached resources are properly cleaned up when instances are disposed.

Fixes #9157
Depends on #9141 (LRU cache utility)

Note: This PR builds on the LRU cache utility from #9141. Please merge that PR first.

Problem

When Instance.dispose() is called:

  1. Plugins not disposed - Plugins may hold resources (connections, file handles) that need cleanup
  2. Cached instances not disposed - The instance cache doesn't call disposal hooks when evicting entries
  3. No disposal hook in Hooks interface - Plugins have no way to register cleanup logic

Solution

1. Plugin Dispose Hook

Add dispose() method to plugin Hooks interface.

2. LRU Cache onEvict Callback

Use the LRU cache's onEvict callback to dispose instances when evicted.

3. Bootstrap Cleanup

Add cleanup in bootstrap to dispose plugins before process exit.

Changes

  • packages/plugin/src/index.ts - Add dispose() to Hooks interface
  • packages/opencode/src/plugin/index.ts - Call plugin dispose() on instance disposal
  • packages/opencode/src/project/instance.ts - Add onEvict callback for cache eviction
  • packages/opencode/src/project/bootstrap.ts - Add cleanup for plugins on exit
  • packages/opencode/src/provider/provider.ts - Use LRU cache for SDK instances
  • packages/opencode/src/util/cache.ts - Add iterator support (from feat(util): Add bounded LRU cache utility #9141)

Testing

  • TypeScript compilation passes (bun turbo typecheck)
  • Unit tests pass (725 tests, 0 failures)
  • Instance/project tests pass

Note: Manual plugin disposal testing was not performed. This requires creating a test plugin with cleanup logic and verifying it's called.

Stacking

This PR includes commits from #9141 (LRU cache utility). After #9141 is merged, this PR can be rebased to only include the disposal-specific changes.

Add bounded LRU cache implementation to prevent unbounded memory growth
in long-running sessions.

Changes:
- Create new createLruCache utility in src/util/cache.ts with:
  - maxEntries limit for bounded cache size
  - LRU eviction policy when limit is reached
  - Optional onEvict callback for cleanup
- SDK cache: limited to 50 entries with LRU eviction
- Languages cache: limited to 100 entries with LRU eviction
- Instance cache: limited to 20 entries with LRU eviction

These caches previously grew unbounded, contributing to 70GB+ memory
usage in long-running sessions.
Add optional dispose callback to plugin Hooks interface to allow
plugins to clean up resources when the Instance is disposed.
When LRU cache evicts an Instance, call State.dispose() to clean up
associated resources. Prevents memory leaks from evicted instances.
…gins

Ensure proper cleanup when Instance is disposed:
- Call plugin dispose() hooks
- Clean up bootstrap subscriptions
- Properly chain disposal through all components

This completes the Instance lifecycle management, preventing memory
leaks from orphaned subscriptions and plugin resources.
@github-actions
Copy link
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@github-actions
Copy link
Contributor

The following comment was made by an LLM, it may be inaccurate:

Based on my search, I found the following related PRs:

Related/Dependent PRs:

  1. PR feat(util): Add bounded LRU cache utility #9141: feat(util): Add bounded LRU cache utility

Similar Previous Work:

  1. PR fix(core): add dispose functions to prevent subscription memory leaks #7032: fix(core): add dispose functions to prevent subscription memory leaks

  2. PR fix(core): add dispose functions to prevent subscription memory leaks #7914: fix(core): add dispose functions to prevent subscription memory leaks

Note: PR #9149 is the current PR being checked, so it's not a duplicate of itself. The main dependency to be aware of is #9141 (LRU cache utility), which the PR explicitly mentions must be merged first.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Memory leak: Instance disposal doesn't clean up plugins or cached resources

1 participant