fix(provider-mapping): 修复详情页映射延迟刷新并补齐 mapping-preview 缓存治理

- 前端:Provider 详情页在 key/模型关联/模型保存/映射保存后并行刷新 endpoints 与 mapping-preview
- 前端:为 mapping-preview 请求增加 requestId 保护,避免旧响应回写覆盖新状态
- 后端:Key.allowed_models 变更时按 provider 精准失效 mapping-preview 缓存
- 后端:GlobalModel 变更(含创建)时全量失效 mapping-preview 缓存
- 监控:在 Redis 缓存分类中新增 provider_mapping_preview(admin:providers:mapping-preview:*)

验证:
- frontend `npm run type-check`
- backend `python -m compileall`(相关文件)
- pytest 定向用例通过
This commit is contained in:
AAEE86
2026-03-11 09:58:25 +08:00
parent 6235c772ac
commit 4955166b85
4 changed files with 65 additions and 6 deletions

View File

@@ -427,6 +427,12 @@ class AdminCreateGlobalModelAdapter(AdminApiAdapter):
logger.info(f"GlobalModel 已创建: id={global_model.id} name={global_model.name}")
# 创建成功后失效缓存(避免 mapping-preview 在 TTL 内读到旧结果)
from src.services.cache.invalidation import get_cache_invalidation_service
cache_service = get_cache_invalidation_service()
await cache_service.on_global_model_changed(global_model.name, str(global_model.id))
return GlobalModelResponse.model_validate(global_model)

View File

@@ -1558,6 +1558,12 @@ _CACHE_CATEGORIES: list[tuple[str, str, str, str]] = [
"model:provider_global:*",
"Provider-GlobalModel 模型映射缓存",
),
(
"provider_mapping_preview",
"映射预览",
"admin:providers:mapping-preview:*",
"Provider 详情页 mapping-preview 缓存",
),
("global_model", "全局模型", "global_model:*", "GlobalModel 缓存ID/名称/解析)"),
("models_list", "模型列表", "models:list:*", "/v1/models 端点模型列表缓存"),
("user", "用户", "user:*", "用户信息缓存ID/Email"),

View File

@@ -6,10 +6,15 @@
from __future__ import annotations
import hashlib
import json
from typing import Any
from src.core.logger import logger
_PROVIDER_MAPPING_PREVIEW_CACHE_KEY_PREFIX = "admin:providers:mapping-preview:global"
_PROVIDER_MAPPING_PREVIEW_CACHE_PATTERN = f"{_PROVIDER_MAPPING_PREVIEW_CACHE_KEY_PREFIX}:v:*"
class CacheInvalidationService:
"""缓存失效服务"""
@@ -61,6 +66,12 @@ class CacheInvalidationService:
except Exception as e:
logger.error(f"[CacheInvalidation] 失效 models list 缓存失败: {e}")
# 5. 清除 Provider 映射预览缓存GlobalModel 映射规则变化会影响所有 Provider
try:
await self._invalidate_all_provider_mapping_preview_cache()
except Exception as e:
logger.error(f"[CacheInvalidation] 失效 Provider 映射预览缓存失败: {e}")
def on_model_changed(self, provider_id: str, global_model_id: str) -> Any:
"""Model 变更时的缓存失效"""
self._refresh_provider_cache(provider_id)
@@ -78,6 +89,12 @@ class CacheInvalidationService:
logger.info(f"[CacheInvalidation] Key allowed_models 变更: provider_id={provider_id}")
self._refresh_provider_cache(provider_id)
# 清除该 Provider 的映射预览缓存(详情页模型映射依赖)
try:
await self._invalidate_provider_mapping_preview_cache(provider_id)
except Exception as e:
logger.error(f"[CacheInvalidation] 失效 Provider 映射预览缓存失败: {e}")
# 清除 /v1/models 列表缓存allowed_models 变更会影响模型可用性)
from src.services.cache.model_list_cache import invalidate_models_list_cache
@@ -92,6 +109,31 @@ class CacheInvalidationService:
ModelMapperMiddleware.refresh_cache(provider_id)
@staticmethod
def _build_provider_mapping_preview_cache_key(provider_id: str) -> str:
"""构建指定 Provider 的 mapping-preview 缓存键。"""
raw = json.dumps(
{"provider_id": provider_id},
sort_keys=True,
ensure_ascii=False,
default=str,
)
vary_hash = hashlib.sha1(raw.encode("utf-8")).hexdigest()[:16]
return f"{_PROVIDER_MAPPING_PREVIEW_CACHE_KEY_PREFIX}:v:{vary_hash}"
async def _invalidate_provider_mapping_preview_cache(self, provider_id: str) -> None:
"""失效指定 Provider 的 mapping-preview 缓存。"""
from src.core.cache_service import CacheService
cache_key = self._build_provider_mapping_preview_cache_key(provider_id)
await CacheService.delete(cache_key)
async def _invalidate_all_provider_mapping_preview_cache(self) -> None:
"""失效所有 Provider 的 mapping-preview 缓存。"""
from src.core.cache_service import CacheService
await CacheService.delete_pattern(_PROVIDER_MAPPING_PREVIEW_CACHE_PATTERN)
def clear_all_caches(self) -> None:
"""清空所有缓存"""
from src.services.model.mapper import ModelMapperMiddleware