@startuml event-최종승인및배포 !theme mono title Event Service - 최종 승인 및 Distribution Service 동기 호출 (UFR-EVENT-050) actor Client participant "API Gateway" as Gateway participant "EventController" as Controller <> participant "EventService" as Service <> participant "EventRepository" as Repo <> participant "Redis Cache" as Cache <> database "Event DB" as DB <> participant "Distribution Service" as DistSvc <> participant "Kafka Producer" as Kafka <> note over Controller, Kafka **UFR-EVENT-050: 이벤트 최종 승인 및 배포** - 이벤트 준비 상태 검증 - 이벤트 승인 및 Kafka 이벤트 발행 - Distribution Service 동기 호출 (다중 채널 배포) - 이벤트 상태를 ACTIVE로 변경 end note Client -> Gateway: POST /api/events/{eventDraftId}/publish\n{"userId": 123,\n"selectedChannels": [\n "우리동네TV",\n "지니TV",\n "Instagram"\n]} activate Gateway Gateway -> Controller: POST /api/events/{eventDraftId}/publish activate Controller Controller -> Controller: 요청 검증\n(필수 필드, 채널 유효성) Controller -> Service: publishEvent(eventDraftId, userId, selectedChannels) activate Service == 1단계: 이벤트 초안 조회 및 검증 == Service -> Repo: findById(eventDraftId) activate Repo Repo -> DB: 이벤트 초안 조회\n(초안ID로 조회) activate DB DB --> Repo: EventDraft 엔티티\n{목적, 추천안, 콘텐츠, 상태} deactivate DB Repo --> Service: EventDraft entity deactivate Repo Service -> Service: validateOwnership(userId, eventDraft) note right 소유권 검증: - 사용자ID와 초안 소유자 일치 확인 - 권한 없으면 403 Forbidden end note Service -> Service: validatePublishReady() note right 발행 준비 검증: - 목적 선택 완료 - AI 추천 선택 완료 - 콘텐츠 선택 완료 - 배포 채널 최소 1개 선택 end note == 2단계: 이벤트 승인 == Service -> Repo: updateStatus(eventDraftId, APPROVED) activate Repo Repo -> DB: 이벤트 초안 상태 업데이트\n(상태를 APPROVED로,\n승인일시를 현재 시각으로 저장) activate DB DB --> Repo: 업데이트 완료 deactivate DB Repo --> Service: EventDraft entity deactivate Repo == 3단계: Kafka 이벤트 발행 == Service -> Kafka: 이벤트 발행\nTopic: event-topic\nPayload: {eventId, userId, title,\nobjective, createdAt} activate Kafka note right Kafka Event Topic: - Topic: event-topic - Consumer: Analytics Service - Event Type: EventCreated end note Kafka --> Service: ACK (발행 확인) deactivate Kafka == 4단계: Distribution Service 동기 호출 == Service -> DistSvc: POST /api/distribution/distribute\n{"eventId": 123,\n"channels": [...],\n"content": {...}} activate DistSvc note right 동기 호출 (Circuit Breaker 적용): - Timeout: 70초 - 다중 채널 병렬 배포 - Failure Rate: 50% 초과 시 OPEN end note DistSvc -> DistSvc: distributeToChannels(eventId, channels) note right 다중 채널 병렬 배포: - 우리동네TV - 링고비즈 (음성 안내) - 지니TV - Instagram - Naver Blog - Kakao Channel end note DistSvc --> Service: DistributionResponse\n{"distributionId": "dist-123",\n"channelResults": [\n {"channel": "우리동네TV", "status": "SUCCESS"},\n {"channel": "지니TV", "status": "SUCCESS"},\n {"channel": "Instagram", "status": "SUCCESS"}\n]} deactivate DistSvc == 5단계: 이벤트 활성화 == Service -> Repo: updateStatus(eventDraftId, ACTIVE) activate Repo Repo -> DB: 이벤트 상태 업데이트\n(상태를 ACTIVE로,\n배포일시를 현재 시각으로 저장) activate DB DB --> Repo: 업데이트 완료 deactivate DB Repo --> Service: Event entity deactivate Repo == 6단계: 캐시 무효화 == Service -> Cache: 캐시 삭제\nKey: draft:event:{eventDraftId} activate Cache note right Redis 캐시 무효화: - 이벤트 초안 캐시 삭제 - 활성화 완료 후 불필요 end note Cache --> Service: 삭제 완료 deactivate Cache == 7단계: 응답 반환 == Service --> Controller: PublishResponse\n{eventId, status: ACTIVE,\ndistributionResults} deactivate Service Controller --> Gateway: 200 OK\n{"eventId": 123,\n"status": "ACTIVE",\n"distributionResults": [...]} deactivate Controller Gateway --> Client: 200 OK\n이벤트 배포 완료 deactivate Gateway note over Client, Kafka **배포 완료 후 처리** - Distribution Service는 배포 완료 후 Kafka에\n DistributionCompleted 이벤트 발행 - Analytics Service가 구독하여 초기 통계 생성 - 이벤트 상태: ACTIVE (참여자 접수 시작) **성능 목표** - 응답 시간: 60초 이내 (Distribution Service 포함) - Distribution Service 타임아웃: 70초 - 채널별 배포: 병렬 처리로 최적화 end note @enduml