zio / interop-guava

https://zio.dev/zio-interop-guava
Apache License 2.0
6 stars 7 forks source link

Add wrapper for ApiFuture? #463

Open fancywriter opened 9 months ago

fancywriter commented 9 months ago

I don't have good understanding why google decided to add yet another future interface (seems it's the same listenable future under the hood) https://cloud.google.com/java/docs/reference/api-common/latest/com.google.api.core.ApiFutures Would be nice to have transparent wrapper for this too...

sideeffffect commented 9 months ago

https://cloud.google.com/java/docs/reference/api-common/latest/com.google.api.core.ApiFuture

A Future that can have a listener added.

Similar to Guava's ListenableFuture, but redeclared so that Guava could be shaded.

sideeffffect commented 9 months ago

@fancywriter what are the Maven coordinates of the JAR that contains this interface?

fancywriter commented 9 months ago

@sideeffffect this one https://mvnrepository.com/artifact/com.google.api/api-common

This is my naive implementation

import com.google.api.core.{ApiFuture, ApiFutureCallback, ApiFutures}
import zio.{Task, ZIO}

object ZIOCompat {
  def fromApiFuture[V](future: => ApiFuture[V]): Task[V] =
    ZIO.executor.flatMap(executor =>
      ZIO.async[Any, Throwable, V] { cb =>
        ApiFutures.addCallback(
          future,
          new ApiFutureCallback[V] {
            def onFailure(t: Throwable): Unit = cb(ZIO.fail(t))
            def onSuccess(v: V): Unit = cb(ZIO.succeed(v))
          },
          executor.asJava
        )
      }
    )
}

extension[V] (future: => ApiFuture[V]) {
  def toZIO: Task[V] = ZIOCompat.fromApiFuture(future)
}

I may not covered all corner cases like cancellation, didn't dig too much there.