https://kotlinlang.org logo
#coroutines
Title
# coroutines
c

christophsturm

05/07/2020, 5:52 PM
whats the best way to convert this code to a suspend method instead of returning a future?
Copy code
fun createCaptureServer(port: Int): CompletableFuture<String> {
        val future = CompletableFuture<String>()
        val undertow = Undertow.builder().addHttpListener(port, "127.0.0.1").setHandler {
            future.complete(it.queryString)
        }.build()
        undertow.start()
        return future.thenApplyAsync {
            undertow.stop()
            it
        }
    }
possibly using ktor instead of undertow.
o

octylFractal

05/07/2020, 5:55 PM
if you're using ktor, it basically just becomes a normal function -- ktor's http methods are all suspend
wait, nvm
misread what was happening here
realistically I think it would be mostly the same, except you'd use a
CompletableDeferred
instead of
Future
l
o

octylFractal

05/07/2020, 5:59 PM
yes, you could do it that way as well
though I would recommend
suspendCancellableCoroutine
c

christophsturm

05/07/2020, 6:03 PM
thanks guys!
and how do do the
thenApplyAsync
part? (stop the http server)
o

octylFractal

05/07/2020, 6:10 PM
use
try-finally
(assuming you go the
suspendCancellableCoroutine
route)
c

christophsturm

05/07/2020, 6:15 PM
why is
suspendCancellableCoroutine
better? when would it cancel?
o

octylFractal

05/07/2020, 6:16 PM
if you cancel the Job that the suspend function is a part of, then it properly cancels and throws an exception
otherwise it will just ignore cancellation
going to be honest, though, I don't see how to do this easily with
suspendCancellableCoroutine
-- I think that using the future model for actually retrieving the data is better
Copy code
suspend fun createCaptureServer(port: Int): String {
  val deferred = CompleteableDeferred<String>()
  val server = <create server, with handler that completes the deferred>
  server.start()
  try {
    return deferred.await()
  } finally {
    server.close()
  }
}
is my take
c

christophsturm

05/07/2020, 6:20 PM
Copy code
suspend fun createCaptureServer(port: Int): String {
        val result =  suspendCoroutine<String>{cont->
            val undertow = Undertow.builder().addHttpListener(port, "127.0.0.1").setHandler {
                cont.resume(it.queryString)
            }.build()
            undertow.start()
        }
        undertow.close()
        return result
    }
this is what i came up with, but it does not work that way because undertow is inside the callback, so i would have to make it nullable and a var. which is not so great
so your solution is probably better
i ended up without finally, but thats probably just a matter of taste:
Copy code
val deferred = CompletableDeferred<String>()
        val undertow = Undertow.builder().addHttpListener(port, "127.0.0.1").setHandler {
            deferred.complete(it.queryString)
        }.build()
        undertow.start()

        val result = deferred.await()
        undertow.stop()
        return result
    }
thanks for your help!
o

octylFractal

05/07/2020, 6:26 PM
i'd be concerned about leaking the server in the case of an exception
but maybe you're okay with that
9 Views