improvement: DeadTokenCleanupWorker Redis 캐시 무효화 연동 (#160)
- ITokenCacheService 주입, 배치 삭제 시 Redis 캐시 무효화 - SELECT → DELETE → 캐시 무효화 순서로 변경 - TASKS.md git 트래킹 해제 (.gitignore에 이미 등록됨) Closes #160
This commit is contained in:
parent
b1cac9d08a
commit
a6d9f2a46f
|
|
@ -2,6 +2,7 @@ using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using SPMS.Application.Interfaces;
|
||||||
using SPMS.Domain.Entities;
|
using SPMS.Domain.Entities;
|
||||||
using SPMS.Infrastructure.Persistence;
|
using SPMS.Infrastructure.Persistence;
|
||||||
|
|
||||||
|
|
@ -10,6 +11,7 @@ namespace SPMS.Infrastructure.Workers;
|
||||||
public class DeadTokenCleanupWorker : BackgroundService
|
public class DeadTokenCleanupWorker : BackgroundService
|
||||||
{
|
{
|
||||||
private readonly IServiceScopeFactory _scopeFactory;
|
private readonly IServiceScopeFactory _scopeFactory;
|
||||||
|
private readonly ITokenCacheService _tokenCache;
|
||||||
private readonly ILogger<DeadTokenCleanupWorker> _logger;
|
private readonly ILogger<DeadTokenCleanupWorker> _logger;
|
||||||
|
|
||||||
private static readonly TimeZoneInfo KstZone = TimeZoneInfo.FindSystemTimeZoneById("Asia/Seoul");
|
private static readonly TimeZoneInfo KstZone = TimeZoneInfo.FindSystemTimeZoneById("Asia/Seoul");
|
||||||
|
|
@ -18,9 +20,11 @@ public class DeadTokenCleanupWorker : BackgroundService
|
||||||
|
|
||||||
public DeadTokenCleanupWorker(
|
public DeadTokenCleanupWorker(
|
||||||
IServiceScopeFactory scopeFactory,
|
IServiceScopeFactory scopeFactory,
|
||||||
|
ITokenCacheService tokenCache,
|
||||||
ILogger<DeadTokenCleanupWorker> logger)
|
ILogger<DeadTokenCleanupWorker> logger)
|
||||||
{
|
{
|
||||||
_scopeFactory = scopeFactory;
|
_scopeFactory = scopeFactory;
|
||||||
|
_tokenCache = tokenCache;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -99,23 +103,38 @@ public class DeadTokenCleanupWorker : BackgroundService
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 배치 삭제 (1000건씩, 트랜잭션 없음)
|
// 배치 삭제 (1000건씩, 트랜잭션 없음) + Redis 캐시 무효화
|
||||||
var totalDeleted = 0;
|
var totalDeleted = 0;
|
||||||
int deletedInBatch;
|
|
||||||
|
|
||||||
do
|
while (!stoppingToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
deletedInBatch = await context.Database.ExecuteSqlRawAsync(
|
var batch = await context.Set<Device>()
|
||||||
"DELETE FROM Device WHERE is_active = false AND updated_at < {0} LIMIT 1000",
|
.Where(d => !d.IsActive && d.UpdatedAt < cutoffUtc)
|
||||||
new object[] { cutoffUtc },
|
.Select(d => new { d.Id, d.ServiceId })
|
||||||
|
.Take(BatchSize)
|
||||||
|
.ToListAsync(stoppingToken);
|
||||||
|
|
||||||
|
if (batch.Count == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
var ids = batch.Select(b => b.Id).ToList();
|
||||||
|
var idList = string.Join(",", ids);
|
||||||
|
|
||||||
|
#pragma warning disable EF1002 // ID는 내부 DB 쿼리에서 추출한 long 값 — SQL injection 위험 없음
|
||||||
|
var deletedInBatch = await context.Database.ExecuteSqlRawAsync(
|
||||||
|
$"DELETE FROM Device WHERE id IN ({idList})",
|
||||||
stoppingToken);
|
stoppingToken);
|
||||||
|
#pragma warning restore EF1002
|
||||||
|
|
||||||
totalDeleted += deletedInBatch;
|
totalDeleted += deletedInBatch;
|
||||||
|
|
||||||
if (deletedInBatch > 0)
|
// 삭제된 디바이스의 Redis 캐시 무효화
|
||||||
_logger.LogInformation("DeadTokenCleanupWorker 배치 삭제: {BatchCount}건 (누적: {TotalDeleted}건)",
|
foreach (var item in batch)
|
||||||
deletedInBatch, totalDeleted);
|
await _tokenCache.InvalidateAsync(item.ServiceId, item.Id);
|
||||||
} while (deletedInBatch > 0 && !stoppingToken.IsCancellationRequested);
|
|
||||||
|
_logger.LogInformation("DeadTokenCleanupWorker 배치 삭제: {BatchCount}건 (누적: {TotalDeleted}건), 캐시 무효화 완료",
|
||||||
|
deletedInBatch, totalDeleted);
|
||||||
|
}
|
||||||
|
|
||||||
await WriteSystemLogAsync(context, totalDeleted, stoppingToken);
|
await WriteSystemLogAsync(context, totalDeleted, stoppingToken);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user