TaobaoGeneralLinkParseCacheCore.cs 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. using dodohold.core;
  2. using System.Security.Cryptography;
  3. using System.Text;
  4. namespace molilian.core
  5. {
  6. public static class TaobaoGeneralLinkParseCacheCore
  7. {
  8. public const int CacheExpireSeconds = 7 * 86400;
  9. // 统计跨天保留,每次通知领取上次通知后的全部次数;同一天只允许领取一次。
  10. private const string ClaimNotificationScript = @"
  11. local count = redis.call('HINCRBY', KEYS[1], 'pending', 1)
  12. local lastDate = redis.call('HGET', KEYS[1], 'last_notify_date')
  13. if lastDate and lastDate >= ARGV[1] then
  14. return 0
  15. end
  16. redis.call('HSET', KEYS[1], 'last_notify_date', ARGV[1])
  17. redis.call('HSET', KEYS[1], 'pending', 0)
  18. return count";
  19. public static async Task<TaobaoGeneralLinkParseCacheDTO?> GetAsync(string content)
  20. {
  21. try
  22. {
  23. return await CenterHub.Redis.GetAsync<TaobaoGeneralLinkParseCacheDTO>(GetCacheKey(content));
  24. }
  25. catch (Exception ex)
  26. {
  27. LogFailure("cache_read_error", ex);
  28. return null;
  29. }
  30. }
  31. public static async Task SaveAsync(TaobaoGeneralLinkParseCacheDTO record)
  32. {
  33. try
  34. {
  35. await CenterHub.Redis.SetAsync(GetCacheKey(record.RequestContent), record, CacheExpireSeconds);
  36. }
  37. catch (Exception ex)
  38. {
  39. LogFailure("cache_write_error", ex);
  40. }
  41. }
  42. public static async Task NotifyFailureOnceAsync(string reason, int parseAccountId, int consumerAccountId)
  43. {
  44. reason = string.IsNullOrWhiteSpace(reason) ? "未知错误" : reason.Trim();
  45. string key = $"notify:taobao:general_link_parse:v1:{Hash(reason)}";
  46. long count = 0;
  47. try
  48. {
  49. count = Convert.ToInt64(await CenterHub.Redis.EvalAsync(ClaimNotificationScript, key, DateTime.Now.ToString("yyyyMMdd")));
  50. if (count <= 0) return;
  51. await NotifyCore.NotifyAsync(
  52. $"【淘宝万能解析失败】\n错误信息:{reason}\n" +
  53. $"自上次相同错误通知以来发生:{count} 次(含本次)\n" +
  54. $"使用账号:{consumerAccountId},解析账号:{parseAccountId}\n已回退原短链解析逻辑。");
  55. }
  56. catch (Exception ex)
  57. {
  58. if (count > 0)
  59. {
  60. try
  61. {
  62. // 发送失败的次数留给下一次通知,同一天不重复尝试发送。
  63. await CenterHub.Redis.HIncrByAsync(key, "pending", count);
  64. }
  65. catch (Exception restoreException)
  66. {
  67. LogFailure("notify_count_restore_error", restoreException);
  68. }
  69. }
  70. LogFailure("notify_error", ex);
  71. }
  72. }
  73. private static string GetCacheKey(string content)
  74. {
  75. return $"cache:taobao:general_link_parse:v1:{Hash(content.Trim())}";
  76. }
  77. private static string Hash(string value)
  78. {
  79. return Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(value)));
  80. }
  81. private static void LogFailure(string operation, Exception ex)
  82. {
  83. _ = new LoggerLibrary("tbk_dg_general_link_parse", operation)
  84. .Info(ex.Message, ex.StackTrace)
  85. .SaveAsync();
  86. }
  87. }
  88. }