Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
val catsVersion = "2.6.0"
val catsEffectVersion = "2.5.0"
val catsEffectVersion = "3.1.0"
val utilVersion = "21.2.0"
val finagleVersion = "21.2.0"

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package io.catbird.util.effect

import cats.effect.{ Bracket, ExitCase }
import cats.effect.ExitCase
import com.twitter.util.{ Future, Monitor }
import io.catbird.util.FutureMonadError
import java.lang.Throwable
import scala.Unit
import cats.effect.MonadCancel

trait FutureInstances {
implicit final val futureBracketInstance: Bracket[Future, Throwable] =
new FutureMonadError with Bracket[Future, Throwable] {
implicit final val futureBracketInstance: MonadCancel[Future, Throwable] =
new FutureMonadError with MonadCancel[Future, Throwable] {
final def bracketCase[A, B](acquire: Future[A])(use: A => Future[B])(
release: (A, ExitCase[Throwable]) => Future[Unit]
): Future[B] =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.catbird.util.effect

import cats.effect.ContextShift
import com.twitter.util.{ Future, FuturePool, Promise }
import io.catbird.util.Rerunnable

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package io.catbird.util.effect

import cats.effect.{ Clock, Timer }
import cats.effect.Clock
import io.catbird.util.Rerunnable
import com.twitter.util.Future
import com.twitter.util
import scala.Unit

import scala.concurrent.duration.FiniteDuration
import cats.effect.Temporal

/**
* Can be used to construct a `cats.effect.Timer` instance for `Rerunnable` which let's you delay execution or
Expand Down Expand Up @@ -35,7 +36,7 @@ object RerunnableTimer {
}
}

final private[effect] class RerunnableTimer private (implicit underlyingTimer: util.Timer) extends Timer[Rerunnable] {
final private[effect] class RerunnableTimer private (implicit underlyingTimer: util.Timer) extends Temporal[Rerunnable] {

override val clock: Clock[Rerunnable] = RerunnableClock()

Expand Down
11 changes: 6 additions & 5 deletions effect/src/main/scala/io/catbird/util/effect/package.scala
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
package io.catbird.util

import cats.effect.{ Async, ContextShift, ExitCase, IO }
import cats.effect.{ Async, ExitCase, IO }
import com.twitter.util.{ Future, Return, Throw, Try }
import java.lang.Throwable

import scala.util.{ Left, Right }
import cats.effect.Spawn

package object effect extends FutureInstances with RerunnableInstances {

/**
* Converts the `Future` to `F` without changing the underlying execution (same thread pool!).
*/
def futureToAsync[F[_], A](fa: => Future[A])(implicit F: Async[F]): F[A] = F.async { k =>
def futureToAsync[F[_], A](fa: => Future[A])(implicit F: Async[F]): F[A] = F.async_ { k =>
fa.respond {
case Return(a) => k(Right[Throwable, A](a))
case Throw(err) => k(Left[Throwable, A](err))
Expand All @@ -26,8 +27,8 @@ package object effect extends FutureInstances with RerunnableInstances {
* the `Future` is running on a thread pool controlled by the library (e.g. the underlying Netty pool).
* It also is closer to the behavior of `IO.fromFuture` for Scala futures which also shifts back.
*/
def futureToAsyncAndShift[F[_], A](fa: => Future[A])(implicit F: Async[F], CS: ContextShift[F]): F[A] =
F.guarantee(futureToAsync[F, A](fa))(CS.shift)
def futureToAsyncAndShift[F[_], A](fa: => Future[A])(implicit F: Async[F]): F[A] =
F.guarantee(futureToAsync[F, A](fa), Spawn[F].cede)

/**
* Converts the `Rerunnable` to `F` without changing the underlying execution (same thread pool!).
Expand All @@ -39,7 +40,7 @@ package object effect extends FutureInstances with RerunnableInstances {
* The same as `rerunnableToIO` but doesn't stay on the thread pool of the `Rerunnable` and instead shifts execution
* back to the one provided by `ContextShift[F]` (which is usually the default one).
*/
final def rerunnableToIOAndShift[A](fa: Rerunnable[A])(implicit CS: ContextShift[IO]): IO[A] =
final def rerunnableToIOAndShift[A](fa: Rerunnable[A]): IO[A] =
futureToAsyncAndShift[IO, A](fa.run)

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.catbird.util.effect

import cats.effect.{ ContextShift, IO }
import cats.effect.IO
import com.twitter.util.{ ExecutorServiceFuturePool, Future, FuturePool }
import org.scalatest.Outcome
import org.scalatest.funsuite.FixtureAnyFunSuite
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.catbird.util.effect

import cats.effect.{ ContextShift, IO, Sync }
import cats.effect.{ IO, Sync }
import com.twitter.util.{ Await, Future, FuturePool }
import io.catbird.util.Rerunnable
import org.scalatest.Outcome
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package io.catbird.util.effect
import cats.effect.laws.discipline.EffectTests
import cats.effect.laws.discipline.arbitrary.catsEffectLawsArbitraryForIO
import cats.effect.laws.util.{ TestContext, TestInstances }
import cats.effect.{ Bracket, IO }
import cats.effect.IO
import cats.instances.either._
import cats.instances.int._
import cats.instances.tuple._
Expand All @@ -15,6 +15,7 @@ import io.catbird.util.{ ArbitraryInstances, Rerunnable }
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.prop.Configuration
import org.typelevel.discipline.scalatest.FunSuiteDiscipline
import cats.effect.MonadCancel

class RerunnableSuite
extends AnyFunSuite
Expand All @@ -35,7 +36,7 @@ class RerunnableSuite
var monitoredException: Throwable = null
val monitor = Monitor.mk { case e => monitoredException = e; true; }

val rerunnable = Bracket[Rerunnable, Throwable]
val rerunnable = MonadCancel[Rerunnable, Throwable]
.bracket(Rerunnable.Unit)(_ => Rerunnable.raiseError(useException))(_ => Rerunnable.raiseError(releaseException))
.liftToTry

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package io.catbird.util.effect

import cats.effect.Timer
import org.scalatest.Outcome
import org.scalatest.funsuite.FixtureAnyFunSuite
import com.twitter.util
import com.twitter.util.{ Await, Future }
import io.catbird.util.Rerunnable

import scala.concurrent.duration._
import cats.effect.Temporal

class RerunnableTimerSuite extends FixtureAnyFunSuite {

Expand All @@ -16,13 +16,13 @@ class RerunnableTimerSuite extends FixtureAnyFunSuite {
}

test("A timer can be used to delay execution") { f =>
implicit val timer: Timer[Rerunnable] = RerunnableTimer(f.twitterTimer)
implicit val timer: Temporal[Rerunnable] = RerunnableTimer(f.twitterTimer)

val result = Await.result(
Future.selectIndex(
Vector(
for {
_ <- Timer[Rerunnable].sleep(100.milliseconds).run
_ <- Temporal[Rerunnable].sleep(100.milliseconds).run
r <- Future.value("slow")
} yield r,
Future.value("fast").delayed(util.Duration.fromMilliseconds(50))(f.twitterTimer)
Expand Down