feat:优化日历缓存,采用ConditionalWeakTable。
This commit is contained in:
@@ -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
|
||||
/// </summary>
|
||||
public static class RiskCalendarHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// 按当前风控执行使用的数据库上下文保存日历缓存,同一次风控检查内复用,数据库上下文释放后不阻止缓存被回收。
|
||||
/// </summary>
|
||||
private static readonly ConditionalWeakTable<YLContext, Dictionary<string, HashSet<string>>> HolidayCaches =
|
||||
new ConditionalWeakTable<YLContext, Dictionary<string, HashSet<string>>>();
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定日期的上一银行间交易日。
|
||||
/// </summary>
|
||||
@@ -36,7 +43,8 @@ namespace YLErp.Modules.RiskEngine
|
||||
if (dbContext == null)
|
||||
throw new ArgumentNullException(nameof(dbContext));
|
||||
|
||||
var holidayCache = new Dictionary<int, HashSet<string>>();
|
||||
// 以本次风控检查的数据库上下文为缓存边界,避免不同规则重复读取和解析相同市场日历。
|
||||
var holidayCache = HolidayCaches.GetOrCreateValue(dbContext);
|
||||
var currentDate = date.Date.AddDays(-1);
|
||||
|
||||
// 最多向前查 370 天,既覆盖跨年和长假场景,也避免日历配置异常时出现无限循环。
|
||||
@@ -60,11 +68,13 @@ namespace YLErp.Modules.RiskEngine
|
||||
/// </summary>
|
||||
/// <param name="dbContext">当前风控执行使用的数据库上下文。</param>
|
||||
/// <param name="year">日历年份。</param>
|
||||
/// <param name="holidayCache">单次查询过程内的年份级缓存,跨年查找时避免重复读取同一年日历。</param>
|
||||
/// <param name="holidayCache">单次风控检查内按市场和年份共享的非交易日缓存。</param>
|
||||
/// <returns>格式为 yyyy,MM,dd 的非交易日集合。</returns>
|
||||
private static HashSet<string> GetHolidays(YLContext dbContext, int year, string country, string calendarName, Dictionary<int, HashSet<string>> holidayCache)
|
||||
private static HashSet<string> GetHolidays(YLContext dbContext, int year, string country, string calendarName, Dictionary<string, HashSet<string>> 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<string>(holidayList ?? new List<string>());
|
||||
holidayCache[year] = holidays;
|
||||
holidayCache[cacheKey] = holidays;
|
||||
return holidays;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user