Przeglądaj źródła

feat: Add caching mechanism for latest plugin version retrieval (#14968)

tags/1.0.1
Yeuoly 8 miesięcy temu
rodzic
commit
cef49da576
No account linked to committer's email address
1 zmienionych plików z 70 dodań i 7 usunięć
  1. 70
    7
      api/services/plugin/plugin_service.py

+ 70
- 7
api/services/plugin/plugin_service.py Wyświetl plik

import logging import logging
from collections.abc import Sequence
from collections.abc import Mapping, Sequence
from mimetypes import guess_type from mimetypes import guess_type
from typing import Optional

from pydantic import BaseModel


from configs import dify_config from configs import dify_config
from core.helper import marketplace from core.helper import marketplace
from core.plugin.manager.asset import PluginAssetManager from core.plugin.manager.asset import PluginAssetManager
from core.plugin.manager.debugging import PluginDebuggingManager from core.plugin.manager.debugging import PluginDebuggingManager
from core.plugin.manager.plugin import PluginInstallationManager from core.plugin.manager.plugin import PluginInstallationManager
from extensions.ext_redis import redis_client


logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)




class PluginService: class PluginService:
class LatestPluginCache(BaseModel):
plugin_id: str
version: str
unique_identifier: str

REDIS_KEY_PREFIX = "plugin_service:latest_plugin:"
REDIS_TTL = 60 * 5 # 5 minutes

@staticmethod
def fetch_latest_plugin_version(plugin_ids: Sequence[str]) -> Mapping[str, Optional[LatestPluginCache]]:
"""
Fetch the latest plugin version
"""
result: dict[str, Optional[PluginService.LatestPluginCache]] = {}

try:
cache_not_exists = []

# Try to get from Redis first
for plugin_id in plugin_ids:
cached_data = redis_client.get(f"{PluginService.REDIS_KEY_PREFIX}{plugin_id}")
if cached_data:
result[plugin_id] = PluginService.LatestPluginCache.model_validate_json(cached_data)
else:
cache_not_exists.append(plugin_id)

if cache_not_exists:
manifests = {
manifest.plugin_id: manifest
for manifest in marketplace.batch_fetch_plugin_manifests(cache_not_exists)
}

for plugin_id, manifest in manifests.items():
latest_plugin = PluginService.LatestPluginCache(
plugin_id=plugin_id,
version=manifest.latest_version,
unique_identifier=manifest.latest_package_identifier,
)

# Store in Redis
redis_client.setex(
f"{PluginService.REDIS_KEY_PREFIX}{plugin_id}",
PluginService.REDIS_TTL,
latest_plugin.model_dump_json(),
)

result[plugin_id] = latest_plugin

# pop plugin_id from cache_not_exists
cache_not_exists.remove(plugin_id)

for plugin_id in cache_not_exists:
result[plugin_id] = None

return result
except Exception:
logger.exception("failed to fetch latest plugin version")
return result

@staticmethod @staticmethod
def get_debugging_key(tenant_id: str) -> str: def get_debugging_key(tenant_id: str) -> str:
""" """
plugins = manager.list_plugins(tenant_id) plugins = manager.list_plugins(tenant_id)
plugin_ids = [plugin.plugin_id for plugin in plugins if plugin.source == PluginInstallationSource.Marketplace] plugin_ids = [plugin.plugin_id for plugin in plugins if plugin.source == PluginInstallationSource.Marketplace]
try: try:
manifests = {
manifest.plugin_id: manifest for manifest in marketplace.batch_fetch_plugin_manifests(plugin_ids)
}
manifests = PluginService.fetch_latest_plugin_version(plugin_ids)
except Exception: except Exception:
manifests = {} manifests = {}
logger.exception("failed to fetch plugin manifests") logger.exception("failed to fetch plugin manifests")
for plugin in plugins: for plugin in plugins:
if plugin.source == PluginInstallationSource.Marketplace: if plugin.source == PluginInstallationSource.Marketplace:
if plugin.plugin_id in manifests: if plugin.plugin_id in manifests:
# set latest_version
plugin.latest_version = manifests[plugin.plugin_id].latest_version
plugin.latest_unique_identifier = manifests[plugin.plugin_id].latest_package_identifier
latest_plugin_cache = manifests[plugin.plugin_id]
if latest_plugin_cache:
# set latest_version
plugin.latest_version = latest_plugin_cache.version
plugin.latest_unique_identifier = latest_plugin_cache.unique_identifier


return plugins return plugins



Ładowanie…
Anuluj
Zapisz