FastGithub/FastGithub.Scanner/GithubScanResults.cs
2021-07-15 09:54:59 +08:00

101 lines
2.9 KiB
C#

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
{
/// <summary>
/// GithubContext集合
/// </summary>
[Service(ServiceLifetime.Singleton)]
sealed class GithubScanResults : IGithubScanResults
{
private readonly object syncRoot = new();
private readonly List<GithubContext> contexts = new();
private readonly IMemoryCache memoryCache;
private readonly IOptionsMonitor<GithubLookupFactoryOptions> options;
public GithubScanResults(
IMemoryCache memoryCache,
IOptionsMonitor<GithubLookupFactoryOptions> options)
{
this.memoryCache = memoryCache;
this.options = options;
}
/// <summary>
/// 添加GithubContext
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public bool Add(GithubContext context)
{
lock (this.syncRoot)
{
if (this.contexts.Contains(context))
{
return false;
}
this.contexts.Add(context);
return true;
}
}
/// <summary>
/// 转换为数组
/// </summary>
/// <returns></returns>
public GithubContext[] ToArray()
{
lock (this.syncRoot)
{
return this.contexts.ToArray();
}
}
/// <summary>
/// 查找最优的ip
/// </summary>
/// <param name="domain"></param>
/// <returns></returns>
public IPAddress? FindBestAddress(string domain)
{
var key = $"domain:{domain}";
return this.memoryCache.GetOrCreate(key, e =>
{
e.SetAbsoluteExpiration(TimeSpan.FromSeconds(1d));
return this.Resolve(domain);
});
}
/// <summary>
/// 解析域名
/// </summary>
/// <param name="domain"></param>
/// <returns></returns>
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();
}
}
}
}