| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 |
- namespace Application.Helpers;
- /// <summary>
- /// DART(OpenDART list.json) 공시 수집의 페이징/백필 판단 순수 로직 (DB/HTTP 비의존 — 테스트 가능).
- /// KRX 배치(날짜별 fetch)와 달리 DART 는 접수일 범위 페이징이라 별도 규칙이 필요하다:
- /// • 스펙 제한: corp_code 미지정 검색은 최근 3개월 접수분만 제공 → 요청 창을 3개월로 클램프.
- /// • 5만 행 상한: page_count=100 × MaxPages=500. 초기 백필처럼 창 전체가 미적재면 주 단위로 쪼개
- /// 창당 행 수를 낮춰 상한(정렬 desc 라 오래된 날짜부터 유실)을 회피한다.
- /// • 조기 종료: 일상 증분 수집에선 "한 페이지 전체가 기존 건"이면 그보다 오래된 페이지도 기수집으로
- /// 간주하고 종료 — 단 1페이지에서는 종료하지 않는다 (같은 날 재실행/부분 적재 방어 보수 조건).
- /// </summary>
- public static class DartBackfill
- {
- /// <summary>corp_code 미지정 list.json 의 스펙상 조회 한도 — 최근 3개월</summary>
- public const int SpecWindowMonths = 3;
- /// <summary>
- /// 요청 창 시작일을 스펙 한도(오늘-3개월)로 클램프. BackfillDays 가 90 초과로 설정돼도 요청 창이 3개월을 넘지 않는다.
- /// </summary>
- /// <returns>클램프된 시작일과 클램프 발생 여부 (발생 시 호출부가 경고 로그)</returns>
- public static (DateOnly Begin, bool Clamped) ClampToSpecWindow(DateOnly begin, DateOnly today)
- {
- var floor = today.AddMonths(-SpecWindowMonths);
- return begin < floor ? (floor, true) : (begin, false);
- }
- /// <summary>
- /// [begin, end] 포함 범위를 7일 단위 (bgn_de, end_de) 청크로 분할 — 오래된 쪽부터 순서대로.
- /// begin > end 면 빈 목록. 마지막 청크는 end 에서 잘린다.
- /// </summary>
- public static IReadOnlyList<(DateOnly Begin, DateOnly End)> SplitWeekly(DateOnly begin, DateOnly end)
- {
- var chunks = new List<(DateOnly Begin, DateOnly End)>();
- for (var chunkBegin = begin; chunkBegin <= end; chunkBegin = chunkBegin.AddDays(7))
- {
- var chunkEnd = chunkBegin.AddDays(6);
- if (chunkEnd > end)
- {
- chunkEnd = end;
- }
- chunks.Add((chunkBegin, chunkEnd));
- }
- return chunks;
- }
- /// <summary>
- /// 증분 수집 조기 종료 판정 — 해당 페이지의 모든 행이 이미 DB 에 존재하고(신규 0), 1페이지가 아닐 때만 true.
- /// 1페이지 제외 이유: 같은 날 재실행이면 1페이지도 전부 기존이지만, 과거에 부분 적재된 창일 가능성을
- /// 배제할 수 없어 최소 2페이지까지는 확인한다 (비용: 페이지 1콜).
- /// </summary>
- public static bool ShouldStopEarly(int pageNo, int rowCount, int newCount)
- {
- return pageNo > 1 && rowCount > 0 && newCount == 0;
- }
- }
|