Hey guys, I'm trying to migrate some functionality...
# arrow
d
Hey guys, I'm trying to migrate some functionality from
IO
to the new
suspend
way We're calling a third-party method which returns a
CompletableFuture<Void>
and before we handled it in the following way
Copy code
async {
    run {
        doSomethingAsync() //this returns the CompletableFuture<Void>
    }
}
How do I correctly go from that completableFuture to a suspend function which returns an
Either<MyError, Unit>
Copy code
Either.catch {
    doSomethingAsync().await()
}.mapLeft { MyError() }.unit()
this is as far as I got, but I'm not sure if
await()
is the correct way to go
s
Hey @Dasyel Willems, I think to correctly wire
CompletableFuture
into
suspend
you want the following implementation. Which is optimised to return immediately in case the
CompletableFuture
is already finished, and adds support for cancellation.
Copy code
suspend fun <A> CompletableFuture<A>.await(): A =
  if (isDone) {
    try {
      get()
    } catch (e: ExecutionException) {
      throw e.cause ?: e // unwrap original cause from ExecutionException
    }
  } else cancellable { callback ->
    whenComplete { res, exception ->
      if (exception == null) callback(Result.success(res))
      else callback(Result.failure((exception as? CompletionException)?.cause ?: exception))
    }

    CancelToken { cancel(false) }
  }
And then you can safely use the snippet you shared in the second snippet. You could also update the above implementation to take a
(exception: Throwable) -> E
lambda and return
Either<E, A>
immediately. This method is not available yet in Arrow Fx Coroutines, but would be a welcomed contribution 🙂
👍 2
❤️ 2
k
Thanks Simon!
😘 1