gpt4 book ai didi

kotlin - Vertx和Kotlin协程永远挂起

转载 作者:行者123 更新时间:2023-12-02 13:39:13 26 4
gpt4 key购买 nike

我出于学习目的,使用Kotlin协程重写了一些Java Vertx异步代码。但是,当我尝试测试简单的HTTP调用时,基于协程的测试将永远挂起,我真的不知道问题出在哪里。这里是一个复制者:

@RunWith(VertxUnitRunner::class)
class HelloWorldTest {

private val vertx: Vertx = Vertx.vertx()

@Before
fun setUp(context: TestContext) {
// HelloWorldVerticle is a simple http server that replies "Hello, World!" to whatever call
vertx.deployVerticle(HelloWorldVerticle::class.java!!.getName(), context.asyncAssertSuccess())
}

// ORIGINAL ASYNC TEST HERE. IT WORKS AS EXPECTED
@Test
fun testAsync(context: TestContext) {
val atc = context.async()
vertx.createHttpClient().getNow(8080, "localhost", "/") { response ->
response.handler { body ->
context.assertTrue(body.toString().equals("Hello, World!"))
atc.complete()
}
}
}

// First attempt, it hangs forever, the response is never called
@Test
fun testSync1(context: TestContext) = runBlocking<Unit> {
val atc = context.async()
val body = await<HttpClientResponse> {
vertx.createHttpClient().getNow(8080, "localhost", "/", { response -> response.handler {it}} )
}
context.assertTrue(body.toString().equals("Hello, World!"))
atc.complete()
}

// Second attempt, it hangs forever, the response is never called
@Test
fun testSync2(context: TestContext) = runBlocking<Unit> {
val atc = context.async()
val response = await<HttpClientResponse> {
vertx.createHttpClient().getNow(8080, "localhost", "/", it )
}
response.handler { body ->
context.assertTrue(body.toString().equals("Hello, World!"))
atc.complete()
}
}

suspend fun <T> await(callback: (Handler<T>) -> Unit) =
suspendCoroutine<T> { cont ->
callback(Handler { result: T ->
cont.resume(result)
})
}
}

每个人都可以找出问题所在吗?

最佳答案

在我看来,您的代码有几个问题:

  • 您可以在部署HTTP服务器之前运行测试
  • 我相信,由于您在runBlocking中执行代码,因此阻止了事件循环完成请求。
  • 最后,我建议您使用HttpClienctResponse::bodyHandler方法而不是HttpClientResponse::handler,因为处理程序可能会接收部分数据。

  • 这是一个可行的替代解决方案:
    import io.vertx.core.AbstractVerticle
    import io.vertx.core.Future
    import io.vertx.core.Handler
    import io.vertx.core.Vertx
    import io.vertx.core.buffer.Buffer
    import io.vertx.core.http.HttpClientResponse
    import kotlin.coroutines.experimental.Continuation
    import kotlin.coroutines.experimental.EmptyCoroutineContext
    import kotlin.coroutines.experimental.startCoroutine
    import kotlin.coroutines.experimental.suspendCoroutine

    inline suspend fun <T> await(crossinline callback: (Handler<T>) -> Unit) =
    suspendCoroutine<T> { cont ->
    callback(Handler { result: T ->
    cont.resume(result)
    })
    }

    fun <T : Any> async(code: suspend () -> T) = Future.future<T>().apply {
    code.startCoroutine(object : Continuation<T> {
    override val context = EmptyCoroutineContext
    override fun resume(value: T) = complete()
    override fun resumeWithException(exception: Throwable) = fail(exception)
    })
    }

    fun main(args: Array<String>) {
    async {
    val vertx: Vertx = Vertx.vertx()

    //0. take the current context
    val ctx = vertx.getOrCreateContext()

    //1. deploy the http server
    await<Unit> { cont ->
    vertx.deployVerticle(object : AbstractVerticle() {
    override fun start() {
    vertx.createHttpServer()
    .requestHandler { it.response().end("Hello World") }
    .listen(7777) { ctx.runOnContext { cont.handle(Unit) } }
    //note that it is important tp complete the handler in the correct context
    }
    })
    }

    //2. send request
    val response: HttpClientResponse = await { vertx.createHttpClient().getNow(7777, "localhost", "/", it) }

    //3. await response
    val body = await<Buffer> { response.bodyHandler(it) }
    println("received $body")
    }
    }

    关于kotlin - Vertx和Kotlin协程永远挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45476676/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com