fix: 修复发货重试后台服务不执行的问题

- 使用 IServiceScopeFactory 解决 scoped 服务依赖问题
- IWechatService 是 scoped 服务,不能直接注入到 singleton 后台服务
- 每次处理订单时创建新的 scope 来解析 IWechatService
- 将检查间隔从 60 秒改为 30 秒
- 优化 RedisService.GetKeysAsync 使用实时连接状态检查
This commit is contained in:
zpc 2026-02-10 17:22:38 +08:00
parent d4c15c8feb
commit 8991118f8d
2 changed files with 37 additions and 11 deletions

View File

@ -1,6 +1,7 @@
using System.Text.Json;
using HoneyBox.Core.Interfaces;
using HoneyBox.Model.Models.Auth;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
@ -12,22 +13,22 @@ namespace HoneyBox.Core.Services;
/// </summary>
public class ShippingRetryBackgroundService : BackgroundService
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly IRedisService _redisService;
private readonly IWechatService _wechatService;
private readonly ILogger<ShippingRetryBackgroundService> _logger;
private const int MaxRetryCount = 10; // 最大重试次数
private const int RetryIntervalSeconds = 30; // 重试间隔(秒)
private const int CheckIntervalSeconds = 60; // 检查间隔(秒)
private const int CheckIntervalSeconds = 30; // 检查间隔(秒)
private const string RetryKeyPattern = "post_order:*";
public ShippingRetryBackgroundService(
IServiceScopeFactory scopeFactory,
IRedisService redisService,
IWechatService wechatService,
ILogger<ShippingRetryBackgroundService> logger)
{
_scopeFactory = scopeFactory;
_redisService = redisService;
_wechatService = wechatService;
_logger = logger;
}
@ -35,20 +36,33 @@ public class ShippingRetryBackgroundService : BackgroundService
{
_logger.LogInformation("发货重试后台服务已启动");
// 启动时等待一小段时间,让其他服务初始化完成
await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
while (!stoppingToken.IsCancellationRequested)
{
try
{
await ProcessFailedShippingOrdersAsync(stoppingToken);
}
catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
{
break;
}
catch (Exception ex)
{
_logger.LogError(ex, "处理发货重试时发生异常");
}
// 等待下一次检查
try
{
await Task.Delay(TimeSpan.FromSeconds(CheckIntervalSeconds), stoppingToken);
}
catch (OperationCanceledException) when (stoppingToken.IsCancellationRequested)
{
break;
}
}
_logger.LogInformation("发货重试后台服务已停止");
}
@ -63,11 +77,12 @@ public class ShippingRetryBackgroundService : BackgroundService
return;
}
_logger.LogDebug("发现 {Count} 个待重试的发货订单", failedOrderKeys.Count());
var keysList = failedOrderKeys.ToList();
_logger.LogInformation("发现 {Count} 个待重试的发货订单", keysList.Count);
var nowTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
foreach (var key in failedOrderKeys)
foreach (var key in keysList)
{
if (stoppingToken.IsCancellationRequested)
break;
@ -83,6 +98,7 @@ public class ShippingRetryBackgroundService : BackgroundService
}
}
private async Task ProcessSingleOrderAsync(string key, long nowTime)
{
// 获取订单数据
@ -125,17 +141,20 @@ public class ShippingRetryBackgroundService : BackgroundService
return;
}
// 尝试重新发货
// 尝试重新发货 - 使用新的 scope 来解析 IWechatService
_logger.LogInformation("开始重试发货: OrderNo={OrderNo}, RetryCount={RetryCount}",
orderData.order_num, orderData.retry_count + 1);
using var scope = _scopeFactory.CreateScope();
var wechatService = scope.ServiceProvider.GetRequiredService<IWechatService>();
var request = new WechatShippingRequest
{
OpenId = orderData.openid,
OrderNo = orderData.order_num
};
var result = await _wechatService.UploadShippingInfoAsync(request);
var result = await wechatService.UploadShippingInfoAsync(request);
if (result.Success)
{

View File

@ -107,7 +107,11 @@ public class RedisService : IRedisService, IDisposable
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>();
var keys = new List<string>();
@ -116,6 +120,9 @@ public class RedisService : IRedisService, IDisposable
foreach (var endpoint in endpoints)
{
var server = _connection.GetServer(endpoint);
if (server == null || !server.IsConnected)
continue;
await foreach (var key in server.KeysAsync(pattern: pattern))
{
keys.Add(key.ToString());