From c771496ecd5d8699b22ab0f678f7dfc4c5970f93 Mon Sep 17 00:00:00 2001 From: ruisu Date: Wed, 5 Aug 2026 16:35:40 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E4=BC=98=E5=8C=96=E6=97=A5=E5=8E=86?= =?UTF-8?q?=E7=BC=93=E5=AD=98=EF=BC=8C=E9=87=87=E7=94=A8ConditionalWeakTab?= =?UTF-8?q?le=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../RiskEngine/Helper/RiskCalendarHelper.cs | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/YLErpDAL/Modules/RiskEngine/Helper/RiskCalendarHelper.cs b/YLErpDAL/Modules/RiskEngine/Helper/RiskCalendarHelper.cs index 6a02e77a..5109aee0 100644 --- a/YLErpDAL/Modules/RiskEngine/Helper/RiskCalendarHelper.cs +++ b/YLErpDAL/Modules/RiskEngine/Helper/RiskCalendarHelper.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Globalization; using System.Linq; +using System.Runtime.CompilerServices; using YLErp.BLL; namespace YLErp.Modules.RiskEngine @@ -13,6 +14,12 @@ namespace YLErp.Modules.RiskEngine /// public static class RiskCalendarHelper { + /// + /// 按当前风控执行使用的数据库上下文保存日历缓存,同一次风控检查内复用,数据库上下文释放后不阻止缓存被回收。 + /// + private static readonly ConditionalWeakTable>> HolidayCaches = + new ConditionalWeakTable>>(); + /// /// 获取指定日期的上一银行间交易日。 /// @@ -36,7 +43,8 @@ namespace YLErp.Modules.RiskEngine if (dbContext == null) throw new ArgumentNullException(nameof(dbContext)); - var holidayCache = new Dictionary>(); + // 以本次风控检查的数据库上下文为缓存边界,避免不同规则重复读取和解析相同市场日历。 + var holidayCache = HolidayCaches.GetOrCreateValue(dbContext); var currentDate = date.Date.AddDays(-1); // 最多向前查 370 天,既覆盖跨年和长假场景,也避免日历配置异常时出现无限循环。 @@ -60,11 +68,13 @@ namespace YLErp.Modules.RiskEngine /// /// 当前风控执行使用的数据库上下文。 /// 日历年份。 - /// 单次查询过程内的年份级缓存,跨年查找时避免重复读取同一年日历。 + /// 单次风控检查内按市场和年份共享的非交易日缓存。 /// 格式为 yyyy,MM,dd 的非交易日集合。 - private static HashSet GetHolidays(YLContext dbContext, int year, string country, string calendarName, Dictionary> holidayCache) + private static HashSet GetHolidays(YLContext dbContext, int year, string country, string calendarName, Dictionary> holidayCache) { - if (holidayCache.TryGetValue(year, out var holidays)) + // 缓存需要同时区分市场和年份,避免银行间与交易所同一年日历相互串用。 + var cacheKey = $"{country.ToUpperInvariant()}:{year}"; + if (holidayCache.TryGetValue(cacheKey, out var holidays)) return holidays; // 同一年可能存在多种市场日历,按规则对应的市场代码读取非交易日。 @@ -90,7 +100,7 @@ namespace YLErp.Modules.RiskEngine } holidays = new HashSet(holidayList ?? new List()); - holidayCache[year] = holidays; + holidayCache[cacheKey] = holidays; return holidays; } }