优化缓存刷新逻辑
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using BaseOUDAL;
|
||||
using Newtonsoft.Json;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text.RegularExpressions;
|
||||
using YLErp.BLL;
|
||||
using YLErp.DBModels;
|
||||
using YLErp.Modules.RiskEngine.Dto;
|
||||
@@ -113,7 +114,7 @@ using YLErp.Modules.RiskEngine.Dto;
|
||||
ValidateTriggerPoints(triggerPoints) 触发时点校验(5 个合法时点)
|
||||
ValidateScopeFields(req) Scope 字段校验(全局互斥 + ID 格式校验)
|
||||
ValidateIdList(idList, fieldName) ID 列表格式校验
|
||||
TryRefreshCache() 安全调用 RefreshCache(失败仅记日志)
|
||||
RefreshOneRuleCache(ruleId) 单条规则缓存刷新(规则变更后调用)
|
||||
GetRuleOrThrow / GetApplicationOrThrow / GetVariableOrThrow 实体获取快捷方法
|
||||
|
||||
【关键设计决策】
|
||||
@@ -124,7 +125,7 @@ using YLErp.Modules.RiskEngine.Dto;
|
||||
5. ConditionJson 校验:变量存在性(按 VariableId)+ 操作符合法性(按 DataType 映射)+ 类型匹配 + 阈值变量引用
|
||||
6. RuleExpr:自由文本模式下前端直接编辑,后端做基础语法校验(括号匹配 + 变量引用校验)
|
||||
7. Scope 字段:逗号分隔字符串存储,全局适用时不允许指定其他维度
|
||||
8. 缓存刷新:写操作后调用 TryRefreshCache(),失败仅记日志不影响操作结果
|
||||
8. 缓存刷新:规则变更后调用 RefreshOneRuleCache(ruleId),应用变更后调用 RefreshApplication()
|
||||
9. 批量操作:单事务批量,全部成功或全部失败
|
||||
10. 变量缓存:5 分钟本地 HashSet<string> 缓存,CRUD 后 InvalidateVariableCache()
|
||||
11. 审计日志:16 种操作类型,CRUD + 审计日志同一事务,SnapshotData 存储版本快照
|
||||
@@ -172,7 +173,7 @@ using YLErp.Modules.RiskEngine.Dto;
|
||||
|
||||
【注意事项】
|
||||
1. RiskEngineService 由另一个团队开发实现,本服务通过 GetInstance() 获取单例引用
|
||||
2. 所有写操作后必须调用 TryRefreshCache(),确保引擎缓存与数据库一致
|
||||
2. 规则变更后调用 RefreshOneRuleCache(ruleId),应用变更后调用 RefreshApplication(),变量变更不触发引擎缓存刷新
|
||||
3. 变量删除为硬删除(物理删除),规则/应用删除为软删除(Status=Deleted)
|
||||
4. ExportAuditLogs 当前为占位实现,Excel 导出功能待后续迭代
|
||||
5. VariableExpr 当前仅做基础长度校验(≤10000),完整编译校验待引入 Roslyn 库
|
||||
@@ -850,7 +851,7 @@ namespace YLErp.Modules.RiskEngine
|
||||
WriteAuditLog("RULE_DELETE", "RULE", ruleId, rule.RuleName, "删除规则");
|
||||
DbContext.SaveChanges();
|
||||
|
||||
TryRefreshCache();
|
||||
RiskEngineService.GetInstance().RefreshOneRuleCache(ruleId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -870,7 +871,7 @@ namespace YLErp.Modules.RiskEngine
|
||||
WriteAuditLog("RULE_ENABLE", "RULE", ruleId, rule.RuleName, "启用规则");
|
||||
DbContext.SaveChanges();
|
||||
|
||||
TryRefreshCache();
|
||||
RiskEngineService.GetInstance().RefreshOneRuleCache(ruleId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -890,7 +891,7 @@ namespace YLErp.Modules.RiskEngine
|
||||
WriteAuditLog("RULE_DISABLE", "RULE", ruleId, rule.RuleName, "停用规则");
|
||||
DbContext.SaveChanges();
|
||||
|
||||
TryRefreshCache();
|
||||
RiskEngineService.GetInstance().RefreshOneRuleCache(ruleId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -966,7 +967,10 @@ namespace YLErp.Modules.RiskEngine
|
||||
}
|
||||
|
||||
DbContext.SaveChanges();
|
||||
TryRefreshCache();
|
||||
foreach (var ruleId in ruleIds)
|
||||
{
|
||||
RiskEngineService.GetInstance().RefreshOneRuleCache(ruleId);
|
||||
}
|
||||
|
||||
return new BatchOperationResult
|
||||
{
|
||||
@@ -1372,6 +1376,27 @@ namespace YLErp.Modules.RiskEngine
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 查询 ConditionJson 中引用了指定变量 ID 的规则(仅结构化模式)
|
||||
/// 精确匹配 "VariableId":{id} 或 "ThresholdVariableId":{id},\b 防止 id=1 误匹配 id=10
|
||||
/// </summary>
|
||||
private List<glms_risk_rule> GetRulesByVariableId(long variableId)
|
||||
{
|
||||
var allRules = DbContext.glms_risk_rule
|
||||
.Where(r => r.Status != RiskRuleStatus.Deleted && r.ConditionJson != null)
|
||||
.ToList();
|
||||
|
||||
if (allRules.Count == 0) return allRules;
|
||||
|
||||
var idPattern = $@"""VariableId""\s*:\s*{variableId}\b";
|
||||
var thresholdPattern = $@"""ThresholdVariableId""\s*:\s*{variableId}\b";
|
||||
|
||||
return allRules.Where(r =>
|
||||
Regex.IsMatch(r.ConditionJson, idPattern) ||
|
||||
Regex.IsMatch(r.ConditionJson, thresholdPattern)
|
||||
).ToList();
|
||||
}
|
||||
|
||||
#region Variable Management
|
||||
|
||||
/// <summary>
|
||||
@@ -1498,7 +1523,6 @@ namespace YLErp.Modules.RiskEngine
|
||||
}
|
||||
|
||||
InvalidateVariableCache();
|
||||
TryRefreshCache();
|
||||
|
||||
return GetVariableDetail(entity.id);
|
||||
}
|
||||
@@ -1520,11 +1544,8 @@ namespace YLErp.Modules.RiskEngine
|
||||
|
||||
if (req.DataType != variable.DataType)
|
||||
{
|
||||
var varExpr = variable.VariableExpr;
|
||||
var activeRefCount = DbContext.glms_risk_rule
|
||||
.Count(r => r.Status == RiskRuleStatus.Active &&
|
||||
((r.ConditionJson != null && r.ConditionJson.Contains(variable.id.ToString())) ||
|
||||
(r.RuleExpr != null && varExpr != null && r.RuleExpr.Contains(varExpr))));
|
||||
var activeRefCount = GetRulesByVariableId(variableId)
|
||||
.Count(r => r.Status == RiskRuleStatus.Active);
|
||||
if (activeRefCount > 0)
|
||||
throw new ServiceException($"该变量被 {activeRefCount} 个生效中的规则引用,无法修改数据类型");
|
||||
}
|
||||
@@ -1548,9 +1569,9 @@ namespace YLErp.Modules.RiskEngine
|
||||
|
||||
if (variableExprChanged)
|
||||
{
|
||||
// 编译校验:变量表达式变更后,需验证所有级联更新的规则表达式可编译
|
||||
var affectedRules = DbContext.glms_risk_rule
|
||||
.Where(r => r.RuleExpr != null && r.RuleExpr.Contains(oldVariableExpr))
|
||||
// 结构化模式:通过 ConditionJson 中的 VariableId 找到受影响的规则
|
||||
var affectedRules = GetRulesByVariableId(variableId)
|
||||
.Where(r => r.RuleExpr != null)
|
||||
.ToList();
|
||||
|
||||
var compileTasks = affectedRules.Select(r =>
|
||||
@@ -1618,11 +1639,8 @@ namespace YLErp.Modules.RiskEngine
|
||||
{
|
||||
var variable = GetVariableOrThrow(variableId);
|
||||
|
||||
var varExpr = variable.VariableExpr;
|
||||
var activeRefCount = DbContext.glms_risk_rule
|
||||
.Count(r => r.Status == RiskRuleStatus.Active &&
|
||||
((r.ConditionJson != null && r.ConditionJson.Contains(variable.id.ToString())) ||
|
||||
(r.RuleExpr != null && varExpr != null && r.RuleExpr.Contains(varExpr))));
|
||||
var activeRefCount = GetRulesByVariableId(variableId)
|
||||
.Count(r => r.Status == RiskRuleStatus.Active);
|
||||
if (activeRefCount > 0)
|
||||
throw new ServiceException($"该变量被 {activeRefCount} 个生效中的规则引用,无法删除");
|
||||
|
||||
@@ -1632,7 +1650,6 @@ namespace YLErp.Modules.RiskEngine
|
||||
DbContext.SaveChanges();
|
||||
|
||||
InvalidateVariableCache();
|
||||
TryRefreshCache();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user