@startuml !theme mono title Notification Service - 초대알림발송 내부 시퀀스 participant "NotificationController" as Controller participant "NotificationService" as Service participant "EmailTemplateService" as TemplateService participant "NotificationRepository" as Repository participant "EmailClient" as EmailClient database "Notification DB" as DB queue "Azure Event Hubs<>" as EventHub participant "Email Service<>" as EmailService == MeetingCreated 이벤트 수신 == EventHub -> Controller: MeetingCreated 이벤트 수신 activate Controller note right 이벤트 데이터: - meetingId - 제목 - 일시 - 장소 - 참석자 목록 (이메일) - 생성자 정보 end note Controller -> Service: sendMeetingInvitation(meetingId, meetingData) activate Service == 알림 기록 생성 == Service -> Repository: createNotification(meetingId, "INVITATION", participants) activate Repository Repository -> DB: 초대 알림 생성\n(알림ID, 회의ID, 유형, 상태, 수신자, 생성일시) activate DB DB --> Repository: notificationId 반환 deactivate DB Repository --> Service: NotificationEntity 반환 deactivate Repository == 이메일 템플릿 생성 == Service -> TemplateService: generateInvitationEmail(meetingData) activate TemplateService TemplateService -> TemplateService: 템플릿 로드 note right 템플릿 정보: - 제목: "[회의 초대] {회의 제목}" - 내용: 회의 정보 + 참여 링크 - CTA 버튼: "회의 참석하기" end note TemplateService -> TemplateService: 데이터 바인딩 note right 바인딩 데이터: - 회의 제목 - 날짜/시간 - 장소 - 생성자 이름 - 회의 참여 링크 - 캘린더 추가 링크 end note TemplateService --> Service: EmailContent 반환\n(subject, htmlBody, plainTextBody) deactivate TemplateService == 참석자별 이메일 발송 (병렬 처리) == loop 각 참석자별 Service -> EmailClient: sendEmail(recipient, emailContent) activate EmailClient EmailClient -> EmailService: SMTP 이메일 발송 activate EmailService EmailService --> EmailClient: 발송 결과 deactivate EmailService alt 발송 성공 EmailClient --> Service: SUCCESS Service -> Repository: updateRecipientStatus(notificationId, recipient, "SENT") activate Repository Repository -> DB: 수신자별 알림 상태 업데이트\n(상태='발송완료', 발송일시=현재시각) activate DB DB --> Repository: 업데이트 완료 deactivate DB Repository --> Service: 완료 deactivate Repository else 발송 실패 EmailClient --> Service: FAILED (errorMessage) Service -> Repository: updateRecipientStatus(notificationId, recipient, "FAILED") activate Repository Repository -> DB: 수신자별 알림 상태 업데이트\n(상태='발송실패', 오류메시지=에러내용) activate DB DB --> Repository: 업데이트 완료 deactivate DB Repository --> Service: 완료 deactivate Repository Service -> Service: 재시도 큐에 추가\n(최대 3회 재시도) end deactivate EmailClient end == 전체 알림 상태 업데이트 == Service -> Repository: updateNotificationStatus(notificationId, finalStatus) activate Repository Repository -> DB: 알림 최종 상태 업데이트\n(상태, 완료일시, 발송건수, 실패건수) activate DB DB --> Repository: 업데이트 완료 deactivate DB Repository --> Service: 완료 deactivate Repository Service --> Controller: NotificationResponse\n(notificationId, status, sentCount, failedCount) deactivate Service Controller --> EventHub: InvitationSent 이벤트 발행\n(meetingId, notificationId, status) deactivate Controller note over Controller, EmailService 처리 시간: - 알림 기록 생성: ~100ms - 템플릿 생성: ~200ms - 이메일 발송 (per recipient): ~500ms - 총 처리 시간: 참석자 수에 비례 (병렬 처리) 재시도 정책: - 최대 3회 재시도 - 재시도 간격: 5분, 15분, 30분 end note @enduml