Files
ExperionCrawler/fastTable/step10.md

4.0 KiB

STEP 10 — 정리 서비스 (ExperionFastCleanupService.cs) 신규 생성

사전 확인 (작업 전 반드시 수행)

  1. src/Infrastructure/OpcUa/ 디렉토리 목록을 확인한다.
  2. 아래 항목을 확인하고 기록한다:
    • STEP 6이 완료되어 GetExpiredFastSessionsAsync, DeleteFastSessionAsync 구현이 있는가?
    • ExperionFastCleanupService.cs 파일이 이미 존재하는가? → 있으면 내용 비교 후 누락 부분만 수정
    • IExperionDbService 인터페이스에 위 두 메서드가 선언되어 있는가?

작업 내용

파일: src/Infrastructure/OpcUa/ExperionFastCleanupService.cs (신규 생성)

using ExperionCrawler.Core.Application.Interfaces;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace ExperionCrawler.Infrastructure.OpcUa;

/// <summary>
/// fastSession 만료 데이터 정리 서비스.
/// 매일 03:00 UTC에 실행.
/// pinned = true 세션은 제외.
/// retention_days가 null인 세션은 무한 보관.
/// </summary>
public class ExperionFastCleanupService : BackgroundService
{
    private readonly IServiceProvider                    _sp;
    private readonly ILogger<ExperionFastCleanupService> _logger;

    public ExperionFastCleanupService(
        IServiceProvider sp,
        ILogger<ExperionFastCleanupService> logger)
    {
        _sp     = sp;
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                // 매일 03:00 UTC까지 대기
                var now     = DateTime.UtcNow;
                var nextRun = new DateTime(now.Year, now.Month, now.Day, 3, 0, 0, DateTimeKind.Utc);
                if (now >= nextRun) nextRun = nextRun.AddDays(1);

                var delay = nextRun - now;
                _logger.LogInformation("[FastCleanup] 다음 정리 예약: {NextRun} (대기 {Delay})", nextRun, delay);

                await Task.Delay(delay, stoppingToken);

                // 만료 세션 조회 및 삭제
                using var scope   = _sp.CreateScope();
                var db            = scope.ServiceProvider.GetRequiredService<IExperionDbService>();
                var expiredList   = (await db.GetExpiredFastSessionsAsync()).ToList();

                foreach (var s in expiredList)
                {
                    _logger.LogInformation("[FastCleanup] 세션 {Id} ({Name}) 삭제 — 만료됨", s.Id, s.Name);
                    await db.DeleteFastSessionAsync(s.Id);
                }

                _logger.LogInformation("[FastCleanup] 정리 완료 — {Count}개 세션 삭제", expiredList.Count);
            }
            catch (OperationCanceledException)
            {
                // 정상 종료
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "[FastCleanup] 오류 발생");
                // 오류 시 1시간 후 재시도
                await Task.Delay(TimeSpan.FromHours(1), stoppingToken);
            }
        }
    }
}

사후 확인 (작업 후 반드시 수행)

  1. ExperionFastCleanupService.cs 파일을 열어 전체 내용을 읽는다.
  2. 아래 항목을 하나씩 확인한다:
    • BackgroundService를 상속하는가?
    • ExecuteAsync 메서드가 있는가?
    • 매일 03:00 UTC 스케줄링 로직이 있는가?
    • GetExpiredFastSessionsAsync() 호출이 있는가?
    • 각 만료 세션에 대해 DeleteFastSessionAsync 호출이 있는가?
    • OperationCanceledException catch가 있는가? (정상 종료 처리)
    • 오류 시 재시도 로직이 있는가?
  3. dotnet build src/Web/ExperionCrawler.csproj 실행 → 에러 0, 경고 0개 확인
  4. 문제가 있으면 수정 후 다시 빌드 확인

완료 조건

  • dotnet build src/Web/ExperionCrawler.csproj 결과: 에러 0, 경고 0
  • ExperionFastCleanupService.cs 파일 존재 및 빌드 통과
  • 완료일: 2026-04-29