mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-03 01:40:21 +08:00
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:
@@ -11,6 +11,7 @@ from fastapi import APIRouter, Depends, Query, Request
|
|||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from src.api.base.admin_adapter import AdminApiAdapter
|
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.api.base.pipeline import ApiRequestPipeline
|
||||||
from src.config.constants import RPMDefaults
|
from src.config.constants import RPMDefaults
|
||||||
from src.core.crypto import crypto_service
|
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:
|
if allowed_models_before != allowed_models_after and key.provider_id:
|
||||||
from src.services.model.global_model import on_key_allowed_models_changed
|
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,
|
db=db,
|
||||||
provider_id=key.provider_id,
|
provider_id=key.provider_id,
|
||||||
allowed_models=list(key.allowed_models or []),
|
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()))
|
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}")
|
logger.error(f"删除 Key 失败: ID={self.key_id}, Error={exc}")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
# 清除 /v1/models 列表缓存
|
||||||
|
await invalidate_models_list_cache()
|
||||||
|
|
||||||
logger.warning(f"[DELETE] 删除 Key: ID={self.key_id}, Provider={provider_id}")
|
logger.warning(f"[DELETE] 删除 Key: ID={self.key_id}, Provider={provider_id}")
|
||||||
return {"message": f"Key {self.key_id} 已删除"}
|
return {"message": f"Key {self.key_id} 已删除"}
|
||||||
|
|
||||||
@@ -641,14 +648,17 @@ class AdminCreateProviderKeyAdapter(AdminApiAdapter):
|
|||||||
logger.error(f"触发模型获取失败: {e}")
|
logger.error(f"触发模型获取失败: {e}")
|
||||||
# 不抛出异常,避免影响 Key 创建操作
|
# 不抛出异常,避免影响 Key 创建操作
|
||||||
|
|
||||||
# 如果创建时指定了 allowed_models,触发自动关联检查
|
# 如果创建时指定了 allowed_models,触发自动关联检查(内部会清除 /v1/models 缓存)
|
||||||
if new_key.allowed_models:
|
if new_key.allowed_models:
|
||||||
from src.services.model.global_model import on_key_allowed_models_changed
|
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,
|
db=db,
|
||||||
provider_id=self.provider_id,
|
provider_id=self.provider_id,
|
||||||
allowed_models=list(new_key.allowed_models),
|
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)
|
return _build_key_response(new_key, api_key_plain=self.key_data.api_key)
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ from sqlalchemy.orm import Session
|
|||||||
from sqlalchemy.orm.attributes import flag_modified
|
from sqlalchemy.orm.attributes import flag_modified
|
||||||
|
|
||||||
from src.api.base.admin_adapter import AdminApiAdapter
|
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.api.base.pipeline import ApiRequestPipeline
|
||||||
from src.core.exceptions import InvalidRequestException, NotFoundException
|
from src.core.exceptions import InvalidRequestException, NotFoundException
|
||||||
from src.core.logger import logger
|
from src.core.logger import logger
|
||||||
@@ -315,6 +316,9 @@ class AdminCreateProviderEndpointAdapter(AdminApiAdapter):
|
|||||||
db.commit()
|
db.commit()
|
||||||
db.refresh(new_endpoint)
|
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}")
|
logger.info(f"[OK] 创建 Endpoint: Provider={provider.name}, Format={self.endpoint_data.api_format}, ID={new_endpoint.id}")
|
||||||
|
|
||||||
endpoint_dict = {
|
endpoint_dict = {
|
||||||
@@ -414,6 +418,9 @@ class AdminUpdateProviderEndpointAdapter(AdminApiAdapter):
|
|||||||
db.commit()
|
db.commit()
|
||||||
db.refresh(endpoint)
|
db.refresh(endpoint)
|
||||||
|
|
||||||
|
# 清除 /v1/models 列表缓存(is_active 变更会影响模型可用性)
|
||||||
|
await invalidate_models_list_cache()
|
||||||
|
|
||||||
provider = db.query(Provider).filter(Provider.id == endpoint.provider_id).first()
|
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())}")
|
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.delete(endpoint)
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
|
# 清除 /v1/models 列表缓存
|
||||||
|
await invalidate_models_list_cache()
|
||||||
|
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f"[DELETE] 删除 Endpoint: ID={self.endpoint_id}, Format={endpoint_format}, "
|
f"[DELETE] 删除 Endpoint: ID={self.endpoint_id}, Format={endpoint_format}, "
|
||||||
f"AffectedKeys={affected_keys_count}"
|
f"AffectedKeys={affected_keys_count}"
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ from fastapi import APIRouter, Depends, Query, Request
|
|||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from src.api.base.admin_adapter import AdminApiAdapter
|
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.api.base.pipeline import ApiRequestPipeline
|
||||||
from src.core.logger import logger
|
from src.core.logger import logger
|
||||||
from src.database import get_db
|
from src.database import get_db
|
||||||
@@ -475,6 +476,10 @@ class AdminBatchAssignToProvidersAdapter(AdminApiAdapter):
|
|||||||
create_models=self.payload.create_models,
|
create_models=self.payload.create_models,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 如果有成功创建的关联,清除 /v1/models 列表缓存
|
||||||
|
if result["success"]:
|
||||||
|
await invalidate_models_list_cache()
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
f"批量为 Provider 添加 GlobalModel: global_model_id={self.global_model_id} success={len(result['success'])} errors={len(result['errors'])}"
|
f"批量为 Provider 添加 GlobalModel: global_model_id={self.global_model_id} success={len(result['success'])} errors={len(result['errors'])}"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from pydantic import BaseModel, ConfigDict, Field, ValidationError
|
|||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
from src.api.base.admin_adapter import AdminApiAdapter
|
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.api.base.pipeline import ApiRequestPipeline
|
||||||
from src.core.enums import ProviderBillingType
|
from src.core.enums import ProviderBillingType
|
||||||
from src.core.exceptions import InvalidRequestException, NotFoundException
|
from src.core.exceptions import InvalidRequestException, NotFoundException
|
||||||
@@ -300,6 +301,9 @@ class AdminCreateProviderAdapter(AdminApiAdapter):
|
|||||||
db.commit()
|
db.commit()
|
||||||
db.refresh(provider)
|
db.refresh(provider)
|
||||||
|
|
||||||
|
# 清除 /v1/models 列表缓存
|
||||||
|
await invalidate_models_list_cache()
|
||||||
|
|
||||||
context.add_audit_metadata(
|
context.add_audit_metadata(
|
||||||
action="create_provider",
|
action="create_provider",
|
||||||
provider_id=provider.id,
|
provider_id=provider.id,
|
||||||
@@ -366,6 +370,9 @@ class AdminUpdateProviderAdapter(AdminApiAdapter):
|
|||||||
db.commit()
|
db.commit()
|
||||||
db.refresh(provider)
|
db.refresh(provider)
|
||||||
|
|
||||||
|
# 清除 /v1/models 列表缓存(is_active 变更会影响模型可用性)
|
||||||
|
await invalidate_models_list_cache()
|
||||||
|
|
||||||
# 如果更新了 billing_type,清除缓存
|
# 如果更新了 billing_type,清除缓存
|
||||||
if "billing_type" in update_data:
|
if "billing_type" in update_data:
|
||||||
await ProviderCacheService.invalidate_provider_cache(provider.id)
|
await ProviderCacheService.invalidate_provider_cache(provider.id)
|
||||||
@@ -410,6 +417,10 @@ class AdminDeleteProviderAdapter(AdminApiAdapter):
|
|||||||
)
|
)
|
||||||
db.delete(provider)
|
db.delete(provider)
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
|
# 清除 /v1/models 列表缓存
|
||||||
|
await invalidate_models_list_cache()
|
||||||
|
|
||||||
return {"message": "提供商已删除"}
|
return {"message": "提供商已删除"}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -69,15 +69,12 @@ async def invalidate_models_list_cache() -> None:
|
|||||||
|
|
||||||
在模型创建、更新、删除时调用,确保模型列表实时更新
|
在模型创建、更新、删除时调用,确保模型列表实时更新
|
||||||
"""
|
"""
|
||||||
# 清除所有格式的缓存
|
try:
|
||||||
all_formats = ["CLAUDE", "OPENAI", "GEMINI"]
|
# 使用通配符删除所有 models:list:* 缓存(包括多格式组合的 key)
|
||||||
for fmt in all_formats:
|
deleted = await CacheService.delete_pattern(f"{_CACHE_KEY_PREFIX}:*")
|
||||||
cache_key = f"{_CACHE_KEY_PREFIX}:{fmt}"
|
logger.debug(f"[ModelsService] 已清除 {deleted} 个 {_CACHE_KEY_PREFIX} 缓存")
|
||||||
try:
|
except Exception as e:
|
||||||
await CacheService.delete(cache_key)
|
logger.warning(f"[ModelsService] 清除缓存失败: {e}")
|
||||||
logger.debug(f"[ModelsService] 已清除缓存: {cache_key}")
|
|
||||||
except Exception as e:
|
|
||||||
logger.warning(f"[ModelsService] 清除缓存失败 {cache_key}: {e}")
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|||||||
18
src/services/cache/invalidation.py
vendored
18
src/services/cache/invalidation.py
vendored
@@ -51,11 +51,19 @@ class CacheInvalidationService:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"[CacheInvalidation] 失效 ModelCacheService 缓存失败: {e}")
|
logger.error(f"[CacheInvalidation] 失效 ModelCacheService 缓存失败: {e}")
|
||||||
|
|
||||||
|
# 4. 清除 /v1/models 列表缓存
|
||||||
|
from src.api.base.models_service import invalidate_models_list_cache
|
||||||
|
|
||||||
|
try:
|
||||||
|
await invalidate_models_list_cache()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"[CacheInvalidation] 失效 models list 缓存失败: {e}")
|
||||||
|
|
||||||
def on_model_changed(self, provider_id: str, global_model_id: str):
|
def on_model_changed(self, provider_id: str, global_model_id: str):
|
||||||
"""Model 变更时的缓存失效"""
|
"""Model 变更时的缓存失效"""
|
||||||
self._refresh_provider_cache(provider_id)
|
self._refresh_provider_cache(provider_id)
|
||||||
|
|
||||||
def on_key_allowed_models_changed(self, provider_id: str) -> None:
|
async def on_key_allowed_models_changed(self, provider_id: str) -> None:
|
||||||
"""
|
"""
|
||||||
Key 的 allowed_models 变更时的缓存失效
|
Key 的 allowed_models 变更时的缓存失效
|
||||||
|
|
||||||
@@ -68,6 +76,14 @@ class CacheInvalidationService:
|
|||||||
logger.info(f"[CacheInvalidation] Key allowed_models 变更: provider_id={provider_id}")
|
logger.info(f"[CacheInvalidation] Key allowed_models 变更: provider_id={provider_id}")
|
||||||
self._refresh_provider_cache(provider_id)
|
self._refresh_provider_cache(provider_id)
|
||||||
|
|
||||||
|
# 清除 /v1/models 列表缓存(allowed_models 变更会影响模型可用性)
|
||||||
|
from src.api.base.models_service import invalidate_models_list_cache
|
||||||
|
|
||||||
|
try:
|
||||||
|
await invalidate_models_list_cache()
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"[CacheInvalidation] 失效 models list 缓存失败: {e}")
|
||||||
|
|
||||||
def _refresh_provider_cache(self, provider_id: str) -> None:
|
def _refresh_provider_cache(self, provider_id: str) -> None:
|
||||||
"""刷新指定 Provider 的 ModelMapper 缓存"""
|
"""刷新指定 Provider 的 ModelMapper 缓存"""
|
||||||
for mapper in self._model_mappers:
|
for mapper in self._model_mappers:
|
||||||
|
|||||||
@@ -360,7 +360,7 @@ class ModelFetchScheduler:
|
|||||||
if has_changed and provider_id:
|
if has_changed and provider_id:
|
||||||
from src.services.model.global_model import on_key_allowed_models_changed
|
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,
|
db=db,
|
||||||
provider_id=provider_id,
|
provider_id=provider_id,
|
||||||
allowed_models=list(key.allowed_models or []),
|
allowed_models=list(key.allowed_models or []),
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ from src.models.database import GlobalModel, Model
|
|||||||
from src.models.pydantic_models import GlobalModelUpdate
|
from src.models.pydantic_models import GlobalModelUpdate
|
||||||
|
|
||||||
|
|
||||||
def on_key_allowed_models_changed(
|
async def on_key_allowed_models_changed(
|
||||||
db: Session,
|
db: Session,
|
||||||
provider_id: str,
|
provider_id: str,
|
||||||
allowed_models: List[str],
|
allowed_models: List[str],
|
||||||
@@ -24,7 +24,7 @@ def on_key_allowed_models_changed(
|
|||||||
Key 的 allowed_models 变更后的统一处理
|
Key 的 allowed_models 变更后的统一处理
|
||||||
|
|
||||||
包括:
|
包括:
|
||||||
1. 触发缓存失效
|
1. 触发缓存失效(包括 /v1/models 列表缓存)
|
||||||
2. 检查并自动关联匹配的 GlobalModel
|
2. 检查并自动关联匹配的 GlobalModel
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -36,7 +36,7 @@ def on_key_allowed_models_changed(
|
|||||||
|
|
||||||
# 1. 触发缓存失效
|
# 1. 触发缓存失效
|
||||||
cache_service = get_cache_invalidation_service()
|
cache_service = get_cache_invalidation_service()
|
||||||
cache_service.on_key_allowed_models_changed(provider_id)
|
await cache_service.on_key_allowed_models_changed(provider_id)
|
||||||
|
|
||||||
# 2. 检查并自动关联 GlobalModel
|
# 2. 检查并自动关联 GlobalModel
|
||||||
if allowed_models:
|
if allowed_models:
|
||||||
|
|||||||
Reference in New Issue
Block a user