using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Linq; using System.Net; namespace FastGithub.Scanner { /// /// GithubContext集合 /// [Service(ServiceLifetime.Singleton)] sealed class GithubScanResults : IGithubScanResults { private readonly object syncRoot = new(); private readonly List contexts = new(); private readonly IMemoryCache memoryCache; private readonly IOptionsMonitor options; public GithubScanResults( IMemoryCache memoryCache, IOptionsMonitor options) { this.memoryCache = memoryCache; this.options = options; } /// /// 添加GithubContext /// /// /// public bool Add(GithubContext context) { lock (this.syncRoot) { if (this.contexts.Contains(context)) { return false; } this.contexts.Add(context); return true; } } /// /// 转换为数组 /// /// public GithubContext[] ToArray() { lock (this.syncRoot) { return this.contexts.ToArray(); } } /// /// 查找最优的ip /// /// /// public IPAddress? FindBestAddress(string domain) { var key = $"domain:{domain}"; return this.memoryCache.GetOrCreate(key, e => { e.SetAbsoluteExpiration(TimeSpan.FromSeconds(1d)); return this.Resolve(domain); }); } /// /// 解析域名 /// /// /// private IPAddress? Resolve(string domain) { if (this.options.CurrentValue.Domains.Contains(domain) == false) { return default; } lock (this.syncRoot) { return this.contexts .Where(item => item.Domain == domain && item.AvailableRate > 0d) .OrderByDescending(item => item.AvailableRate) .ThenByDescending(item => item.Available) .ThenBy(item => item.AvgElapsed) .Select(item => item.Address) .FirstOrDefault(); } } } }