fix: stabilize rule config and cross-review backend

This commit is contained in:
wren
2026-05-11 02:03:01 +08:00
parent 900fc2e8a2
commit 32fb2a4812
14 changed files with 444 additions and 46 deletions
@@ -3,6 +3,8 @@
from __future__ import annotations
import hashlib
import logging
import time
from fastapi_common.fastapi_common_sqlalchemy.database import GetAsyncSession
from fastapi_common.fastapi_common_web.domain.responses import StatusCodeEnum
from fastapi_common.fastapi_common_web.exception.LeauditException import LeauditException
@@ -25,6 +27,9 @@ from fastapi_modules.fastapi_leaudit.services.impl.ruleGroupSupport import sync_
class RuleServiceImpl(IRuleService):
"""规则服务实现。"""
_GLOBAL_LIST_SETS_CACHE: tuple[float, list[RuleSetVO]] | None = None
_GLOBAL_RULE_COUNT_CACHE: dict[int, tuple[float, int]] = {}
def __init__(
self,
OssService: IOssService | None = None,
@@ -32,6 +37,21 @@ class RuleServiceImpl(IRuleService):
) -> None:
self.OssService = OssService or OssServiceImpl()
self.Validator = Validator or RuleValidator()
self._list_sets_cache = self.__class__._GLOBAL_LIST_SETS_CACHE
self._rule_count_cache = self.__class__._GLOBAL_RULE_COUNT_CACHE
@classmethod
def _set_list_sets_cache(cls, value: tuple[float, list[RuleSetVO]] | None) -> None:
cls._GLOBAL_LIST_SETS_CACHE = value
def InvalidateCaches(self, version_ids: list[int] | None = None) -> None:
"""清理规则集及规则数量缓存。"""
self.__class__._set_list_sets_cache(None)
if version_ids is None:
self._rule_count_cache.clear()
return
for version_id in {int(item) for item in version_ids if item is not None}:
self._rule_count_cache.pop(version_id, None)
async def _resolve_unique_child_group_id(self, Session, DocTypeId: int) -> int | None:
"""仅当文档类型唯一对应一个二级分组时,返回该分组ID。"""
@@ -71,6 +91,11 @@ class RuleServiceImpl(IRuleService):
async def ListSets(self) -> list[RuleSetVO]:
"""列出所有规则集。"""
now = time.monotonic()
cached = self.__class__._GLOBAL_LIST_SETS_CACHE
if cached and now - cached[0] <= 30:
return cached[1]
async with GetAsyncSession() as Session:
Result = await Session.execute(
text(
@@ -114,7 +139,7 @@ class RuleServiceImpl(IRuleService):
if usable_version_id is not None and int(usable_version_id) not in usable_counts:
usable_counts[int(usable_version_id)] = await self._GetRuleCountByVersionId(int(usable_version_id))
return [
items = [
RuleSetVO(
id=int(Row["id"]),
ruleType=Row["rule_type"],
@@ -130,9 +155,18 @@ class RuleServiceImpl(IRuleService):
)
for Row in rows
]
cache_value = (time.monotonic(), items)
self.__class__._set_list_sets_cache(cache_value)
self._list_sets_cache = cache_value
return items
async def _GetRuleCountByVersionId(self, VersionId: int) -> int:
"""读取指定可用规则版本的规则数。"""
cached = self._rule_count_cache.get(VersionId)
now = time.monotonic()
if cached and now - cached[0] <= 120:
return cached[1]
async with GetAsyncSession() as Session:
Result = await Session.execute(
text(
@@ -153,7 +187,9 @@ class RuleServiceImpl(IRuleService):
try:
yaml_text = (await self.OssService.DownloadBytes(Row["oss_url"])).decode("utf-8")
validation = self.Validator.ValidateYaml(yaml_text)
return int(validation.ruleCount or 0)
count = int(validation.ruleCount or 0)
self._rule_count_cache[VersionId] = (time.monotonic(), count)
return count
except Exception:
return 0
@@ -786,6 +822,16 @@ class RuleServiceImpl(IRuleService):
)
await Session.commit()
self.InvalidateCaches()
try:
from fastapi_modules.fastapi_leaudit.services.impl.ruleConfigServiceImpl import GetRuleConfigServiceSingleton
RuleConfigService = GetRuleConfigServiceSingleton()
RuleConfigService.InvalidateSummaryCaches()
await RuleConfigService.WarmPackSummaries(force=False)
except Exception as exc:
logging.getLogger("RULE").warning("刷新规则配置摘要缓存失败: %s", exc)
VersionRow = await self._GetVersion(Session, VersionId)
return self._BuildRuleVersionVo(VersionRow)
@@ -848,3 +894,14 @@ class RuleServiceImpl(IRuleService):
"legal_doc": "legal_doc",
}
return Mapping.get(Prefix, Prefix or "unknown")
_RULE_SERVICE_SINGLETON: RuleServiceImpl | None = None
def GetRuleServiceSingleton() -> RuleServiceImpl:
"""返回共享规则服务实例,供控制器与聚合服务复用缓存。"""
global _RULE_SERVICE_SINGLETON
if _RULE_SERVICE_SINGLETON is None:
_RULE_SERVICE_SINGLETON = RuleServiceImpl()
return _RULE_SERVICE_SINGLETON