Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,14 @@ class AiChatbotAdapter(
},
).build()

fun chat(request: SendAiChatRequest): SendAiChatResponse =
fun chat(
request: SendAiChatRequest,
authorization: String,
): SendAiChatResponse =
try {
circuitBreaker.executeCheckedSupplier {
retry.executeCheckedSupplier {
doChat(request)
doChat(request, authorization)
}
}
} catch (e: CallNotPermittedException) {
Expand All @@ -50,11 +53,15 @@ class AiChatbotAdapter(
throw ExpectedException("AI 챗봇 서버와 통신 중 오류가 발생했습니다.", HttpStatus.BAD_GATEWAY)
}

private fun doChat(request: SendAiChatRequest): SendAiChatResponse =
private fun doChat(
request: SendAiChatRequest,
authorization: String,
): SendAiChatResponse =
restClient
.post()
.uri("/ai/chat")
.contentType(MediaType.APPLICATION_JSON)
.header("Authorization", authorization)
.body(request)
.retrieve()
.onStatus({ it.isError }) { _, response ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import io.swagger.v3.oas.annotations.tags.Tag
import jakarta.validation.Valid
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestHeader
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import team.incube.flooding.domain.ai.presentation.data.request.SendAiChatRequest
Expand Down Expand Up @@ -34,7 +35,9 @@ class AiController(
@PostMapping("/chat")
fun chat(
@Valid @RequestBody request: SendAiChatRequest,
): CommonApiResponse<SendAiChatResponse> = CommonApiResponse.success("OK", sendAiChatService.execute(request))
@RequestHeader("Authorization") authorization: String,
): CommonApiResponse<SendAiChatResponse> =
CommonApiResponse.success("OK", sendAiChatService.execute(request, authorization))

@Operation(
summary = "AI 음악 추천",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@ import team.incube.flooding.domain.ai.presentation.data.request.SendAiChatReques
import team.incube.flooding.domain.ai.presentation.data.response.SendAiChatResponse

interface SendAiChatService {
fun execute(request: SendAiChatRequest): SendAiChatResponse
fun execute(
request: SendAiChatRequest,
authorization: String,
): SendAiChatResponse
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,8 @@ import team.incube.flooding.domain.ai.service.SendAiChatService
class SendAiChatServiceImpl(
private val aiChatbotAdapter: AiChatbotAdapter,
) : SendAiChatService {
override fun execute(request: SendAiChatRequest): SendAiChatResponse = aiChatbotAdapter.chat(request)
override fun execute(
request: SendAiChatRequest,
authorization: String,
): SendAiChatResponse = aiChatbotAdapter.chat(request, authorization)
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ class SendAiChatServiceTest :
val service = SendAiChatServiceImpl(adapter)

Given("챗봇 어댑터가 정상 응답을 반환할 때") {
every { adapter.chat(any()) } returns SendAiChatResponse("안녕하세요!")
every { adapter.chat(any(), any()) } returns SendAiChatResponse("안녕하세요!")

When("서비스를 실행하면") {
val result = service.execute(SendAiChatRequest("안녕"))
val result = service.execute(SendAiChatRequest("안녕"), "Bearer token")

Then("챗봇 응답이 반환된다") {
result.response shouldBe "안녕하세요!"
Expand All @@ -32,26 +32,28 @@ class SendAiChatServiceTest :

Given("챗봇 어댑터에 요청이 전달될 때") {
val requestSlot = slot<SendAiChatRequest>()
every { adapter.chat(capture(requestSlot)) } returns SendAiChatResponse("응답")
val authorizationSlot = slot<String>()
every { adapter.chat(capture(requestSlot), capture(authorizationSlot)) } returns SendAiChatResponse("응답")

When("서비스를 실행하면") {
service.execute(SendAiChatRequest("테스트 메시지"))
service.execute(SendAiChatRequest("테스트 메시지"), "Bearer token")

Then("요청이 어댑터에 그대로 전달된다") {
Then("요청과 인증 토큰이 어댑터에 그대로 전달된다") {
requestSlot.captured.userInput shouldBe "테스트 메시지"
authorizationSlot.captured shouldBe "Bearer token"
}
}
}

Given("챗봇 서버가 오류를 반환할 때") {
every { adapter.chat(any()) } throws
every { adapter.chat(any(), any()) } throws
ExpectedException("AI 챗봇 서버와 통신 중 오류가 발생했습니다.", HttpStatus.BAD_GATEWAY)

When("서비스를 실행하면") {
Then("BAD_GATEWAY 예외가 발생한다") {
val exception =
shouldThrow<ExpectedException> {
service.execute(SendAiChatRequest("안녕"))
service.execute(SendAiChatRequest("안녕"), "Bearer token")
}
exception.statusCode shouldBe HttpStatus.BAD_GATEWAY
}
Expand Down
Loading