PersistenceService.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. using FastGithub.Configuration;
  2. using Microsoft.Extensions.Logging;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Net;
  8. using System.Text.Json;
  9. using System.Text.Json.Serialization;
  10. using System.Threading;
  11. using System.Threading.Tasks;
  12. namespace FastGithub.DomainResolve
  13. {
  14. /// <summary>
  15. /// 域名持久化
  16. /// </summary>
  17. sealed partial class PersistenceService
  18. {
  19. private static readonly string dataFile = "dnsendpoints.json";
  20. private static readonly SemaphoreSlim dataLocker = new(1, 1);
  21. private readonly FastGithubConfig fastGithubConfig;
  22. private readonly ILogger<PersistenceService> logger;
  23. private record EndPointItem(string Host, int Port);
  24. [JsonSerializable(typeof(EndPointItem[]))]
  25. [JsonSourceGenerationOptions(
  26. WriteIndented = true,
  27. PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
  28. private partial class EndPointItemsContext : JsonSerializerContext
  29. {
  30. }
  31. /// <summary>
  32. /// 域名持久化
  33. /// </summary>
  34. /// <param name="fastGithubConfig"></param>
  35. /// <param name="logger"></param>
  36. public PersistenceService(
  37. FastGithubConfig fastGithubConfig,
  38. ILogger<PersistenceService> logger)
  39. {
  40. this.fastGithubConfig = fastGithubConfig;
  41. this.logger = logger;
  42. }
  43. /// <summary>
  44. /// 读取保存的节点
  45. /// </summary>
  46. /// <returns></returns>
  47. public IList<DnsEndPoint> ReadDnsEndPoints()
  48. {
  49. if (File.Exists(dataFile) == false)
  50. {
  51. return Array.Empty<DnsEndPoint>();
  52. }
  53. try
  54. {
  55. dataLocker.Wait();
  56. var utf8Json = File.ReadAllBytes(dataFile);
  57. var endPointItems = JsonSerializer.Deserialize(utf8Json, EndPointItemsContext.Default.EndPointItemArray);
  58. if (endPointItems == null)
  59. {
  60. return Array.Empty<DnsEndPoint>();
  61. }
  62. var dnsEndPoints = new List<DnsEndPoint>();
  63. foreach (var item in endPointItems)
  64. {
  65. if (this.fastGithubConfig.IsMatch(item.Host) == true)
  66. {
  67. dnsEndPoints.Add(new DnsEndPoint(item.Host, item.Port));
  68. }
  69. }
  70. return dnsEndPoints;
  71. }
  72. catch (Exception ex)
  73. {
  74. this.logger.LogWarning(ex.Message, "读取dns记录异常");
  75. return Array.Empty<DnsEndPoint>();
  76. }
  77. finally
  78. {
  79. dataLocker.Release();
  80. }
  81. }
  82. /// <summary>
  83. /// 保存节点到文件
  84. /// </summary>
  85. /// <param name="dnsEndPoints"></param>
  86. /// <param name="cancellationToken"></param>
  87. /// <returns></returns>
  88. public async Task WriteDnsEndPointsAsync(IEnumerable<DnsEndPoint> dnsEndPoints, CancellationToken cancellationToken)
  89. {
  90. try
  91. {
  92. await dataLocker.WaitAsync(CancellationToken.None);
  93. var endPointItems = dnsEndPoints.Select(item => new EndPointItem(item.Host, item.Port)).ToArray();
  94. var utf8Json = JsonSerializer.SerializeToUtf8Bytes(endPointItems, EndPointItemsContext.Default.EndPointItemArray);
  95. await File.WriteAllBytesAsync(dataFile, utf8Json, cancellationToken);
  96. }
  97. catch (Exception ex)
  98. {
  99. this.logger.LogWarning(ex.Message, "保存dns记录异常");
  100. }
  101. finally
  102. {
  103. dataLocker.Release();
  104. }
  105. }
  106. }
  107. }