perf(store): cache GitHub API calls and eliminate redundant requests (#251)

The plugin store was making excessive GitHub API calls causing slow
page loads (10-30s):

- Installed plugins endpoint called get_plugin_info() per plugin (3
  GitHub API calls each) just to read the `verified` field from the
  registry. Use new get_registry_info() instead (zero API calls).
- _get_latest_commit_info() had no cache — all 31 monorepo plugins
  share the same repo URL, causing 31 identical API calls. Add 5-min
  cache keyed by repo:branch.
- _fetch_manifest_from_github() also uncached — add 5-min cache.
- load_config() called inside loop per-plugin — hoist outside loop.
- Install/update operations pass force_refresh=True to bypass caches
  and always get the latest commit SHA from GitHub.

Co-authored-by: Chuck <chuck@example.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Chuck
2026-02-15 14:46:31 -05:00
committed by GitHub
parent 5b0ad5ab71
commit 22c495ea7c
3 changed files with 75 additions and 22 deletions

View File

@@ -1737,6 +1737,9 @@ def get_installed_plugins():
# Get all installed plugin info from the plugin manager
all_plugin_info = api_v3.plugin_manager.get_all_plugin_info()
# Load config once before the loop (not per-plugin)
full_config = api_v3.config_manager.load_config() if api_v3.config_manager else {}
# Format for the web interface
plugins = []
for plugin_info in all_plugin_info:
@@ -1758,7 +1761,6 @@ def get_installed_plugins():
# Read from config file first, fall back to plugin instance if config doesn't have the key
enabled = None
if api_v3.config_manager:
full_config = api_v3.config_manager.load_config()
plugin_config = full_config.get(plugin_id, {})
# Check if 'enabled' key exists in config (even if False)
if 'enabled' in plugin_config:
@@ -1773,8 +1775,8 @@ def get_installed_plugins():
# Default to True if no config key and plugin not loaded (matches BasePlugin default)
enabled = True
# Get verified status from store registry (if available)
store_info = api_v3.plugin_store_manager.get_plugin_info(plugin_id)
# Get verified status from store registry (no GitHub API calls needed)
store_info = api_v3.plugin_store_manager.get_registry_info(plugin_id)
verified = store_info.get('verified', False) if store_info else False
# Get local git info for installed plugin (actual installed commit)

View File

@@ -186,6 +186,9 @@ def _load_plugins_partial():
# Get all installed plugin info
all_plugin_info = pages_v3.plugin_manager.get_all_plugin_info()
# Load config once before the loop (not per-plugin)
full_config = pages_v3.config_manager.load_config() if pages_v3.config_manager else {}
# Format for the web interface
for plugin_info in all_plugin_info:
plugin_id = plugin_info.get('id')
@@ -206,7 +209,6 @@ def _load_plugins_partial():
# Read from config file first, fall back to plugin instance if config doesn't have the key
enabled = None
if pages_v3.config_manager:
full_config = pages_v3.config_manager.load_config()
plugin_config = full_config.get(plugin_id, {})
# Check if 'enabled' key exists in config (even if False)
if 'enabled' in plugin_config:
@@ -221,8 +223,8 @@ def _load_plugins_partial():
# Default to True if no config key and plugin not loaded (matches BasePlugin default)
enabled = True
# Get verified status from store registry
store_info = pages_v3.plugin_store_manager.get_plugin_info(plugin_id)
# Get verified status from store registry (no GitHub API calls needed)
store_info = pages_v3.plugin_store_manager.get_registry_info(plugin_id)
verified = store_info.get('verified', False) if store_info else False
last_updated = plugin_info.get('last_updated')