using dodohold.core; using molilian.core; using Org.BouncyCastle.Crypto; using System; using System.Collections.Concurrent; using System.Linq; using YunhuiKit; using static molilian.core.TkPoolCore; public partial class TkEndpointCore { private static SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); private static IEnumerable _cached; // 添加到 TkEndpointCore 类中 private static readonly ConcurrentDictionary<(int, bool?), List> _accountEndpointCache = new(); private static async Task> ListAsync(bool force = false) { // 内存缓存检查 if (!force && _cached != null) return _cached; string cache_key = "cache:tk_endpoint_config"; if (!force) { var cachedList = await RedisHelper.GetAsync>(cache_key); if (cachedList != null) { _cached = cachedList; return cachedList; } } // 获取新数据 await _semaphore.WaitAsync(); try { // 双重检查,防止并发情况下重复加载 if (!force) { var cachedList = await RedisHelper.GetAsync>(cache_key); if (cachedList != null) { _cached = cachedList; return cachedList; } } // 从数据库加载数据 var list = new DBContext.Table("tk_endpoint_config") .Where("status=@status", new { status = 1 }) .Select(); if (list == null) return default; // 更新调用次数 //foreach (var item in list) //{ // item.current_daily_calls = await RiskControlCore.GetAllNodesTkEndpointCallsAsync(item.id, DateTime.Now.ToString("yyyyMMdd")); // item.current_hourly_calls = await RiskControlCore.GetAllNodesTkEndpointCallsAsync(item.id, DateTime.Now.ToString("yyyyMMddHH")); //} // 更新缓存 await RedisHelper.SetAsync(cache_key, list, 30 * 86400); _cached = list; _accountEndpointCache.Clear(); return list; } finally { _semaphore.Release(); } } public static async Task> GetEndpointsByAccountAsync(int accountId, bool? isTaobaoUrl = null, string parseEndpoints = null) { var cacheKey = (accountId, isTaobaoUrl); if (_accountEndpointCache.TryGetValue(cacheKey, out var cached)) return cached.Select(x => x.DeepCopy()).ToList(); // 2. 获取所有端点(包含全局和专属) var allEndpoints = (await ListAsync())?.Where(e => e.status).ToList() ?? []; // 3. 合并逻辑:专属配置覆盖全局配置(关键!) var mergedEndpoints = allEndpoints .GroupBy(e => e.endpoint) .Select(g => { // 优先取专属配置 var accountSpecific = g.FirstOrDefault(e => e.tk_pool_id == accountId); if (accountSpecific != null) return accountSpecific.DeepCopy(); // 深拷贝专属配置 // 否则取全局配置(tk_pool_id=0) var global = g.FirstOrDefault(e => e.tk_pool_id == 0); return global?.DeepCopy(); // 深拷贝全局配置 }) .Where(e => e != null) .ToList(); // 4. 根据isTaobaoUrl过滤 if (isTaobaoUrl.HasValue) { mergedEndpoints = mergedEndpoints.Where(e => { if (e.taobao_id_handling == 0) return true; if (e.taobao_id_handling == 1 && isTaobaoUrl.Value) return true; if (e.taobao_id_handling == 2 && !isTaobaoUrl.Value) return true; return false; }).ToList(); } // 5. 排除指定的端点 if (!string.IsNullOrEmpty(parseEndpoints)) { var parseEndpointIds = parseEndpoints.Split(',') .Select(idStr => int.TryParse(idStr.Trim(), out var id) ? id : (int?)null) .Where(id => id.HasValue) .Select(id => id.Value) .ToHashSet(); mergedEndpoints = mergedEndpoints.Where(e => parseEndpointIds.Contains(e.ep_id)).ToList(); } // 6. 存入缓存 _accountEndpointCache.TryAdd(cacheKey, mergedEndpoints.Select(x => x.DeepCopy()).ToList()); return mergedEndpoints; } // 添加缓存清理方法 public static void ClearEndpointCache(int accountId) { _accountEndpointCache.TryRemove((accountId, true), out _); _accountEndpointCache.TryRemove((accountId, false), out _); _accountEndpointCache.TryRemove((accountId, null), out _); } public static void Refresh() { _ = AllListAsync(true); _ = ListAsync(true); _accountEndpointCache.Clear(); } }