fix: 修复发货重试后台服务不执行的问题
- 使用 IServiceScopeFactory 解决 scoped 服务依赖问题 - IWechatService 是 scoped 服务,不能直接注入到 singleton 后台服务 - 每次处理订单时创建新的 scope 来解析 IWechatService - 将检查间隔从 60 秒改为 30 秒 - 优化 RedisService.GetKeysAsync 使用实时连接状态检查
This commit is contained in:
parent
d4c15c8feb
commit
8991118f8d
|
|
@ -1,6 +1,7 @@
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using HoneyBox.Core.Interfaces;
|
using HoneyBox.Core.Interfaces;
|
||||||
using HoneyBox.Model.Models.Auth;
|
using HoneyBox.Model.Models.Auth;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
|
@ -12,22 +13,22 @@ namespace HoneyBox.Core.Services;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ShippingRetryBackgroundService : BackgroundService
|
public class ShippingRetryBackgroundService : BackgroundService
|
||||||
{
|
{
|
||||||
|
private readonly IServiceScopeFactory _scopeFactory;
|
||||||
private readonly IRedisService _redisService;
|
private readonly IRedisService _redisService;
|
||||||
private readonly IWechatService _wechatService;
|
|
||||||
private readonly ILogger<ShippingRetryBackgroundService> _logger;
|
private readonly ILogger<ShippingRetryBackgroundService> _logger;
|
||||||
|
|
||||||
private const int MaxRetryCount = 10; // 最大重试次数
|
private const int MaxRetryCount = 10; // 最大重试次数
|
||||||
private const int RetryIntervalSeconds = 30; // 重试间隔(秒)
|
private const int RetryIntervalSeconds = 30; // 重试间隔(秒)
|
||||||
private const int CheckIntervalSeconds = 60; // 检查间隔(秒)
|
private const int CheckIntervalSeconds = 30; // 检查间隔(秒)
|
||||||
private const string RetryKeyPattern = "post_order:*";
|
private const string RetryKeyPattern = "post_order:*";
|
||||||
|
|
||||||
public ShippingRetryBackgroundService(
|
public ShippingRetryBackgroundService(
|
||||||
|
IServiceScopeFactory scopeFactory,
|
||||||
IRedisService redisService,
|
IRedisService redisService,
|
||||||
IWechatService wechatService,
|
|
||||||
ILogger<ShippingRetryBackgroundService> logger)
|
ILogger<ShippingRetryBackgroundService> logger)
|
||||||
{
|
{
|
||||||
|
_scopeFactory = scopeFactory;
|
||||||
_redisService = redisService;
|
_redisService = redisService;
|
||||||
_wechatService = wechatService;
|
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,20 +36,33 @@ public class ShippingRetryBackgroundService : BackgroundService
|
||||||
{
|
{
|
||||||
_logger.LogInformation("发货重试后台服务已启动");
|
_logger.LogInformation("发货重试后台服务已启动");
|
||||||
|
|
||||||
|
// 启动时等待一小段时间,让其他服务初始化完成
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
|
||||||
|
|
||||||
while (!stoppingToken.IsCancellationRequested)
|
while (!stoppingToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await ProcessFailedShippingOrdersAsync(stoppingToken);
|
await ProcessFailedShippingOrdersAsync(stoppingToken);
|
||||||
}
|
}
|
||||||
|
catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "处理发货重试时发生异常");
|
_logger.LogError(ex, "处理发货重试时发生异常");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 等待下一次检查
|
try
|
||||||
|
{
|
||||||
await Task.Delay(TimeSpan.FromSeconds(CheckIntervalSeconds), stoppingToken);
|
await Task.Delay(TimeSpan.FromSeconds(CheckIntervalSeconds), stoppingToken);
|
||||||
}
|
}
|
||||||
|
catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_logger.LogInformation("发货重试后台服务已停止");
|
_logger.LogInformation("发货重试后台服务已停止");
|
||||||
}
|
}
|
||||||
|
|
@ -63,11 +77,12 @@ public class ShippingRetryBackgroundService : BackgroundService
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogDebug("发现 {Count} 个待重试的发货订单", failedOrderKeys.Count());
|
var keysList = failedOrderKeys.ToList();
|
||||||
|
_logger.LogInformation("发现 {Count} 个待重试的发货订单", keysList.Count);
|
||||||
|
|
||||||
var nowTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
var nowTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||||
|
|
||||||
foreach (var key in failedOrderKeys)
|
foreach (var key in keysList)
|
||||||
{
|
{
|
||||||
if (stoppingToken.IsCancellationRequested)
|
if (stoppingToken.IsCancellationRequested)
|
||||||
break;
|
break;
|
||||||
|
|
@ -83,6 +98,7 @@ public class ShippingRetryBackgroundService : BackgroundService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private async Task ProcessSingleOrderAsync(string key, long nowTime)
|
private async Task ProcessSingleOrderAsync(string key, long nowTime)
|
||||||
{
|
{
|
||||||
// 获取订单数据
|
// 获取订单数据
|
||||||
|
|
@ -125,17 +141,20 @@ public class ShippingRetryBackgroundService : BackgroundService
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 尝试重新发货
|
// 尝试重新发货 - 使用新的 scope 来解析 IWechatService
|
||||||
_logger.LogInformation("开始重试发货: OrderNo={OrderNo}, RetryCount={RetryCount}",
|
_logger.LogInformation("开始重试发货: OrderNo={OrderNo}, RetryCount={RetryCount}",
|
||||||
orderData.order_num, orderData.retry_count + 1);
|
orderData.order_num, orderData.retry_count + 1);
|
||||||
|
|
||||||
|
using var scope = _scopeFactory.CreateScope();
|
||||||
|
var wechatService = scope.ServiceProvider.GetRequiredService<IWechatService>();
|
||||||
|
|
||||||
var request = new WechatShippingRequest
|
var request = new WechatShippingRequest
|
||||||
{
|
{
|
||||||
OpenId = orderData.openid,
|
OpenId = orderData.openid,
|
||||||
OrderNo = orderData.order_num
|
OrderNo = orderData.order_num
|
||||||
};
|
};
|
||||||
|
|
||||||
var result = await _wechatService.UploadShippingInfoAsync(request);
|
var result = await wechatService.UploadShippingInfoAsync(request);
|
||||||
|
|
||||||
if (result.Success)
|
if (result.Success)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,11 @@ public class RedisService : IRedisService, IDisposable
|
||||||
|
|
||||||
public async Task<IEnumerable<string>> GetKeysAsync(string pattern)
|
public async Task<IEnumerable<string>> GetKeysAsync(string pattern)
|
||||||
{
|
{
|
||||||
if (_connection == null || !_isConnected)
|
if (_connection == null)
|
||||||
|
return Enumerable.Empty<string>();
|
||||||
|
|
||||||
|
// 检查当前连接状态(而不是构造时的状态)
|
||||||
|
if (!_connection.IsConnected)
|
||||||
return Enumerable.Empty<string>();
|
return Enumerable.Empty<string>();
|
||||||
|
|
||||||
var keys = new List<string>();
|
var keys = new List<string>();
|
||||||
|
|
@ -116,6 +120,9 @@ public class RedisService : IRedisService, IDisposable
|
||||||
foreach (var endpoint in endpoints)
|
foreach (var endpoint in endpoints)
|
||||||
{
|
{
|
||||||
var server = _connection.GetServer(endpoint);
|
var server = _connection.GetServer(endpoint);
|
||||||
|
if (server == null || !server.IsConnected)
|
||||||
|
continue;
|
||||||
|
|
||||||
await foreach (var key in server.KeysAsync(pattern: pattern))
|
await foreach (var key in server.KeysAsync(pattern: pattern))
|
||||||
{
|
{
|
||||||
keys.Add(key.ToString());
|
keys.Add(key.ToString());
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user