fix: 在 Provider/Endpoint/Key 变更时清除 /v1/models 列表缓存

- 将 on_key_allowed_models_changed 改为 async 函数
- 在 Provider/Endpoint/Key 的增删改操作后调用 invalidate_models_list_cache
- 优化 invalidate_models_list_cache 使用 delete_pattern 通配符删除
This commit is contained in:
fawney19
2026-01-16 19:42:35 +08:00
parent 019e148ddb
commit 45f071abd9
8 changed files with 66 additions and 17 deletions

View File

@@ -11,6 +11,7 @@ from fastapi import APIRouter, Depends, Query, Request
from sqlalchemy.orm import Session
from src.api.base.admin_adapter import AdminApiAdapter
from src.api.base.models_service import invalidate_models_list_cache
from src.api.base.pipeline import ApiRequestPipeline
from src.config.constants import RPMDefaults
from src.core.crypto import crypto_service
@@ -295,11 +296,14 @@ class AdminUpdateEndpointKeyAdapter(AdminApiAdapter):
if allowed_models_before != allowed_models_after and key.provider_id:
from src.services.model.global_model import on_key_allowed_models_changed
on_key_allowed_models_changed(
await on_key_allowed_models_changed(
db=db,
provider_id=key.provider_id,
allowed_models=list(key.allowed_models or []),
)
else:
# allowed_models 未变化时,仍需清除 /v1/models 缓存is_active、api_formats 变更会影响模型可用性)
await invalidate_models_list_cache()
logger.info("[OK] 更新 Key: ID=%s, Updates=%s", self.key_id, list(update_data.keys()))
@@ -349,6 +353,9 @@ class AdminDeleteEndpointKeyAdapter(AdminApiAdapter):
logger.error(f"删除 Key 失败: ID={self.key_id}, Error={exc}")
raise
# 清除 /v1/models 列表缓存
await invalidate_models_list_cache()
logger.warning(f"[DELETE] 删除 Key: ID={self.key_id}, Provider={provider_id}")
return {"message": f"Key {self.key_id} 已删除"}
@@ -641,14 +648,17 @@ class AdminCreateProviderKeyAdapter(AdminApiAdapter):
logger.error(f"触发模型获取失败: {e}")
# 不抛出异常,避免影响 Key 创建操作
# 如果创建时指定了 allowed_models触发自动关联检查
# 如果创建时指定了 allowed_models触发自动关联检查(内部会清除 /v1/models 缓存)
if new_key.allowed_models:
from src.services.model.global_model import on_key_allowed_models_changed
on_key_allowed_models_changed(
await on_key_allowed_models_changed(
db=db,
provider_id=self.provider_id,
allowed_models=list(new_key.allowed_models),
)
else:
# 没有 allowed_models 时,仍需清除 /v1/models 缓存
await invalidate_models_list_cache()
return _build_key_response(new_key, api_key_plain=self.key_data.api_key)

View File

@@ -13,6 +13,7 @@ from sqlalchemy.orm import Session
from sqlalchemy.orm.attributes import flag_modified
from src.api.base.admin_adapter import AdminApiAdapter
from src.api.base.models_service import invalidate_models_list_cache
from src.api.base.pipeline import ApiRequestPipeline
from src.core.exceptions import InvalidRequestException, NotFoundException
from src.core.logger import logger
@@ -315,6 +316,9 @@ class AdminCreateProviderEndpointAdapter(AdminApiAdapter):
db.commit()
db.refresh(new_endpoint)
# 清除 /v1/models 列表缓存
await invalidate_models_list_cache()
logger.info(f"[OK] 创建 Endpoint: Provider={provider.name}, Format={self.endpoint_data.api_format}, ID={new_endpoint.id}")
endpoint_dict = {
@@ -414,6 +418,9 @@ class AdminUpdateProviderEndpointAdapter(AdminApiAdapter):
db.commit()
db.refresh(endpoint)
# 清除 /v1/models 列表缓存is_active 变更会影响模型可用性)
await invalidate_models_list_cache()
provider = db.query(Provider).filter(Provider.id == endpoint.provider_id).first()
logger.info(f"[OK] 更新 Endpoint: ID={self.endpoint_id}, Updates={list(update_data.keys())}")
@@ -482,6 +489,9 @@ class AdminDeleteProviderEndpointAdapter(AdminApiAdapter):
db.delete(endpoint)
db.commit()
# 清除 /v1/models 列表缓存
await invalidate_models_list_cache()
logger.warning(
f"[DELETE] 删除 Endpoint: ID={self.endpoint_id}, Format={endpoint_format}, "
f"AffectedKeys={affected_keys_count}"

View File

@@ -11,6 +11,7 @@ from fastapi import APIRouter, Depends, Query, Request
from sqlalchemy.orm import Session
from src.api.base.admin_adapter import AdminApiAdapter
from src.api.base.models_service import invalidate_models_list_cache
from src.api.base.pipeline import ApiRequestPipeline
from src.core.logger import logger
from src.database import get_db
@@ -475,6 +476,10 @@ class AdminBatchAssignToProvidersAdapter(AdminApiAdapter):
create_models=self.payload.create_models,
)
# 如果有成功创建的关联,清除 /v1/models 列表缓存
if result["success"]:
await invalidate_models_list_cache()
logger.info(
f"批量为 Provider 添加 GlobalModel: global_model_id={self.global_model_id} success={len(result['success'])} errors={len(result['errors'])}"
)

View File

@@ -9,6 +9,7 @@ from pydantic import BaseModel, ConfigDict, Field, ValidationError
from sqlalchemy.orm import Session
from src.api.base.admin_adapter import AdminApiAdapter
from src.api.base.models_service import invalidate_models_list_cache
from src.api.base.pipeline import ApiRequestPipeline
from src.core.enums import ProviderBillingType
from src.core.exceptions import InvalidRequestException, NotFoundException
@@ -300,6 +301,9 @@ class AdminCreateProviderAdapter(AdminApiAdapter):
db.commit()
db.refresh(provider)
# 清除 /v1/models 列表缓存
await invalidate_models_list_cache()
context.add_audit_metadata(
action="create_provider",
provider_id=provider.id,
@@ -366,6 +370,9 @@ class AdminUpdateProviderAdapter(AdminApiAdapter):
db.commit()
db.refresh(provider)
# 清除 /v1/models 列表缓存is_active 变更会影响模型可用性)
await invalidate_models_list_cache()
# 如果更新了 billing_type清除缓存
if "billing_type" in update_data:
await ProviderCacheService.invalidate_provider_cache(provider.id)
@@ -410,6 +417,10 @@ class AdminDeleteProviderAdapter(AdminApiAdapter):
)
db.delete(provider)
db.commit()
# 清除 /v1/models 列表缓存
await invalidate_models_list_cache()
return {"message": "提供商已删除"}

View File

@@ -69,15 +69,12 @@ async def invalidate_models_list_cache() -> None:
在模型创建、更新、删除时调用,确保模型列表实时更新
"""
# 清除所有格式的缓存
all_formats = ["CLAUDE", "OPENAI", "GEMINI"]
for fmt in all_formats:
cache_key = f"{_CACHE_KEY_PREFIX}:{fmt}"
try:
await CacheService.delete(cache_key)
logger.debug(f"[ModelsService] 已清除缓存: {cache_key}")
except Exception as e:
logger.warning(f"[ModelsService] 清除缓存失败 {cache_key}: {e}")
try:
# 使用通配符删除所有 models:list:* 缓存(包括多格式组合的 key
deleted = await CacheService.delete_pattern(f"{_CACHE_KEY_PREFIX}:*")
logger.debug(f"[ModelsService] 已清除 {deleted}{_CACHE_KEY_PREFIX} 缓存")
except Exception as e:
logger.warning(f"[ModelsService] 清除缓存失败: {e}")
@dataclass