cats.effect.ExitCase Scala Examples
The following examples show how to use cats.effect.ExitCase.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example.
Example 1
Source File: TaskInstances.scala From shims with Apache License 2.0 | 5 votes |
package shims.effect.instances import cats.{Applicative, Monad, Parallel, StackSafeMonad, ~>} import cats.effect.{Effect, ExitCase, IO, SyncIO} import scalaz.{Tag, -\/, \/, \/-} import scalaz.concurrent.Task.ParallelTask import scalaz.concurrent.{Future, Task} import shims.conversions.MonadErrorConversions import java.util.concurrent.atomic.AtomicBoolean import scala.util.control.NonFatal trait TaskInstances extends MonadErrorConversions { // cribbed from quasar, where it was mostly cribbed from scalaz-task-effect implicit object taskEffect extends Effect[Task] with StackSafeMonad[Task] { def pure[A](x: A): Task[A] = Task.now(x) def handleErrorWith[A](fa: Task[A])(f: Throwable => Task[A]): Task[A] = fa.handleWith(functionToPartial(f)) def raiseError[A](e: Throwable): Task[A] = Task.fail(e) // In order to comply with `repeatedCallbackIgnored` law // on async, a custom AtomicBoolean is required to ignore // second callbacks. def async[A](k: (Either[Throwable, A] => Unit) => Unit): Task[A] = Task.async { registered => val a = new AtomicBoolean(true) try k(e => if (a.getAndSet(false)) registered(\/.fromEither(e)) else ()) catch { case NonFatal(t) => registered(-\/(t)) } } def asyncF[A](k: (Either[Throwable, A] => Unit) => Task[Unit]): Task[A] = async(k.andThen(_.unsafePerformAsync(forget))) // emulates using attempt def bracketCase[A, B](acquire: Task[A])(use: A => Task[B])(release: (A, ExitCase[Throwable]) => Task[Unit]): Task[B] = { for { a <- acquire bOr <- use(a).attempt ec = bOr.fold(ExitCase.Error(_), _ => ExitCase.Completed) _ <- release(a, ec) b <- bOr.fold(Task.fail, Task.now) } yield b } def runAsync[A](fa: Task[A])(cb: Either[Throwable, A] => IO[Unit]): SyncIO[Unit] = SyncIO { fa unsafePerformAsync { disjunction => cb(disjunction.toEither).unsafeRunAsync(forget) } } def runSyncStep[A](fa: Task[A]): IO[Either[Task[A], A]] = IO { fa.get match { case Future.Now(-\/(_)) => Left(fa) case other => other.step match { case Future.Now(\/-(a)) => Right(a) case other => Left(new Task(other)) } } } override def map[A, B](fa: Task[A])(f: A => B): Task[B] = fa.map(f) def flatMap[A, B](fa: Task[A])(f: A => Task[B]): Task[B] = fa.flatMap(f) override def delay[A](thunk: => A): Task[A] = Task.delay(thunk) def suspend[A](thunk: => Task[A]): Task[A] = Task.suspend(thunk) } implicit val taskParallel: Parallel.Aux[Task, ParallelTask] = new Parallel[Task] { import Task.taskParallelApplicativeInstance type F[A] = ParallelTask[A] val monad: Monad[Task] = taskEffect val applicative: Applicative[ParallelTask] = Applicative[ParallelTask] val sequential: ParallelTask ~> Task = λ[ParallelTask ~> Task](Tag.unwrap(_)) val parallel: Task ~> ParallelTask = λ[Task ~> ParallelTask](Tag(_)) } private def functionToPartial[A, B](f: A => B): PartialFunction[A, B] = { case a => f(a) } private def forget[A](x: A): Unit = () }
Example 2
Source File: RerunnableInstances.scala From catbird with Apache License 2.0 | 5 votes |
package io.catbird.util.effect import cats.effect.{ Effect, ExitCase, IO, SyncIO } import com.twitter.util.{ Future, Monitor, 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) 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] 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] 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.handle(Monitor.catcher).flatMap(_ => future) case Throw(err) => release(a, ExitCase.error(err)).run.handle(Monitor.catcher).flatMap(_ => future) } } } } }
Example 3
Source File: ExpiryServiceTest.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal.eventual.cassandra import java.time.{Instant, LocalDate, ZoneOffset} import cats.effect.ExitCase import cats.implicits._ import cats.{Id, catsInstancesForId} import com.evolutiongaming.kafka.journal.ExpireAfter import com.evolutiongaming.kafka.journal.ExpireAfter.implicits._ import com.evolutiongaming.kafka.journal.eventual.cassandra.ExpireOn.implicits._ import com.evolutiongaming.kafka.journal.eventual.cassandra.ExpiryService.Action import com.evolutiongaming.kafka.journal.util.BracketFromMonad import org.scalatest.FunSuite import org.scalatest.matchers.should.Matchers import scala.concurrent.duration._ import scala.util.control.NonFatal class ExpiryServiceTest extends FunSuite with Matchers { import ExpiryServiceTest._ test("expireOn") { val expireAfter = 1.day.toExpireAfter val expected = LocalDate.of(2019, 12, 12).toExpireOn expireService.expireOn(expireAfter, timestamp) shouldEqual expected } for { (expiry, expireAfter, action) <- List( ( none[Expiry], 1.minute.toExpireAfter.some, Action.update(Expiry( 1.minute.toExpireAfter, LocalDate.of(2019, 12, 11).toExpireOn))), ( none[Expiry], 1.day.toExpireAfter.some, Action.update(Expiry( 1.day.toExpireAfter, LocalDate.of(2019, 12, 12).toExpireOn))), ( Expiry( 1.day.toExpireAfter, LocalDate.of(2019, 12, 11).toExpireOn).some, 1.day.toExpireAfter.some, Action.update(Expiry( 1.day.toExpireAfter, LocalDate.of(2019, 12, 12).toExpireOn))), ( Expiry( 1.day.toExpireAfter, LocalDate.of(2019, 12, 12).toExpireOn).some, 1.day.toExpireAfter.some, Action.ignore), ( Expiry( 1.day.toExpireAfter, LocalDate.of(2019, 12, 12).toExpireOn).some, none[ExpireAfter], Action.remove)) } yield { test(s"action expiry: $expiry, expireAfter: $expireAfter, action: $action") { expireService.action(expiry, expireAfter, timestamp) shouldEqual action } } } object ExpiryServiceTest { implicit val bracketId: BracketFromMonad[Id, Throwable] = new BracketFromMonad[Id, Throwable] { def F = catsInstancesForId def bracketCase[A, B](acquire: Id[A])(use: A => Id[B])(release: (A, ExitCase[Throwable]) => Id[Unit]) = { flatMap(acquire) { a => try { val b = use(a) try release(a, ExitCase.Completed) catch { case NonFatal(_) => } b } catch { case NonFatal(e) => release(a, ExitCase.Error(e)) raiseError(e) } } } def raiseError[A](a: Throwable) = throw a def handleErrorWith[A](fa: Id[A])(f: Throwable => Id[A]) = fa } val timestamp: Instant = Instant.parse("2019-12-11T10:10:10.00Z") val zoneId: ZoneOffset = ZoneOffset.UTC val expireService: ExpiryService[Id] = ExpiryService[Id](zoneId) }
Example 4
Source File: TestSync.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal.util import cats.Monad import cats.effect.{ExitCase, Sync} import scala.util.control.NonFatal object TestSync { def apply[F[_]](implicit F: Monad[F]): Sync[F] = new Sync[F] { def suspend[A](thunk: => F[A]) = thunk def bracketCase[A, B](acquire: F[A])(use: A => F[B])(release: (A, ExitCase[Throwable]) => F[Unit]) = { flatMap(acquire) { a => try { val b = use(a) try release(a, ExitCase.Completed) catch { case NonFatal(_) => } b } catch { case NonFatal(e) => release(a, ExitCase.Error(e)) raiseError(e) } } } def raiseError[A](e: Throwable) = throw e def handleErrorWith[A](fa: F[A])(f: Throwable => F[A]) = try fa catch { case NonFatal(e) => f(e) } def flatMap[A, B](fa: F[A])(f: A => F[B]) = F.flatMap(fa)(f) def tailRecM[A, B](a: A)(f: A => F[Either[A, B]]) = F.tailRecM(a)(f) def pure[A](a: A) = F.pure(a) } }
Example 5
Source File: ConditionalLogger.scala From odin with Apache License 2.0 | 5 votes |
package io.odin.extras.loggers import cats.MonadError import cats.effect.{Concurrent, ContextShift, ExitCase, Resource, Timer} import cats.syntax.applicativeError._ import cats.syntax.flatMap._ import cats.syntax.functor._ import cats.syntax.order._ import io.odin.loggers.DefaultLogger import io.odin.{Level, Logger, LoggerMessage} import monix.catnap.ConcurrentQueue import monix.execution.{BufferCapacity, ChannelType} final case class ConditionalLogger[F[_]: Timer] private ( queue: ConcurrentQueue[F, LoggerMessage], inner: Logger[F], override val minLevel: Level )(implicit F: MonadError[F, Throwable]) extends DefaultLogger[F](minLevel) { def log(msg: LoggerMessage): F[Unit] = queue.tryOffer(msg).void private def drain(exitCase: ExitCase[Throwable]): F[Unit] = { val level = exitCase match { case ExitCase.Completed => inner.minLevel case _ => minLevel } queue .drain(0, Int.MaxValue) .flatMap(msgs => inner.log(msgs.filter(_.level >= level).toList)) .attempt .void } } object ConditionalLogger { def create[F[_]: Timer: Concurrent: ContextShift]( inner: Logger[F], minLevelOnError: Level, maxBufferSize: Option[Int] ): Resource[F, Logger[F]] = { val queueCapacity = maxBufferSize match { case Some(value) => BufferCapacity.Bounded(value) case None => BufferCapacity.Unbounded() } def acquire: F[ConditionalLogger[F]] = for { queue <- ConcurrentQueue.withConfig[F, LoggerMessage](queueCapacity, ChannelType.MPSC) } yield ConditionalLogger(queue, inner, minLevelOnError) def release(logger: ConditionalLogger[F], exitCase: ExitCase[Throwable]): F[Unit] = logger.drain(exitCase) Resource.makeCase(acquire)(release).widen } }
Example 6
Source File: KafkaDistributedProcessingTest.scala From aecor with MIT License | 5 votes |
package aecor.kafkadistributedprocessing import cats.effect.concurrent.{ Deferred, Ref } import cats.effect.{ ExitCase, IO } import cats.implicits._ import fs2.concurrent.Queue import org.apache.kafka.clients.consumer.ConsumerConfig import org.scalatest.funsuite.AnyFunSuiteLike import scala.concurrent.duration._ class KafkaDistributedProcessingTest extends AnyFunSuiteLike with KafkaSupport with IOSupport { val topicName = "process-distribution" createCustomTopic(topicName, partitions = 4) val settings = DistributedProcessingSettings(Set(s"localhost:${kafkaConfig.kafkaPort}"), topicName) test("Process error propagation") { val exception = new RuntimeException("Oops!") val result = DistributedProcessing(settings) .start("Process error propagation", List(IO.raiseError[Unit](exception))) .attempt .timeout(20.seconds) .unsafeRunSync() assert(result == Left(exception)) } test("Process lifecycle") { val test = Ref.of[IO, (Boolean, Boolean)]((false, false)).flatMap { ref => Deferred[IO, Unit] .flatMap { done => val process = ref.set((true, false)) >> done.complete(()) >> IO.never.guaranteeCase { case ExitCase.Canceled => ref.set((true, true)) case _ => IO.unit }.void val run = DistributedProcessing(settings) .start("Process lifecycle", List(process)) IO.race(run, done.get) >> ref.get } } val (started, finished) = test.timeout(20.seconds).unsafeRunSync() assert(started) assert(finished) } test("Process distribution") { val test = Queue.unbounded[IO, Int].flatMap { queue => def run(client: Int) = DistributedProcessing( settings.withConsumerSetting(ConsumerConfig.CLIENT_ID_CONFIG, client.toString) ).start( "Process distribution", Stream .from(0) .take(8) .map { n => val idx = client * 10 + n (queue.enqueue1(idx) >> IO.cancelBoundary <* IO.never) .guarantee(queue.enqueue1(-idx)) } .toList ) def dequeue(size: Long): IO[List[Int]] = queue.dequeue.take(size).compile.to[List] for { d1 <- run(1).start s1 <- dequeue(8) d2 <- run(2).start s2 <- dequeue(16) _ <- d1.cancel s3 <- dequeue(16) _ <- d2.cancel s4 <- dequeue(8) } yield (s1, s2, s3, s4) } val (s1, s2, s3, s4) = test.timeout(20.seconds).unsafeRunSync() assert(s1.toSet == Set(10, 11, 12, 13, 14, 15, 16, 17)) assert((s1 ++ s2 ++ s3 ++ s4).sum == 0) } }
Example 7
Source File: Memoize.scala From tofu with Apache License 2.0 | 5 votes |
package tofu.memo import cats.effect.{Concurrent, ExitCase} import cats.effect.concurrent.{Deferred, Ref} import simulacrum.typeclass import tofu.syntax.monadic._ import cats.syntax.option._ import cats.effect.syntax.concurrent._ import cats.effect.syntax.bracket._ def memoizeOnSuccess[A](fa: F[A]): F[F[A]] } object Memoize { def concurrentMemoize[F[_]](implicit F: Concurrent[F]): Memoize[F] = new Memoize[F] { def memoize[A](fa: F[A]): F[F[A]] = Concurrent.memoize(fa) //copy of Concurrent.memoize accepting success only def memoizeOnSuccess[A](f: F[A]): F[F[A]] = { { sealed trait State case class Subs(n: Int) extends State case object Done extends State case class Fetch(state: State, v: Deferred[F, A], stop: Deferred[F, F[Unit]]) Ref[F].of(Option.empty[Fetch]).map { state => (Deferred[F, A] product Deferred[F, F[Unit]]).flatMap { case (v, stop) => def endState(ec: ExitCase[Throwable]) = state.modify { case None => throw new AssertionError("unreachable") case s @ Some(Fetch(Done, _, _)) => s -> F.unit case Some(Fetch(Subs(n), v, stop)) => if (ec == ExitCase.Canceled && n == 1) None -> stop.get.flatten else if (ec == ExitCase.Canceled) Fetch(Subs(n - 1), v, stop).some -> F.unit else Fetch(Done, v, stop).some -> F.unit }.flatten def fetch = f.flatMap(v.complete) .start .flatMap(fiber => stop.complete(fiber.cancel)) state.modify { case s @ Some(Fetch(Done, v, _)) => s -> v.get case Some(Fetch(Subs(n), v, stop)) => Fetch(Subs(n + 1), v, stop).some -> v.get.guaranteeCase(endState) case None => Fetch(Subs(1), v, stop).some -> fetch.bracketCase(_ => v.get) { case (_, ec) => endState(ec) } }.flatten } } } } } }
Example 8
Source File: Exit.scala From tofu with Apache License 2.0 | 5 votes |
package tofu.concurrent import cats.{Applicative, Eval, Traverse} import cats.effect.ExitCase import tofu.control.ApplicativeZip import tofu.syntax.monadic._ sealed trait Exit[+E, +A] { def exitCase: ExitCase[E] } object Exit { sealed trait Incomplete[+E] extends Exit[E, Nothing] case object Canceled extends Incomplete[Nothing] { def exitCase = ExitCase.Canceled } final case class Error[+E](e: E) extends Incomplete[E] { def exitCase = ExitCase.Error(e) } final case class Completed[+A](a: A) extends Exit[Nothing, A] { override def exitCase = ExitCase.Completed } private[this] object exitInstanceAny extends Traverse[Exit[Any, *]] with ApplicativeZip[Exit[Any, *]] { def traverse[G[_], A, B](fa: Exit[Any, A])(f: A => G[B])(implicit G: Applicative[G]): G[Exit[Any, B]] = fa match { case Canceled => G.pure(Canceled) case Error(e) => G.pure(Error(e)) case Completed(a) => f(a).map(Completed(_)) } def foldLeft[A, B](fa: Exit[Any, A], b: B)(f: (B, A) => B): B = fa match { case Canceled | Error(_) => b case Completed(a) => f(b, a) } def foldRight[A, B](fa: Exit[Any, A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] = fa match { case Canceled | Error(_) => lb case Completed(a) => f(a, lb) } override def map[A, B](fa: Exit[Any, A])(f: A => B): Exit[Any, B] = fa match { case Canceled => Canceled case e: Error[Any] => e case Completed(a) => Completed(f(a)) } def zipWith[A, B, C](fa: Exit[Any, A], fb: Exit[Any, B])(f: (A, B) => C): Exit[Any, C] = fa match { case Canceled => Canceled case err: Error[Any] => err case Completed(a) => fb match { case Canceled => Canceled case err: Error[Any] => err case Completed(b) => Completed(f(a, b)) } } def pure[A](x: A): Exit[Any, A] = Completed(x) } implicit def exitInstance[E]: Traverse[Exit[E, *]] with Applicative[Exit[E, *]] = exitInstanceAny.asInstanceOf[Traverse[Exit[E, *]] with Applicative[Exit[E, *]]] }
Example 9
Source File: Guarantee.scala From tofu with Apache License 2.0 | 5 votes |
package tofu import cats.effect.{Bracket, ExitCase} def finallyCase[A, B, C](init: F[A])(action: A => F[B])(release: (A, Exit[B]) => F[C]): F[B] } object Finally extends FinallyInstanceChain[Finally] trait FinallyInstanceChain[T[f[_], exit[_]] >: Finally[f, exit]] { final implicit def fromBracket[F[_], E](implicit F: Bracket[F, E]): T[F, TConst[ExitCase[E], *]] = new Finally[F, TConst[ExitCase[E], *]] { def finallyCase[A, B, C](init: F[A])(action: A => F[B])(release: (A, ExitCase[E]) => F[C]): F[B] = F.bracketCase(init)(action) { case (a, exit) => F.void(release(a, exit)) } def bracket[A, B, C](init: F[A])(action: A => F[B])(release: (A, Boolean) => F[C]): F[B] = F.bracketCase(init)(action) { case (a, ExitCase.Completed) => F.void(release(a, true)) case (a, _) => F.void(release(a, false)) } } }
Example 10
Source File: unlift.scala From tofu with Apache License 2.0 | 5 votes |
package tofu.syntax import cats.effect.{CancelToken, ConcurrentEffect, Effect, ExitCase, Fiber, IO, SyncIO} import cats.{FlatMap, Functor, ~>} import tofu.lift.Unlift object unlift { implicit final class UnliftEffectOps[F[_], G[_]](private val U: Unlift[F, G]) extends AnyVal { def effect(implicit G: Functor[G], E: Effect[F]): G[Effect[G]] = G.map(U.unlift) { unliftF => new EffectInstance[F, G] { def toG: F ~> G = U.liftF def toF: G ~> F = unliftF implicit def F: Effect[F] = E } } def effectWith[A](f: Effect[G] => G[A])(implicit G: FlatMap[G], E: Effect[F]): G[A] = G.flatMap(U.unlift) { unliftF => val eff = new EffectInstance[F, G] { def toG: F ~> G = U.liftF def toF: G ~> F = unliftF implicit def F: Effect[F] = E } f(eff) } def concurrentEffect(implicit G: Functor[G], CE: ConcurrentEffect[F]): G[ConcurrentEffect[G]] = G.map(U.unlift) { unliftF => new ConcurrentEffectInstance[F, G] { def toG: F ~> G = U.liftF def toF: G ~> F = unliftF implicit def F: ConcurrentEffect[F] = CE } } def concurrentEffectWith[A](f: ConcurrentEffect[G] => G[A])(implicit G: FlatMap[G], CE: ConcurrentEffect[F]): G[A] = G.flatMap(U.unlift) { unliftF => val ce = new ConcurrentEffectInstance[F, G] { def toG: F ~> G = U.liftF def toF: G ~> F = unliftF implicit def F: ConcurrentEffect[F] = CE } f(ce) } } private[unlift] trait EffectInstance[F[_], G[_]] extends Effect[G] { def toG: F ~> G def toF: G ~> F implicit def F: Effect[F] def pure[A](x: A): G[A] = toG(F.pure(x)) def flatMap[A, B](ga: G[A])(f: A => G[B]): G[B] = toG(F.flatMap(toF(ga))(a => toF(f(a)))) def tailRecM[A, B](a: A)(f: A => G[Either[A, B]]): G[B] = toG(F.tailRecM(a)(a => toF(f(a)))) def raiseError[A](e: Throwable): G[A] = toG(F.raiseError(e)) def handleErrorWith[A](ga: G[A])(f: Throwable => G[A]): G[A] = toG(F.handleErrorWith(toF(ga))(t => toF(f(t)))) def bracketCase[A, B](acquire: G[A])(use: A => G[B])(release: (A, ExitCase[Throwable]) => G[Unit]): G[B] = toG(F.bracketCase(toF(acquire))(a => toF(use(a)))((a, e) => toF(release(a, e)))) def suspend[A](thunk: => G[A]): G[A] = toG(F.suspend(toF(thunk))) def async[A](k: (Either[Throwable, A] => Unit) => Unit): G[A] = toG(F.async(k)) def asyncF[A](k: (Either[Throwable, A] => Unit) => G[Unit]): G[A] = toG(F.asyncF[A](cb => toF(k(cb)))) def runAsync[A](ga: G[A])(cb: Either[Throwable, A] => IO[Unit]): SyncIO[Unit] = F.runAsync(toF(ga))(cb) } private[unlift] trait ConcurrentEffectInstance[F[_], G[_]] extends EffectInstance[F, G] with ConcurrentEffect[G] { implicit def F: ConcurrentEffect[F] def start[A](ga: G[A]): G[Fiber[G, A]] = toG(F.map(F.start(toF(ga)))(_.mapK(toG))) def racePair[A, B](ga: G[A], gb: G[B]): G[Either[(A, Fiber[G, B]), (Fiber[G, A], B)]] = toG(F.map(F.racePair(toF(ga), toF(gb))) { case Left((a, fb)) => Left((a, fb.mapK(toG))) case Right((fa, b)) => Right((fa.mapK(toG), b)) }) def runCancelable[A](ga: G[A])(cb: Either[Throwable, A] => IO[Unit]): SyncIO[CancelToken[G]] = F.runCancelable(toF(ga))(cb).map(toG(_)) } }
Example 11
Source File: Monix.scala From neotypes with MIT License | 5 votes |
package neotypes.monix import cats.effect.{ExitCase, Resource} import monix.eval.Task trait Monix { implicit final def monixAsync: neotypes.Async.Aux[Task, Monix.TaskResource] = Monix.instance } object Monix { private[neotypes] final type TaskResource[A] = Resource[Task, A] private final val instance: neotypes.Async.Aux[Task, TaskResource] = new neotypes.Async[Task] { override final type R[A] = Resource[Task, A] override final def async[T](cb: (Either[Throwable, T] => Unit) => Unit): Task[T] = Task.async(cb) override final def delay[A](t: => A): Task[A] = Task.delay(t) override final def failed[T](e: Throwable): Task[T] = Task.raiseError(e) override final def flatMap[T, U](m: Task[T])(f: T => Task[U]): Task[U] = m.flatMap(f) override final def guarantee[A, B](fa: Task[A]) (f: A => Task[B]) (finalizer: (A, Option[Throwable]) => Task[Unit]): Task[B] = Resource.makeCase(fa) { case (a, ExitCase.Completed | ExitCase.Canceled) => finalizer(a, None) case (a, ExitCase.Error(ex)) => finalizer(a, Some(ex)) }.use(f) override final def map[T, U](m: Task[T])(f: T => U): Task[U] = m.map(f) override final def recoverWith[T, U >: T](m: Task[T])(f: PartialFunction[Throwable, Task[U]]): Task[U] = m.onErrorRecoverWith(f) override final def resource[A](input: => A)(close: A => Task[Unit]): Resource[Task, A] = Resource.make(Task.delay(input))(close) } }
Example 12
Source File: BracketSyntax.scala From cats-effect with Apache License 2.0 | 5 votes |
package cats.effect.syntax import cats.effect.{Bracket, ExitCase} trait BracketSyntax { implicit def catsEffectSyntaxBracket[F[_], A, E](fa: F[A])(implicit bracket: Bracket[F, E]): BracketOps[F, E, A] = { // Bracket instance here is required to ensure correct inference for E val _ = bracket new BracketOps[F, E, A](fa) } } final class BracketOps[F[_], E, A](val self: F[A]) extends AnyVal { def bracketCase[B](use: A => F[B])(release: (A, ExitCase[E]) => F[Unit])(implicit F: Bracket[F, E]): F[B] = F.bracketCase(self)(use)(release) def bracket[B](use: A => F[B])(release: A => F[Unit])(implicit F: Bracket[F, E]): F[B] = F.bracket(self)(use)(release) def guarantee(finalizer: F[Unit])(implicit F: Bracket[F, E]): F[A] = F.guarantee(self)(finalizer) def guaranteeCase(finalizer: ExitCase[E] => F[Unit])(implicit F: Bracket[F, E]): F[A] = F.guaranteeCase(self)(finalizer) def uncancelable(implicit F: Bracket[F, E]): F[A] = F.uncancelable(self) def onCancel(finalizer: F[Unit])(implicit F: Bracket[F, E]): F[A] = F.onCancel(self)(finalizer) }
Example 13
Source File: monix.scala From sangria-monix with Apache License 2.0 | 5 votes |
package sangria.streaming import scala.language.higherKinds import _root_.monix.execution.Scheduler import _root_.monix.reactive._ import _root_.monix.eval.Task import cats.effect.ExitCase import scala.concurrent.Future object monix { class ObservableSubscriptionStream(implicit scheduler: Scheduler) extends SubscriptionStream[Observable] { def supported[T[_]](other: SubscriptionStream[T]) = other.isInstanceOf[ObservableSubscriptionStream] def map[A, B](source: Observable[A])(fn: A => B) = source.map(fn) def singleFuture[T](value: Future[T]) = Observable.fromFuture(value) def single[T](value: T) = Observable(value) def mapFuture[A, B](source: Observable[A])(fn: A => Future[B]) = source.mergeMap(a => Observable.fromFuture(fn(a))) def first[T](s: Observable[T]) = s.firstOrElseL(throw new IllegalStateException("Promise was not completed - observable haven't produced any elements.")).runToFuture def failed[T](e: Throwable) = Observable.raiseError(e) def onComplete[Ctx, Res](result: Observable[Res])(op: => Unit) = result.guaranteeCase { case ExitCase.Error(e) => Task(op) case _ => Task(op) } def flatMapFuture[Ctx, Res, T](future: Future[T])(resultFn: T => Observable[Res]) = Observable.fromFuture(future).mergeMap(resultFn) def merge[T](streams: Vector[Observable[T]]) = if (streams.nonEmpty) Observable(streams: _*).merge else throw new IllegalStateException("No streams produced!") def recover[T](stream: Observable[T])(fn: Throwable => T) = stream onErrorRecover {case e => fn(e)} } implicit def observableSubscriptionStream(implicit scheduler: Scheduler): SubscriptionStream[Observable] = new ObservableSubscriptionStream }
Example 14
Source File: package.scala From interop-cats with Apache License 2.0 | 5 votes |
package zio import cats.effect.{ Effect, ExitCase, LiftIO } import zio.interop.catz.taskEffectInstance package object interop { type ParIO[-R, +E, +A] = Par.T[R, E, A] type Queue[F[+_], A] = CQueue[F, A, A] @inline private[interop] final def exitToExitCase(exit: Exit[Any, Any]): ExitCase[Throwable] = exit match { case Exit.Success(_) => ExitCase.Completed case Exit.Failure(cause) if cause.interrupted => ExitCase.Canceled case Exit.Failure(cause) => cause.failureOrCause match { case Left(t: Throwable) => ExitCase.Error(t) case _ => ExitCase.Error(FiberFailure(cause)) } } @inline private[interop] final def exitCaseToExit[E](exitCase: ExitCase[E]): Exit[E, Unit] = exitCase match { case ExitCase.Completed => Exit.unit case ExitCase.Error(e) => Exit.fail(e) case ExitCase.Canceled => Exit.interrupt(Fiber.Id.None) } private[interop] def fromEffect[F[+_], R, A]( eff: F[A] )(implicit R: Runtime[R], F: Effect[F]): RIO[R, A] = taskEffectInstance.liftIO[A](F.toIO(eff)) private[interop] def toEffect[F[+_], R, A](zio: RIO[R, A])(implicit R: Runtime[R], F: LiftIO[F]): F[A] = F.liftIO(taskEffectInstance.toIO(zio)) }