eclipse-theia/theia

vsx-registry: startup floods OVSX registries with per-builtin queries when updateInstalled() races the frontend plugin sync

Ouverte

#17 769 ouverte le 8 juil. 2026

 (1 commentaire) (2 réactions) (0 personne assignée)TypeScript (2 478 forks)batch import
bughelp wantedperformancevsx-registry

Métriques du dépôt

Stars
 (18 676 étoiles)
Métriques de merge PR
 (Merge moyen 15j 4h) (75 PRs mergées en 30 j)

Description

Bug Description:

VSXExtensionsModel can flood the configured OVSX registries with one metadata query per deployed builtin at startup, without the user ever opening the Extensions view.

Mechanism:

  • The model is instantiated eagerly (VSXExtensionsContribution is a FrontendApplicationContribution), and updateInstalled() calls refresh(id, version) for every id returned by getInstalledPluginIds() — which includes all deployed builtins.
  • refresh() is supposed to skip locally-known plugins via shouldRefresh() (extension.plugin === undefined), but that guard reads HostedPluginSupport.getPlugin(), whose contributions map is only populated by syncPlugins().
  • updateInstalled() re-runs immediately on every HostedPluginWatcher.onDidDeploy event, while the re-sync that populates the map is debounced (50 ms) and needs RPC round trips. When the frontend connects while the backend is still deploying (cold start — e.g. one backend per session in a container), the guard loses the race and every builtin looks unknown.
  • Each lost race costs findLatestCompatibleExtension per builtin = 2 queries (targetPlatform + universal, OVSXApiFilterImpl) × N registries (OVSXRouterClient fans out to all entries in use). With ~60 builtins and 2 registries that is ~240 HTTP calls per page load.

Suggested fix: make the guard race-free. updateInstalled() already fetches the deployed versioned ids into this.deployed before the refresh loop, so skipping refresh(id, version) when `${id}@${version}` is in that set avoids the dependency on frontend sync timing. We applied exactly that as a downstream override and it eliminates the storm with no UI regression (installed/builtin entries render from local deployment metadata, as intended).

Steps to Reproduce:

  1. Configure --ovsx-router-config with 2 registries in use, and deploy the builtins bundle via --plugins=local-dir:... (~60 plugins).
  2. Start the backend and connect a browser page while plugin deployment is still in progress (reliably reproduces when the backend cold-starts per session).
  3. Watch outgoing traffic: ~4 /api/v2/-/query?extensionId=vscode.*&extensionVersion=...&targetPlatform=... calls per builtin (2 target platforms × 2 registries), with the Extensions view never opened.

Additional Information

  • Operating System: any (observed on Linux containers and macOS)
  • Theia Version: 1.72.3 and 1.73 (relevant code identical in both)

Guide contributeur