diff --git a/_endpoint_test/notification-sse.http b/_endpoint_test/notification-sse.http new file mode 100644 index 00000000..d85fd46e --- /dev/null +++ b/_endpoint_test/notification-sse.http @@ -0,0 +1,7 @@ +### emitter 연결(조회) +GET {{host}}/test/event-stream +Authorization: {{authorization}} + +### 알림 전송 +POST {{host}}/notification?message=hello~5 +Authorization: {{authorization}} diff --git a/api/src/main/kotlin/com/mashup/dojo/NotificationSseController.kt b/api/src/main/kotlin/com/mashup/dojo/NotificationSseController.kt new file mode 100644 index 00000000..bcc74950 --- /dev/null +++ b/api/src/main/kotlin/com/mashup/dojo/NotificationSseController.kt @@ -0,0 +1,49 @@ +package com.mashup.dojo + +import io.github.oshai.kotlinlogging.KotlinLogging +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.RestController +import org.springframework.web.servlet.mvc.method.annotation.SseEmitter +import java.util.concurrent.CopyOnWriteArrayList + +@RestController +class NotificationSseController { + private val emitters = CopyOnWriteArrayList() + private val logger = KotlinLogging.logger { } + + private fun addEmitter(emitter: SseEmitter) { + emitters.add(emitter) + emitter.onCompletion { + logger.debug { "emitter completed successfully" } + emitters.remove(emitter) + } + emitter.onError { + logger.debug { "emitter error occurred: $it" } + emitters.remove(emitter) + } + emitter.onTimeout { + logger.debug { "emitter timed out" } + emitters.remove(emitter) + } + } + + @PostMapping("/notification") + fun send(message: String) { + emitters.forEach { + kotlin.runCatching { + it.send(SseEmitter.event().name("notification-test").data(message)) + }.onFailure { + logger.error { "error occurred: $it" } + } + } + } + + @GetMapping("/test/event-stream") + fun test(): SseEmitter { + // timeout 동안 아무런 데이터 전송되지 않으면 연결 자동 종료 + val emitter = SseEmitter(180000L) + addEmitter(emitter) + return emitter + } +}