GithubScanResults.cs 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. using Microsoft.Extensions.DependencyInjection;
  2. using Microsoft.Extensions.Options;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Net;
  6. namespace FastGithub.Scanner
  7. {
  8. /// <summary>
  9. /// GithubContext集合
  10. /// </summary>
  11. [Service(ServiceLifetime.Singleton)]
  12. sealed class GithubScanResults : IGithubScanResults
  13. {
  14. private readonly object syncRoot = new();
  15. private readonly List<GithubContext> contexts = new();
  16. private readonly IOptionsMonitor<GithubLookupFactoryOptions> options;
  17. public GithubScanResults(IOptionsMonitor<GithubLookupFactoryOptions> options)
  18. {
  19. this.options = options;
  20. }
  21. /// <summary>
  22. /// 添加GithubContext
  23. /// </summary>
  24. /// <param name="context"></param>
  25. /// <returns></returns>
  26. public bool Add(GithubContext context)
  27. {
  28. lock (this.syncRoot)
  29. {
  30. if (this.contexts.Contains(context))
  31. {
  32. return false;
  33. }
  34. this.contexts.Add(context);
  35. return true;
  36. }
  37. }
  38. /// <summary>
  39. /// 转换为数组
  40. /// </summary>
  41. /// <returns></returns>
  42. public GithubContext[] ToArray()
  43. {
  44. lock (this.syncRoot)
  45. {
  46. return this.contexts.ToArray();
  47. }
  48. }
  49. /// <summary>
  50. /// 是否支持指定域名
  51. /// </summary>
  52. /// <param name="domain"></param>
  53. /// <returns></returns>
  54. public bool Support(string domain)
  55. {
  56. return this.options.CurrentValue.Domains.Contains(domain);
  57. }
  58. /// <summary>
  59. /// 查找最优的ip
  60. /// </summary>
  61. /// <param name="domain"></param>
  62. /// <returns></returns>
  63. public IPAddress? FindBestAddress(string domain)
  64. {
  65. if (this.Support(domain) == false)
  66. {
  67. return default;
  68. }
  69. lock (this.syncRoot)
  70. {
  71. return this.contexts
  72. .Where(item => item.Domain == domain && item.AvailableRate > 0d)
  73. .OrderByDescending(item => item.AvailableRate)
  74. .ThenByDescending(item => item.Available)
  75. .ThenBy(item => item.AvgElapsed)
  76. .Select(item => item.Address)
  77. .FirstOrDefault();
  78. }
  79. }
  80. }
  81. }