Skip to content

Give each workspace its own gem CacheDir - #272

Draft
apiology wants to merge 3 commits into
load-plugins-when-caching-gemsfrom
workspace-owned-gem-cache-dir
Draft

apiology wants to merge 3 commits into
load-plugins-when-caching-gemsfrom
workspace-owned-gem-cache-dir

Conversation

@apiology

Copy link
Copy Markdown
Owner

Claude: This PR was written by Claude Code on behalf of @apiology.

Alternative to #260; same behavior, different design.

Problem

A workspace with plugins moves every other workspace to its gem cache:

Solargraph::Workspace.new('/work/rails_app')    # .solargraph.yml: plugins: [solargraph-rails]
plain = Solargraph::Workspace.new('/work/gem')  # no plugins
api_map = Solargraph::ApiMap.new
api_map.catalog Solargraph::Bench.new(workspace: plain)
# expected .../gems, got .../gems-solargraph-rails-1.2.0
Solargraph::CacheDir.gem_dir

In one language server, the plain workspace finds none of its cached gems and rebuilds them into the plugin directory, which castwide/solargraph#1407 introduced.

Solution

CacheDir becomes a class, and each Workspace owns an instance (Workspace#cache_dir) that Config#require_plugins fills with the plugin gems it loads, so the key lives in that object and Collection::Gem, External, ApiMap, the cache/uncache commands and the cache subprocess's --plugins= take it from the workspace they serve.

Convention.register no longer touches the key, because it runs once per process; Convention.add_plugin_conventions(cache_dir, plugin_gems) instead adds the registered conventions defined by that workspace's plugin gems.

A plugin loaded by plain require into a workspace without config is no longer part of any key; it reads and writes the plain gems directory.

apiology and others added 3 commits October 22, 2026 16:01
The gem cache directory was process-global, keyed on every plugin gem
loaded so far, so loading one workspace with plugin gems switched the
directory for every other workspace in the process.

CacheDir is now a class. Each Workspace owns an instance, created at
init and filled by Config#require_plugins, which adds each plugin gem
it loads; Convention.add_plugin_conventions then adds the registered
conventions those plugin gems define. External, Collection::Gem,
ApiMap.load_with_cache, Shell cache/uncache and the Library cache
subprocess use the CacheDir of the workspace they serve. Path helpers
that do not depend on plugins stay class methods.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEntZKsZwQHhzqcwG7MTqn
CacheDir#add_plugin already records each plugin gem name and version,
so walking its conventions added nothing to the gem directory key.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEntZKsZwQHhzqcwG7MTqn
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SEntZKsZwQHhzqcwG7MTqn
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.

1 participant