Permalink
Browse files

Fix Effect[Rerunnable] instance for cats-effect 1.0

  • Loading branch information...
travisbrown committed Sep 12, 2018
1 parent ce29d74 commit c9585610f3dce480395a13f041a838a2a580445b
@@ -1,34 +1,66 @@
package io.catbird.util.effect
import cats.effect.{ Effect, IO }
import com.twitter.util.{ Future, Promise }
import cats.effect.{ Effect, ExitCase, IO, SyncIO }
import com.twitter.util.{ Future, Promise, Return, Throw }
import io.catbird.util.{ Rerunnable, RerunnableMonadError }
import java.lang.Throwable
import scala.Unit
import scala.util.{ Either, Left, Right }
trait RerunnableInstances {
implicit final val rerunnableEffectInstance: Effect[Rerunnable] = new RerunnableMonadError with Effect[Rerunnable] {
final def suspend[A](thunk: => Rerunnable[A]): Rerunnable[A] = Rerunnable.suspend[A](thunk)
implicit final val rerunnableEffectInstance: Effect[Rerunnable] =
new RerunnableMonadError with Effect[Rerunnable] {
final def suspend[A](thunk: => Rerunnable[A]): Rerunnable[A] = Rerunnable.suspend[A](thunk)
override final def delay[A](thunk: => A): Rerunnable[A] = Rerunnable[A](thunk)
override final def delay[A](thunk: => A): Rerunnable[A] = Rerunnable[A](thunk)
final def async[A](k: (Either[Throwable, A] => Unit) => Unit): Rerunnable[A] = new Rerunnable[A] {
final def run: Future[A] = {
val promise = new Promise[A]
final def async[A](k: (Either[Throwable, A] => Unit) => Unit): Rerunnable[A] =
new Rerunnable[A] {
final def run: Future[A] = {
val promise = new Promise[A]
k { e =>
if (promise.isDefined) () else e match {
case Right(a) => promise.setValue(a)
case Left(err) => promise.setException(err)
k { e =>
if (promise.isDefined) () else e match {
case Right(a) => promise.setValue(a)
case Left(err) => promise.setException(err)
}
}
promise
}
}
final def asyncF[A](k: (Either[Throwable, A] => Unit) => Rerunnable[Unit]): Rerunnable[A] =
new Rerunnable[A] {
final def run: Future[A] = {
val promise = new Promise[A]
promise
val rerunnable = k { e =>
if (promise.isDefined) () else e match {
case Right(a) => promise.setValue(a)
case Left(err) => promise.setException(err)
}
}
rerunnable.run.flatMap(_ => promise)
}
}
final def runAsync[A](fa: Rerunnable[A])(cb: Either[Throwable, A] => IO[Unit]): SyncIO[Unit] =
rerunnableToIO[A](fa).runAsync(cb)
final def bracketCase[A, B](acquire: Rerunnable[A])(use: A => Rerunnable[B])(
release: (A, ExitCase[Throwable]) => Rerunnable[Unit]
): Rerunnable[B] = new Rerunnable[B] {
final def run: Future[B] = {
acquire.run.flatMap { a =>
val future = use(a).run
future.transform {
case Return(b) => release(a, ExitCase.complete).run.flatMap(_ => future)
case Throw(err) => release(a, ExitCase.error(err)).run.flatMap(_ => future)
}
}
}
}
}
final def runAsync[A](fa: Rerunnable[A])(cb: Either[Throwable, A] => IO[Unit]): IO[Unit] =
rerunnableToIO[A](fa).runAsync(cb)
}
}
@@ -1,21 +1,23 @@
package io.catbird.util.effect
import cats.kernel.Eq
import cats.effect.IO
import cats.effect.laws.discipline.EffectTests
import cats.effect.laws.discipline.arbitrary.catsEffectLawsArbitraryForIO
import cats.effect.laws.util.{ TestContext, TestInstances }
import cats.instances.either._
import cats.instances.int._
import cats.instances.tuple._
import cats.instances.unit._
import cats.laws.discipline.arbitrary._
import com.twitter.conversions.time._
import io.catbird.util.{ ArbitraryInstances, EqInstances, Rerunnable }
import io.catbird.util.{ ArbitraryInstances, Rerunnable }
import org.scalatest.FunSuite
import org.typelevel.discipline.scalatest.Discipline
class RerunnableSuite extends FunSuite with Discipline with ArbitraryInstances with TestInstances {
implicit val context: TestContext = TestContext()
implicit def rerunnableEq[A](implicit A: Eq[A]): Eq[Rerunnable[A]] = Rerunnable.rerunnableEqWithFailure[A](1.second)
implicit def rerunnableEq[A](implicit A: Eq[A]): Eq[Rerunnable[A]] =
Eq.by[Rerunnable[A], IO[A]](rerunnableToIO)
checkAll("Rerunnable[Int]", EffectTests[Rerunnable].effect[Int, Int, Int])
}

0 comments on commit c958561

Please sign in to comment.