Nexters / 8potatoes-server

ํœด๊ฒŒ์†Œ ๋จน๊ฑฐ๋ฆฌ ์ถ”์ฒœ ์„œ๋น„์Šค๐ŸŸ๐Ÿข
0 stars 0 forks source link

kotlinx.coroutines.runBlocking & awaitSingle deadlock issue #4

Closed jun108059 closed 2 weeks ago

jun108059 commented 1 month ago

โœ๐Ÿป Description

  1. Spring Webflux + coroutine runBlocking + webClient + awaitSingle ์‚ฌ์šฉ์‹œ timeout์ด ๋ฐœ์ƒํ•˜๋Š” ์ด์Šˆ๊ฐ€ ๋ฐœ์ƒ
  2. webClient + awaitSingle์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด timeout์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š์Œ

๋ฐ๋“œ๋ฝ ๋ฐœ์ƒ ๊ฐ€๋Šฅ์„ฑ

runBlocking์€ ํ˜„์žฌ ์“ฐ๋ ˆ๋“œ๋ฅผ ๋ธ”๋กœํ‚นํ•˜๊ณ , ์ด๋ฒคํŠธ ๋ฃจํ”„์˜ ์Šค๋ ˆ๋“œ๋ฅผ ์ฐจ๋‹จ
์ด๋กœ ์ธํ•ด, ์ด๋ฒคํŠธ ๋ฃจํ”„ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ธ”๋กœํ‚น๋˜๋ฉด ๋‹ค๋ฅธ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†๊ฒŒ ๋˜์–ด ์„ฑ๋Šฅ ์ €ํ•˜์™€ ๋ฐ๋“œ๋ฝ์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œ

jun108059 commented 1 month ago

Sample code

Controller

    @GetMapping("/api/reststop/foods")
    fun getRestBestFoods() = runBlocking {
        val allRestBestFoods = restBestFoodService.fetchAllPages()
        allRestBestFoods.forEach { response ->
            response.list.forEach { restBestFood ->
                println(restBestFood)
            }
        }
        allRestBestFoods
    }

Linked method

    suspend fun fetchReststopFood(pageNo: Int): ReststopFoodResponse {
        return webClient.get()
            .uri { builder ->
                builder.path("/openapi/restinfo/restBestfoodList")
                    .queryParam("key", "secret")
                    .queryParam("type", "json")
                    .queryParam("numOfRows", "99")
                    .queryParam("pageNo", pageNo)
                    .build()
            }
            .retrieve()
            .bodyToMono(ReststopFoodResponse::class.java)
            .awaitSingle()
    }