Skip to content

Instantly share code, notes, and snippets.

@ShahOdin
Created January 29, 2020 20:50
Show Gist options
  • Save ShahOdin/cd2870492e7574ec5e801950fc603c34 to your computer and use it in GitHub Desktop.
Save ShahOdin/cd2870492e7574ec5e801950fc603c34 to your computer and use it in GitHub Desktop.
lifts Java Future to generic F using cats
import java.util.concurrent.Future
import cats.Applicative
import cats.effect.{Concurrent, Sync, Timer}
import cats.effect.concurrent.Deferred
import fs2.Stream
import cats.syntax.flatMap._
import cats.syntax.functor._
import scala.concurrent.duration.FiniteDuration
package object convertors {
type JFuture[A] = java.util.concurrent.Future[A]
implicit class JFutureOps[A](value: JFuture[A]) {
private def jFutureToF[F[_] : Timer : Concurrent](fa: F[JFuture[A]])(
signal: Deferred[F, Either[Throwable, Unit]],
pollInterval: FiniteDuration): F[A] = {
def pollUntilSucceeds(future: Future[A]): F[Unit] =
Stream.awakeEvery[F](pollInterval)
.evalMap(_ => if (future.isDone) signal.complete(Right(())) else Applicative[F].unit)
.repeat
.interruptWhen(signal.get)
.compile.drain
for {
future <- fa
_ <- pollUntilSucceeds(future)
effect <- Sync[F].delay(future.get())
} yield effect
}
def liftTo[F[_] : Timer : Concurrent](pollInterval: FiniteDuration): F[A] = for {
signal <- Deferred[F, Either[Throwable, Unit]]
fa = Sync[F].delay(value)
ioa <- jFutureToF(fa)(signal, pollInterval)
} yield ioa
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment