重构GithubContext
This commit is contained in:
parent
b486f551cf
commit
922d47fdab
@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
|
||||
@ -10,9 +12,21 @@ namespace FastGithub.Scanner
|
||||
sealed class GithubContext : DomainAddress, IEquatable<GithubContext>
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取或设置是否可用
|
||||
/// 最多保存最的近的10条记录
|
||||
/// </summary>
|
||||
public bool Available { get; set; }
|
||||
private const int MAX_LOG_COUNT = 10;
|
||||
|
||||
/// <summary>
|
||||
/// 扫描记录
|
||||
/// </summary>
|
||||
private record ScanLog(bool Available, TimeSpan Elapsed);
|
||||
|
||||
/// <summary>
|
||||
/// 扫描历史记录
|
||||
/// </summary>
|
||||
private readonly Queue<ScanLog> history = new();
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 设置取消令牌
|
||||
@ -20,9 +34,21 @@ namespace FastGithub.Scanner
|
||||
public CancellationToken CancellationToken { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取扫描历史信息
|
||||
/// 获取可用率
|
||||
/// </summary>
|
||||
public GithubContextHistory History { get; } = new();
|
||||
/// <returns></returns>
|
||||
public double AvailableRate => this.GetAvailableRate();
|
||||
|
||||
/// <summary>
|
||||
/// 获取平均耗时
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public TimeSpan AvgElapsed => this.GetAvgElapsed();
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置是否可用
|
||||
/// </summary>
|
||||
public bool Available { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
@ -47,19 +73,74 @@ namespace FastGithub.Scanner
|
||||
this.CancellationToken = cancellationToken;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取可用率
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private double GetAvailableRate()
|
||||
{
|
||||
if (this.history.Count == 0)
|
||||
{
|
||||
return 0d;
|
||||
}
|
||||
|
||||
var availableCount = this.history.Count(item => item.Available);
|
||||
return (double)availableCount / this.history.Count;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取平均耗时
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private TimeSpan GetAvgElapsed()
|
||||
{
|
||||
var availableCount = 0;
|
||||
var availableElapsed = TimeSpan.Zero;
|
||||
|
||||
foreach (var item in this.history)
|
||||
{
|
||||
if (item.Available == true)
|
||||
{
|
||||
availableCount += 1;
|
||||
availableElapsed = availableElapsed.Add(item.Elapsed);
|
||||
}
|
||||
}
|
||||
return availableCount == 0 ? TimeSpan.MaxValue : availableElapsed / availableCount;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 添加扫描记录
|
||||
/// </summary>
|
||||
/// <param name="elapsed">扫描耗时</param>
|
||||
public void AddScanLog(TimeSpan elapsed)
|
||||
{
|
||||
var log = new ScanLog(this.Available, elapsed);
|
||||
this.history.Enqueue(log);
|
||||
while (this.history.Count > MAX_LOG_COUNT)
|
||||
{
|
||||
this.history.Dequeue();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否相等
|
||||
/// </summary>
|
||||
/// <param name="other"></param>
|
||||
/// <returns></returns>
|
||||
public bool Equals(GithubContext? other)
|
||||
{
|
||||
return base.Equals(other);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 转换为为统计信息
|
||||
/// 转换为统计信息
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string ToStatisticsString()
|
||||
{
|
||||
var rate = Math.Round(this.History.AvailableRate * 100, 2);
|
||||
return $"{{Address={this.Address}, AvailableRate={rate}%, AvgElapsed={this.History.AvgElapsed.TotalSeconds}s}}";
|
||||
var availableRate = Math.Round(this.AvailableRate * 100, 2);
|
||||
return $"{{{nameof(Address)}={this.Address}, {nameof(AvailableRate)}={availableRate}%, {nameof(AvgElapsed)}={this.AvgElapsed.TotalSeconds}s}}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,77 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace FastGithub.Scanner
|
||||
{
|
||||
/// <summary>
|
||||
/// GithubContext的扫描历史
|
||||
/// </summary>
|
||||
sealed class GithubContextHistory
|
||||
{
|
||||
/// <summary>
|
||||
/// 最多保存最的近的10条记录
|
||||
/// </summary>
|
||||
private const int MAX_LOG_COUNT = 10;
|
||||
private record ScanLog(bool Available, TimeSpan Elapsed);
|
||||
|
||||
private readonly Queue<ScanLog> scanLogs = new();
|
||||
|
||||
/// <summary>
|
||||
/// 获取可用率
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public double AvailableRate
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.scanLogs.Count == 0)
|
||||
{
|
||||
return 0d;
|
||||
}
|
||||
|
||||
var availableCount = this.scanLogs.Count(item => item.Available);
|
||||
return (double)availableCount / this.scanLogs.Count;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取平均耗时
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public TimeSpan AvgElapsed
|
||||
{
|
||||
get
|
||||
{
|
||||
var availableCount = 0;
|
||||
var availableElapsed = TimeSpan.Zero;
|
||||
|
||||
foreach (var item in this.scanLogs)
|
||||
{
|
||||
if (item.Available == true)
|
||||
{
|
||||
availableCount += 1;
|
||||
availableElapsed = availableElapsed.Add(item.Elapsed);
|
||||
}
|
||||
}
|
||||
|
||||
return availableCount == 0 ? TimeSpan.MaxValue : availableElapsed / availableCount;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加记录
|
||||
/// </summary>
|
||||
/// <param name="available">是否可用</param>
|
||||
/// <param name="elapsed">扫描耗时</param>
|
||||
public void Add(bool available, TimeSpan elapsed)
|
||||
{
|
||||
this.scanLogs.Enqueue(new ScanLog(available, elapsed));
|
||||
while (this.scanLogs.Count > MAX_LOG_COUNT)
|
||||
{
|
||||
this.scanLogs.Dequeue();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -13,12 +13,12 @@ namespace FastGithub.Scanner
|
||||
[Service(ServiceLifetime.Transient)]
|
||||
sealed class GithubDnsHttpHandler : DelegatingHandler
|
||||
{
|
||||
private readonly GithubContextCollection scanResults;
|
||||
private readonly GithubScanResults scanResults;
|
||||
|
||||
/// <summary>
|
||||
/// Github的dns解析的httpHandler
|
||||
/// </summary>
|
||||
public GithubDnsHttpHandler(GithubContextCollection scanResults)
|
||||
public GithubDnsHttpHandler(GithubScanResults scanResults)
|
||||
{
|
||||
this.scanResults = scanResults;
|
||||
}
|
||||
|
||||
@ -9,10 +9,10 @@ namespace FastGithub.Scanner
|
||||
/// GithubContext集合
|
||||
/// </summary>
|
||||
[Service(ServiceLifetime.Singleton)]
|
||||
sealed class GithubContextCollection : IGithubScanResults
|
||||
sealed class GithubScanResults : IGithubScanResults
|
||||
{
|
||||
private readonly object syncRoot = new();
|
||||
private readonly List<GithubContext> contextList = new();
|
||||
private readonly List<GithubContext> contexts = new();
|
||||
|
||||
/// <summary>
|
||||
/// 添加GithubContext
|
||||
@ -23,11 +23,11 @@ namespace FastGithub.Scanner
|
||||
{
|
||||
lock (this.syncRoot)
|
||||
{
|
||||
if (this.contextList.Contains(context))
|
||||
if (this.contexts.Contains(context))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
this.contextList.Add(context);
|
||||
this.contexts.Add(context);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -40,23 +40,7 @@ namespace FastGithub.Scanner
|
||||
{
|
||||
lock (this.syncRoot)
|
||||
{
|
||||
return this.contextList.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询ip是否可用
|
||||
/// </summary>
|
||||
/// <param name="domain"></param>
|
||||
/// <param name="address"></param>
|
||||
/// <returns></returns>
|
||||
public bool IsAvailable(string domain, IPAddress address)
|
||||
{
|
||||
lock (this.syncRoot)
|
||||
{
|
||||
var target = new GithubContext(domain, address);
|
||||
var context = this.contextList.Find(item => item.Equals(target));
|
||||
return context != null && context.Available;
|
||||
return this.contexts.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,11 +53,11 @@ namespace FastGithub.Scanner
|
||||
{
|
||||
lock (this.syncRoot)
|
||||
{
|
||||
return this.contextList
|
||||
.Where(item => item.Domain == domain && item.History.AvailableRate > 0d)
|
||||
.OrderByDescending(item => item.History.AvailableRate)
|
||||
return this.contexts
|
||||
.Where(item => item.Domain == domain && item.AvailableRate > 0d)
|
||||
.OrderByDescending(item => item.AvailableRate)
|
||||
.ThenByDescending(item => item.Available)
|
||||
.ThenBy(item => item.History.AvgElapsed)
|
||||
.ThenBy(item => item.AvgElapsed)
|
||||
.Select(item => item.Address)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
@ -15,7 +15,7 @@ namespace FastGithub.Scanner
|
||||
sealed class GithubScanService
|
||||
{
|
||||
private readonly GithubLookupFacotry lookupFactory;
|
||||
private readonly GithubContextCollection scanResults;
|
||||
private readonly GithubScanResults scanResults;
|
||||
private readonly ILoggerFactory loggerFactory;
|
||||
private readonly ILogger<GithubScanService> logger;
|
||||
|
||||
@ -31,7 +31,7 @@ namespace FastGithub.Scanner
|
||||
/// <param name="logger"></param>
|
||||
public GithubScanService(
|
||||
GithubLookupFacotry lookupFactory,
|
||||
GithubContextCollection scanResults,
|
||||
GithubScanResults scanResults,
|
||||
IServiceProvider appService,
|
||||
ILoggerFactory loggerFactory,
|
||||
ILogger<GithubScanService> logger)
|
||||
@ -94,8 +94,8 @@ namespace FastGithub.Scanner
|
||||
var results = this.scanResults.ToArray();
|
||||
var contexts = results
|
||||
.OrderBy(item => item.Domain)
|
||||
.ThenByDescending(item => item.History.AvailableRate)
|
||||
.ThenBy(item => item.History.AvgElapsed);
|
||||
.ThenByDescending(item => item.AvailableRate)
|
||||
.ThenBy(item => item.AvgElapsed);
|
||||
|
||||
foreach (var context in contexts)
|
||||
{
|
||||
|
||||
@ -7,14 +7,6 @@ namespace FastGithub.Scanner
|
||||
/// </summary>
|
||||
public interface IGithubScanResults
|
||||
{
|
||||
/// <summary>
|
||||
/// 查询ip是否可用
|
||||
/// </summary>
|
||||
/// <param name="domain"></param>
|
||||
/// <param name="address"></param>
|
||||
/// <returns></returns>
|
||||
bool IsAvailable(string domain, IPAddress address);
|
||||
|
||||
/// <summary>
|
||||
/// 查找最优的ip
|
||||
/// </summary>
|
||||
|
||||
@ -31,7 +31,7 @@ namespace FastGithub.Scanner.ScanMiddlewares
|
||||
stopwatch.Stop();
|
||||
}
|
||||
|
||||
context.History.Add(context.Available, stopwatch.Elapsed);
|
||||
context.AddScanLog(stopwatch.Elapsed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@ namespace FastGithub
|
||||
.AddServiceAndOptions(assembly, configuration)
|
||||
.AddHostedService<GithubFullScanHostedService>()
|
||||
.AddHostedService<GithubResultScanHostedService>()
|
||||
.AddSingleton<IGithubScanResults>(appService => appService.GetRequiredService<GithubContextCollection>());
|
||||
.AddSingleton<IGithubScanResults>(appService => appService.GetRequiredService<GithubScanResults>());
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user