Skip to content

fix(plugins): revalidate the plugin registry instead of serving a stale cached list#1802

Merged
datlechin merged 1 commit into
mainfrom
fix/plugin-registry-stale-cache-1799
Jul 2, 2026
Merged

fix(plugins): revalidate the plugin registry instead of serving a stale cached list#1802
datlechin merged 1 commit into
mainfrom
fix/plugin-registry-stale-cache-1799

Conversation

@datlechin

Copy link
Copy Markdown
Member

Fixes #1799.

Problem

A plugin published to the registry after an app release never showed up: the install prompt failed with "Plugin not found" and Settings > Plugins > Browse did not list it, even across relaunches. Two defects compounded:

  1. Non-forced registry fetches never reached the network. RegistryClient left the URLSession cache policy at its default while the jsDelivr registry URL serves a 7-day max-age, so the OS URLCache answered fetches locally for a week. The hand-rolled ETag header never left the machine.
  2. Callers conflated "fetched this process" with "fresh". Browse fetched once per launch behind an idle-state gate, and the connection-form install path threw notFound from a stale lookup with no retry. lastFetchDate was written but never read.

Fix

  • RegistryClient now owns freshness. Callers express intent via ensureManifest(.ifStale | .mustBeCurrent); a 300s throttle and in-flight task dedup sit on top of .reloadRevalidatingCacheData, which sends a conditional GET on every real fetch (about 300 bytes on a 304). The manual ETag layer is deleted; URLCache handles validation natively.
  • Registry URL moves from jsDelivr to raw.githubusercontent.com (5-minute edge cache, strong ETag, no purge dependency). The CI purge step stays for apps 0.54.0 and earlier that still point at jsDelivr.
  • The install prompt force-revalidates and retries once before erroring, and a new PluginError.registryUnreachable separates "couldn't reach the registry" from a genuine "Plugin not found".
  • Browse renders the cached list instantly and revalidates in the background, gains a Refresh button in the loaded state, and shows a caption when a refresh failed and the list is served from cache. The app also revalidates once at launch.
  • The manifest disk copy moves from purgeable ~/Library/Caches to Application Support, with one-time migration.

Tests

New RegistryClientFreshnessTests (9 tests, mock URLProtocol): cache-policy shape, freshness throttle, forced revalidation, in-flight dedup, cached-fallback state, and the anchor regression (stale manifest without the plugin, fresh server copy with it, install no longer throws notFound). All existing RegistryClientURLTests and PluginManagerReconciliationTests pass unchanged. swiftlint --strict clean.

@mintlify

mintlify Bot commented Jul 2, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
TablePro 🔴 Failed Jul 2, 2026, 1:19 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@datlechin
datlechin merged commit 3a8061b into main Jul 2, 2026
3 checks passed
@datlechin
datlechin deleted the fix/plugin-registry-stale-cache-1799 branch July 2, 2026 13:18
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.

The Elasticsearch plugin is still not found in the registry

1 participant