using Dlhis.Middle.Apis; using Dlhis.Middle.Entities; using Dlhis.Middle.Services; using Kurisu.AspNetCore.DataAccess.SqlSugar.Services; using Kurisu.AspNetCore.UnifyResultAndValidation; namespace Dlhis.Middle.BackgroundServices; public class BalanceRecordUploadBackgroundService : BackgroundService { private readonly IServiceProvider _serviceProvider; private readonly ILogger _logger; private readonly ISettingService _settingService; private readonly ICanteenApi _canteenApi; private readonly IHealthCheckService _healthCheckService; public BalanceRecordUploadBackgroundService(IServiceProvider serviceProvider, ILogger logger, ISettingService settingService, ICanteenApi canteenApi, IHealthCheckService healthCheckService) { _serviceProvider = serviceProvider; _logger = logger; _settingService = settingService; _canteenApi = canteenApi; _healthCheckService = healthCheckService; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { if (!_healthCheckService.GetIsOffline()) { var now = DateTime.Now; using var scope = _serviceProvider.CreateScope(); var db = scope.ServiceProvider.GetService(); var ds = scope.ServiceProvider.GetService(); var factories = _settingService.GetFactories(); foreach (var factory in factories) { try { var balanceRecords = await db.Queryable() .Where(x => x.TenantId == factory) .Where(x => !x.IsSync).ToListAsync(stoppingToken); if (balanceRecords.Any()) { _logger.LogInformation("上传离线订单"); foreach (var balanceRecord in balanceRecords) { //事务 await db.Client.Ado.BeginTranAsync(); try { var r = await _canteenApi.UploadAsync(balanceRecord); if (r.Code != ApiStateCode.Success) { throw new Exception(r.Msg); } var d = r.Data; //更新本地余额表 await db.Updateable() .SetColumns(x => x.Balance == d.Balance) .Where(x => x.UserCode == d.UserCode) .ExecuteCommandAsync(stoppingToken); //eg:一定要在此处更新为已同步 balanceRecord.IsSync = true; await db.UpdateAsync(balanceRecord); await db.Client.Ado.CommitTranAsync(); } catch (Exception e) { _logger.LogError(e, "{factory}上传离线消费失败:{message}", factory, e.Message); await db.Client.Ado.RollbackTranAsync(); } } balanceRecords = await db.Queryable().Where(x => x.TenantId == factory).Where(x => !x.IsSync).ToListAsync(stoppingToken); if (!balanceRecords.Any()) { _logger.LogInformation("{factory}上传离线订单完成", factory); } } else { _logger.LogInformation("{factory}无离线订单", factory); } } catch (Exception e) { _logger.LogError(e, "{factory}同步离线数据失败:{message}", factory, e.Message); } } try { if (now is { Hour: 5, Minute: 1 } && !_healthCheckService.GetIsOffline() && !await db.Queryable().Where(x => !x.IsSync).AnyAsync()) { await ds.InitAsync(factories); } } catch (Exception e) { _logger.LogError(e, "定时同步离线数据失败"); } } await Task.Delay(30 * 1000, stoppingToken); } } }