[BE-34] 수집 dispatcher · lease 회수 · HTTP-트랜잭션 분리

작업 내용 (설계 의도)

변경 사항

TDD의 CollectionDispatchUseCase와 최소 dispatcher scheduler trigger를 구현한다. 활성 source의 일일 cycle을 idempotent하게 생성하고 tick당 claim 상한 안에서 공정하게 실행한다. claim, 결과 반영, terminal 실패 기록만 짧은 transaction이며 JobSourceGateway.collectSlice는 transaction 밖에서 호출한다. gateway raw payload를 버리지 않는다: CollectionSliceProcessor가 회사 종속형 저장/refresh, aggregator 회사 resolve, seen ID 저장, safe-close final delta를 결과 반영 transaction에서 수행한다. 모든 cycle state write와 delta transaction은 BE-43의 concrete SLA cutoff gate를 transactionally 획득한다. aggregator의 회사 resolve는 slice 결과 뒤 같은 짧은 persistence transaction에서 수행한다. FR-69에 따라 HTTP 403/429/5xx/timeout/policy 실패와 lease 만료는 즉시 FAILED이며 같은 KST 날짜에 외부 HTTP를 재호출하지 않는다. dispatcher scheduler는 v2 ON일 때만 이 UseCase를 호출하는 최소 functional trigger이며, BE-41은 cron/config·legacy scheduler disable·09:00 ordering의 최종 wiring을 소유한다. 롤백은 posting.collection-dispatch-v2 OFF 후 lease 만료를 기다린다.

의존

  • BE-33
  • BE-43
  • DBA migration

다이어그램

처리 흐름

sequenceDiagram
    participant S as Scheduler
    participant U as DispatchUseCase
    participant R as CycleRepository
    participant G as JobSourceGateway
    S->>U: executeTick()
    U->>R: claimReady short tx
    U->>G: collectSlice no tx
    G-->>U: slice outcome
    U->>R: applySlice short tx

클래스 의존

flowchart LR
    Scheduler --> DispatchUseCase
    DispatchUseCase --> CycleDomainService
    DispatchUseCase --> JobSourceGateway
    DispatchUseCase --> CompanyDomainService

테스트 케이스

  • tick은 설정된 최대 source 수보다 많은 ready cycle을 claim하지 않는다.
  • gateway 호출 시 활성 Spring transaction이 없다.
  • 목록 HTTP 실패는 즉시 FAILED로 기록되고 해당 source는 다음 KST 일자까지 다시 claim되지 않는다.
  • 만료 lease는 terminal FAILED가 되고 이전 token 결과는 저장되지 않는다.
  • aggregator의 회사 자동 등록 DB 실패는 HTTP를 재호출하지 않고 terminal FAILED로 기록하며 다른 source를 막지 않는다.
  • fetched slice raw posting은 저장/refresh와 seen ID 기록을 거친 뒤에만 cursor·카운터 state write가 완료된다.
  • two-worker MySQL test는 SLA cutoff capture와 cycle state write가 같은 gate로 직렬화되어 snapshot이 state 전이 전 또는 후 하나만 관측함을 검증한다.
  • disabled source는 prepare 전과 claim 전 모두 제외되며 throttle 이후에도 다시 확인해 새 HTTP를 발행하지 않는다.
  • v2 ON dispatcher scheduler는 한 tick을 호출하고 v2 OFF에서는 호출하지 않는다.