[BE-78] 단계 3 운영 가시성 — 소스 상태 조회 · 소스 레지스트리 백필 API
작업 내용 (설계 의도)
근거 TDD: 20260808-지원관리-확장-tdd.md — “Observability”, “Release Scenario 3-4 소스 레지스트리 초기값 산출”
변경 사항
GET /api/operations/source-registry— 소스별 6종 상태·마지막 전이 시각·연속 비정상 일수·마지막 정상 수집 시각을 조회합니다. PRD Operations “소스 상태 레지스트리 가시성”과 Success Metrics “소스 커버리지 가시성”의 조회 수단입니다.POST /api/operations/backfills/source-registry— 데이터 마이그레이션 2단계(배치 백필). 대상 30행 미만(NFR-1: 회사 종속형 소스 30개 미만 + 애그리게이터 소수)이라 페이지 순회·청크가 불필요합니다. 이 근거를 코드 주석에 남깁니다 —private-db-schema-convention의 청크 요구는 락 범위 축소가 목적인데, 30행 단일 트랜잭션은 락 영향이 없습니다.registry_status IS NULL인 행만 대상이라 재실행 멱등입니다.- 초기값은
seeded_at·disabled_at·job_source_health·어댑터 보유 여부로 계산합니다.
- 크로스 컨텍스트 조합 — 응답에 회사명이 필요하므로
companyId집합으로 배치 조회 1회를 수행합니다(N+1 금지). OperationApiController.kt에 엔드포인트 2개를 추가합니다. 같은 wave(BE-77)는presentation/contact만 건드리므로 파일이 겹치지 않습니다.
롤백: 백필은 registry_status를 다시 NULL로 되돌리는 UPDATE로 즉시 복구 가능합니다(30행).
의존
- BE-70 (소스 레지스트리 상태 도메인)
다이어그램
처리 흐름
sequenceDiagram participant Op as 운영자 participant C as OperationApiController participant U as BackfillSourceRegistryUseCase participant R as JobSourceRegistryDomainService participant H as JobSourceHealthQueryDomainService participant Co as CompanyDomainService Op->>C: POST /api/operations/backfills/source-registry C->>U: execute() U->>H: 소스별 health 배치 조회 U->>R: recalculateAll() — 30행 단일 트랜잭션 R-->>U: 갱신 건수 Op->>C: GET /api/operations/source-registry C->>R: findAllStatuses() C->>Co: findAllBy(companyIds) 배치 1회 C-->>Op: 소스별 상태 + 회사명
클래스 의존
flowchart LR subgraph Presentation["presentation/operation"] Api[OperationApiController] end subgraph Application["application/operation"] Backfill[BackfillSourceRegistryUseCase] ListS[ListSourceRegistryUseCase] end subgraph Domain["domain"] RDS[JobSourceRegistryDomainService] HDS[JobSourceHealthQueryDomainService] CDS[CompanyDomainService] end Api --> Backfill Api --> ListS Backfill --> RDS Backfill --> HDS ListS --> RDS ListS --> CDS
테스트 케이스
- 백필 실행 후
registry_status IS NULL인 소스가 0건이다 - 수집 성공 이력이 있는 소스는
ACTIVE로 초기화된다 seeded_at이 NULL인 소스는DISCOVERED로 초기화된다disabled_at이 설정된 소스는DISABLED로 초기화된다- 어댑터가 없는 플랫폼 소스는
UNSUPPORTED로 초기화된다 - 연속 비정상 일수가 1 이상인 소스는
TRANSIENT_FAILURE로 초기화된다 - 백필을 두 번 실행하면 두 번째는 갱신 건수가 0이다 (멱등)
- 소스 레지스트리 조회에 상태·마지막 전이 시각·회사명이 포함된다
- 소스 30건 조회 시 회사 조회가 1회만 발생한다 (N+1 방지)
- 애그리게이터 소스는
companyId·companyName이 null이다 - 소스가 0건이면 빈 배열을 반환한다 (0건 경계)
- 기존 운영 조회 API(수집 이력·알림 이력·웹훅 수신) 동작이 변경되지 않는다 (회귀)