kt-event-marketing/design/backend/sequence/inner/distribution-배포상태조회.puml
2025-10-22 14:13:57 +09:00

170 lines
6.5 KiB
Plaintext

@startuml distribution-배포상태조회
!theme mono
title Distribution Service - 배포 상태 조회 (UFR-DIST-020)
actor "소상공인" as User
participant "Frontend" as FE
participant "API Gateway" as Gateway
participant "Distribution\nREST API" as API
participant "Distribution\nController" as Controller
participant "Distribution\nService" as Service
participant "Redis Cache" as Cache
database "Event DB" as DB
participant "Circuit Breaker\nManager" as CB
== 배포 상태 조회 요청 ==
User -> FE: 이벤트 상세 화면\n배포 상태 섹션 확인
activate FE
FE -> Gateway: GET /api/distribution/{eventId}/status
activate Gateway
Gateway -> Gateway: JWT 토큰 검증
Gateway -> API: GET /distribution/{eventId}/status
activate API
API -> Controller: getDistributionStatus(eventId)
activate Controller
Controller -> Service: fetchDistributionStatus(eventId)
activate Service
== Cache-Aside 패턴 적용 ==
Service -> Cache: 캐시 조회\nkey: distribution:{eventId}
activate Cache
alt 캐시 HIT
Cache --> Service: 캐시된 배포 상태\n{status, results[], cachedAt}
deactivate Cache
note over Service: 캐시 TTL: 1시간\n빠른 응답 (0.1초)
Service --> Controller: DistributionStatus\n{eventId, status, channelResults[]}
deactivate Service
else 캐시 MISS
Cache --> Service: null (캐시 없음)
deactivate Cache
== 데이터베이스에서 배포 이력 조회 ==
Service -> DB: SELECT * FROM distribution_logs\nWHERE event_id = :eventId\nORDER BY created_at DESC\nLIMIT 1
activate DB
alt 배포 이력 존재
DB --> Service: DistributionLog\n{id, eventId, status, createdAt, completedAt}
deactivate DB
Service -> DB: SELECT * FROM distribution_channel_logs\nWHERE distribution_log_id = :logId
activate DB
DB --> Service: List<ChannelLog>\n{channel, status, distributionId, postUrl, retries, error}
deactivate DB
== 실시간 채널 상태 확인 (선택적) ==
note over Service: 진행중(IN_PROGRESS) 상태일 때만\n외부 API로 실시간 상태 확인
alt 배포 진행중 (IN_PROGRESS)
loop 각 채널별 상태 확인
Service -> CB: checkCircuitBreaker(channel)
alt Circuit Breaker CLOSED
CB --> Service: 요청 허용
alt 우리동네TV
Service -> DB: SELECT distribution_id FROM distribution_channel_logs\nWHERE channel = 'WooridongneTV'
DB --> Service: distributionId
note over Service: Timeout: 5초\nCircuit Breaker 적용
Service -> "외부 APIs": GET /api/status/{distributionId}
activate "외부 APIs"
alt 성공
"외부 APIs" --> Service: 200 OK\n{status: COMPLETED, views: 1500}
deactivate "외부 APIs"
Service -> DB: UPDATE distribution_channel_logs\nSET status = 'COMPLETED', views = 1500
else 실패 (Timeout/Error)
"외부 APIs" --> Service: 500 Error or Timeout
deactivate "외부 APIs"
Service -> CB: recordFailure(channel)
note over Service: Circuit Breaker 실패율 증가\n50% 초과 시 Circuit Open
end
end
note over Service: 다른 채널(링고비즈, 지니TV, SNS)도\n동일한 패턴으로 상태 확인
else Circuit Breaker OPEN
CB --> Service: 서킷 오픈 상태\n(외부 API 호출 스킵)
note over Service: Fallback: DB 저장 상태 사용\n30초 후 Half-Open 전환
end
end
== 배포 완료 여부 판단 ==
Service -> Service: 모든 채널 상태 확인\n완료/실패 여부 판단
alt 모든 채널 완료
Service -> DB: UPDATE distribution_logs\nSET status = 'COMPLETED', completed_at = NOW()
else 일부 실패
Service -> DB: UPDATE distribution_logs\nSET status = 'PARTIAL_FAILURE'
end
end
== 배포 상태 응답 준비 ==
Service -> Service: 채널별 상태 집계\n{channel, status, distributionId, postUrl, views, error}
Service -> Cache: 배포 상태 캐싱\nkey: distribution:{eventId}\nvalue: {status, results[]}\nTTL: 1시간
Service --> Controller: DistributionStatus\n{eventId, status, channelResults[]}
deactivate Service
else 배포 이력 없음
DB --> Service: null
deactivate DB
Service --> Controller: DistributionStatus\n{eventId, status: NOT_FOUND}
deactivate Service
end
end
== 응답 반환 ==
Controller --> API: DistributionStatusResponse\n{eventId, status, channelResults[]}
deactivate Controller
API --> Gateway: 200 OK\n{eventId, overallStatus, channels[]}
deactivate API
Gateway --> FE: 배포 상태 응답\n{overallStatus, channels[]}
deactivate Gateway
== 프론트엔드 화면 표시 ==
FE -> FE: 채널별 상태 표시\n- 대기중: 회색\n- 진행중: 파란색\n- 완료: 초록색\n- 실패: 빨간색
FE --> User: 배포 상태 시각화\n채널별 세부 정보 표시
deactivate FE
note over User: 배포 상태 정보\n- 우리동네TV: 완료 (배포ID, 조회수)\n- 링고비즈: 완료 (업데이트 시각)\n- 지니TV: 완료 (광고ID, 스케줄)\n- SNS: 완료 (포스팅 URL)
== 재시도 기능 (실패한 채널) ==
alt 실패한 채널 존재
User -> FE: "재시도" 버튼 클릭
FE -> Gateway: POST /api/distribution/{eventId}/retry\n{channels: [failed_channel_list]}
Gateway -> API: 재시도 요청
API -> Controller: retryDistribution(eventId, channels)
Controller -> Service: retryFailedChannels(eventId, channels)
activate Service
note over Service: 실패한 채널만\n다시 배포 시도\n(동일한 Circuit Breaker/Retry 적용)
Service -> DB: 새로운 배포 시도 로그 생성
Service -> Cache: 캐시 무효화
Service --> Controller: 재시도 완료\n{retryStatus}
deactivate Service
Controller --> API: RetryResponse
API --> Gateway: 200 OK
Gateway --> FE: 재시도 결과
FE --> User: "재시도가 완료되었습니다"
end
== 실시간 업데이트 (선택적) ==
note over FE: Frontend는 5초마다\nPolling 또는 WebSocket으로\n배포 상태 자동 갱신\n(Phase 2에서 WebSocket 적용 가능)
@enduml