fix: 统一逐租户上下文执行
This commit is contained in:
@@ -5,6 +5,7 @@ using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using TakeoutSaaS.Domain.Tenants.Enums;
|
||||
using TakeoutSaaS.Infrastructure.App.Persistence;
|
||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||
|
||||
namespace TakeoutSaaS.Infrastructure.BackgroundServices;
|
||||
|
||||
@@ -67,45 +68,70 @@ public sealed class SubscriptionExpiryCheckService : BackgroundService
|
||||
|
||||
using var scope = _serviceProvider.CreateScope();
|
||||
var dbContext = scope.ServiceProvider.GetRequiredService<TakeoutAppDbContext>();
|
||||
var tenantContextAccessor = scope.ServiceProvider.GetRequiredService<ITenantContextAccessor>();
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
var gracePeriodDays = _options.GracePeriodDays;
|
||||
|
||||
try
|
||||
{
|
||||
// 1. 检查活跃订阅中已到期的,转为宽限期
|
||||
var expiredActive = await dbContext.TenantSubscriptions
|
||||
.Where(s => s.Status == SubscriptionStatus.Active && s.EffectiveTo < now)
|
||||
var tenants = await dbContext.Tenants
|
||||
.AsNoTracking()
|
||||
.Where(x => x.DeletedAt == null && x.Id > 0)
|
||||
.Select(x => new { x.Id, x.Code })
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
foreach (var subscription in expiredActive)
|
||||
if (tenants.Count == 0)
|
||||
{
|
||||
subscription.Status = SubscriptionStatus.GracePeriod;
|
||||
_logger.LogInformation(
|
||||
"订阅 {SubscriptionId} (租户 {TenantId}) 已到期,进入宽限期",
|
||||
subscription.Id, subscription.TenantId);
|
||||
_logger.LogInformation("订阅到期检查完成:未找到可处理租户");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 检查宽限期订阅中超过宽限期的,转为暂停
|
||||
var gracePeriodExpired = await dbContext.TenantSubscriptions
|
||||
.Where(s => s.Status == SubscriptionStatus.GracePeriod
|
||||
&& s.EffectiveTo.AddDays(gracePeriodDays) < now)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
foreach (var subscription in gracePeriodExpired)
|
||||
var changedTotal = 0;
|
||||
var expiredTotal = 0;
|
||||
var suspendedTotal = 0;
|
||||
foreach (var tenant in tenants)
|
||||
{
|
||||
subscription.Status = SubscriptionStatus.Suspended;
|
||||
_logger.LogInformation(
|
||||
"订阅 {SubscriptionId} (租户 {TenantId}) 宽限期已结束,已暂停",
|
||||
subscription.Id, subscription.TenantId);
|
||||
}
|
||||
using (tenantContextAccessor.EnterTenantScope(tenant.Id, "background:subscription-expiry", tenant.Code))
|
||||
{
|
||||
// 1. 检查活跃订阅中已到期的,转为宽限期
|
||||
var expiredActive = await dbContext.TenantSubscriptions
|
||||
.Where(s => s.Status == SubscriptionStatus.Active && s.EffectiveTo < now)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
// 3. 保存更改
|
||||
var changedCount = await dbContext.SaveChangesAsync(cancellationToken);
|
||||
foreach (var subscription in expiredActive)
|
||||
{
|
||||
subscription.Status = SubscriptionStatus.GracePeriod;
|
||||
_logger.LogInformation(
|
||||
"订阅 {SubscriptionId} (租户 {TenantId}) 已到期,进入宽限期",
|
||||
subscription.Id, subscription.TenantId);
|
||||
}
|
||||
|
||||
// 2. 检查宽限期订阅中超过宽限期的,转为暂停
|
||||
var gracePeriodExpired = await dbContext.TenantSubscriptions
|
||||
.Where(s => s.Status == SubscriptionStatus.GracePeriod
|
||||
&& s.EffectiveTo.AddDays(gracePeriodDays) < now)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
||||
foreach (var subscription in gracePeriodExpired)
|
||||
{
|
||||
subscription.Status = SubscriptionStatus.Suspended;
|
||||
_logger.LogInformation(
|
||||
"订阅 {SubscriptionId} (租户 {TenantId}) 宽限期已结束,已暂停",
|
||||
subscription.Id, subscription.TenantId);
|
||||
}
|
||||
|
||||
// 3. 保存更改(逐租户保存,避免跨租户写入)
|
||||
var changedCount = await dbContext.SaveChangesAsync(cancellationToken);
|
||||
|
||||
changedTotal += changedCount;
|
||||
expiredTotal += expiredActive.Count;
|
||||
suspendedTotal += gracePeriodExpired.Count;
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogInformation(
|
||||
"订阅到期检查完成,共更新 {Count} 条记录 (到期转宽限期: {ExpiredCount}, 宽限期转暂停: {SuspendedCount})",
|
||||
changedCount, expiredActive.Count, gracePeriodExpired.Count);
|
||||
changedTotal, expiredTotal, suspendedTotal);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user