| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 |
- namespace Application.Helpers;
- /// <summary>
- /// KRX 일별 수집 배치의 공용 백필 오케스트레이션 (순수 로직, DB 비의존 — 테스트 가능).
- /// endDate 에서 startDate 방향(과거)으로 영업일을 훑으며, 아직 적재되지 않은 날만 수집한다:
- /// • 주말/휴장일(holidays) 은 건너뛴다.
- /// • existsForDate(day) == true (이미 적재됨) 이면 건너뛴다 → resumable.
- /// • 그 외에는 fetchAndUpsertForDate(day) 를 호출하고, quota 보호를 위해 호출 사이에 delayMs 만큼 쉰다.
- /// • fetch 횟수가 maxPerRun 에 도달하면 즉시 멈춘다 → 하루 배치가 quota 상한 안에서 조금씩 채운다.
- /// 최신일부터 채우므로(recent-first) 여러 번의 일일 실행에 걸쳐 3년치를 메우고 이후엔 최신만 유지한다.
- /// 반환값은 이번 실행에서 실제 fetch 한 날 수.
- /// </summary>
- public static class KrxBackfill
- {
- /// <param name="existsForDate">해당 날짜가 이미 적재되어 있는지 (true = skip)</param>
- /// <param name="fetchAndUpsertForDate">해당 날짜를 수집·upsert (부작용 담당)</param>
- /// <param name="startDate">백필 하한(포함) — 보통 today.AddYears(-BackfillYears)</param>
- /// <param name="endDate">백필 상한(포함) — 보통 직전 영업일. 여기서부터 과거로 훑는다</param>
- /// <param name="holidays">휴장일 집합 (주말은 자동 제외)</param>
- /// <param name="maxPerRun">이번 실행 최대 fetch 수 (quota 상한). 0 이하면 fetch 안 함</param>
- /// <param name="delayMs">fetch 호출 사이 지연(ms). 0 이하면 지연 없음</param>
- public static async Task<int> RunAsync(
- Func<DateOnly, CancellationToken, Task<bool>> existsForDate,
- Func<DateOnly, CancellationToken, Task> fetchAndUpsertForDate,
- DateOnly startDate,
- DateOnly endDate,
- IReadOnlySet<DateOnly> holidays,
- int maxPerRun,
- int delayMs,
- CancellationToken ct)
- {
- if (maxPerRun <= 0)
- {
- return 0;
- }
- var fetched = 0;
- for (var day = endDate; day >= startDate; day = day.AddDays(-1))
- {
- ct.ThrowIfCancellationRequested();
- if (day.DayOfWeek is DayOfWeek.Saturday or DayOfWeek.Sunday || holidays.Contains(day))
- {
- continue;
- }
- if (await existsForDate(day, ct))
- {
- continue;
- }
- if (fetched > 0 && delayMs > 0)
- {
- await Task.Delay(delayMs, ct);
- }
- await fetchAndUpsertForDate(day, ct);
- fetched++;
- if (fetched >= maxPerRun)
- {
- break;
- }
- }
- return fetched;
- }
- }
|