[BE-33] 내구성 수집 사이클 도메인 계약 · 상태 머신
작업 내용 (설계 의도)
변경 사항
TDD 20260730-확장-안전-공고수집-배치-tdd.md의 cycle aggregate, budget value object, slice gateway 계약을 posting 도메인에 추가한다. 자정 eligible source creation의 NOT_STARTED→PENDING→RUNNING→PENDING/SUCCESS/BUDGET_EXHAUSTED/FAILED 전이, disable 시 cycle 상태를 바꾸지 않고 future claim만 막는 규칙, lease token, named safe-close predicate SUCCESS && isComplete && fetchedCount>0을 domain에 캡슐화한다. HTTP·JPA·sleep은 이 티켓에 넣지 않는다.
의존
- DBA의 expand-only cycle/seen/host-throttle 스키마 설계 및 migration
다이어그램
처리 흐름
sequenceDiagram participant D as DomainService participant C as Cycle participant R as CycleRepository D->>R: claimReady() D->>C: claim(token, until) D->>C: recordSlice(result) C-->>D: pending/success/exhausted
클래스 의존
flowchart LR CycleDomainService --> CollectionCycle CycleDomainService --> CycleRepository CollectionCycle --> CollectionBudget JobSourceGateway --> CollectionSliceDescriptor
테스트 케이스
- 동일 source/KST 일자 cycle 생성은 멱등이며 하나의 cycle ID만 반환한다.
- eligible source의 cycle은 00:00 KST 생성 시 NOT_STARTED이고 외부 HTTP 없이 prepare될 때만 PENDING이 된다.
- 09:00 snapshot 보충 생성은 누락된 eligible source만 NOT_STARTED으로 만들며 기존 cycle 상태를 바꾸지 않는다.
- NOT_STARTED/PENDING source가 disable되면 상태를 바꾸지 않고 외부 HTTP 없이 claim 대상에서 제외한다.
- PENDING cycle은 유효한 lease token으로만 RUNNING이 된다.
- 만료 또는 다른 token의 slice 결과는 상태·카운터를 변경하지 않는다.
- complete-zero SUCCESS는 abnormal·closeGuarded이고
isComplete=true여도 미발견/마감 델타를 실행하지 않는다. - SUCCESS·isComplete·fetchedCount>0을 모두 만족할 때만 미발견/마감 델타 실행 자격을 만든다.
- 일일 페이지·공고·상세 상한 도달은 BUDGET_EXHAUSTED이며 auto-close 자격을 만들지 않는다.