cats.effect.concurrent.Deferred Scala Examples
The following examples show how to use cats.effect.concurrent.Deferred.
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: RebalanceEvents.scala From aecor with MIT License | 5 votes |
package aecor.kafkadistributedprocessing.internal import java.util import aecor.data.Committable import cats.effect.concurrent.Deferred import cats.effect.implicits._ import cats.effect.{ ConcurrentEffect, Effect } import cats.implicits._ import fs2.Stream import fs2.concurrent.Queue import org.apache.kafka.clients.consumer.ConsumerRebalanceListener import org.apache.kafka.common import org.apache.kafka.common.TopicPartition import scala.collection.JavaConverters._ private[kafkadistributedprocessing] object RebalanceEvents { final class UsePartiallyApplied[F[_]] { def subscribe[A]( f: ConsumerRebalanceListener => F[Unit] )(implicit F: ConcurrentEffect[F]): F[Stream[F, Committable[F, RebalanceEvent]]] = for { queue <- Queue.unbounded[F, Committable[F, RebalanceEvent]] listener = new Listener[F]( event => Deferred[F, Unit] .flatMap { completion => queue.enqueue1(Committable(completion.complete(()), event)) >> completion.get } ) _ <- f(listener) } yield queue.dequeue } def apply[F[_]]: UsePartiallyApplied[F] = new UsePartiallyApplied[F] sealed abstract class RebalanceEvent object RebalanceEvent { final case class PartitionsRevoked(partitions: Set[TopicPartition]) extends RebalanceEvent final case class PartitionsAssigned(partitions: Set[TopicPartition]) extends RebalanceEvent } private final class Listener[F[_]: Effect](processEvent: RebalanceEvent => F[Unit]) extends ConsumerRebalanceListener { override def onPartitionsRevoked(partitions: util.Collection[common.TopicPartition]): Unit = processEvent(RebalanceEvent.PartitionsRevoked(partitions.asScala.toSet)).toIO .unsafeRunSync() override def onPartitionsAssigned(partitions: util.Collection[common.TopicPartition]): Unit = processEvent(RebalanceEvent.PartitionsAssigned(partitions.asScala.toSet)).toIO .unsafeRunSync() } }
Example 2
Source File: ListProjector.scala From event-sourcing-kafka-streams with MIT License | 5 votes |
package org.amitayh.invoices.projector import java.util.UUID import cats.effect.concurrent.Deferred import cats.effect.{ContextShift, IO} import cats.syntax.apply._ import org.amitayh.invoices.common.Config import org.amitayh.invoices.common.domain.InvoiceSnapshot import org.amitayh.invoices.common.serde.AvroSerde.SnapshotSerde import org.amitayh.invoices.common.serde.UuidSerde import org.amitayh.invoices.dao.{InvoiceList, InvoiceRecord, MySqlInvoiceList} import org.amitayh.invoices.streamprocessor.StreamProcessorApp import org.apache.kafka.streams.kstream.{Consumed, ForeachAction, KeyValueMapper} import org.apache.kafka.streams.{KeyValue, StreamsBuilder, Topology} import scala.concurrent.ExecutionContext.global object ListProjector extends StreamProcessorApp { override def appId: String = "invoices.processor.list-projector" override def topology: Topology = ListProjectorTopology.create.unsafeRunSync() } object ListProjectorTopology { implicit val contextShift: ContextShift[IO] = IO.contextShift(global) def create: IO[Topology] = for { deferred <- Deferred[IO, Topology] _ <- MySqlInvoiceList.resource[IO].use { invoiceList => buildTopology(invoiceList).flatMap(deferred.complete) *> IO.never }.start topology <- deferred.get } yield topology private def buildTopology(invoiceList: InvoiceList[IO]): IO[Topology] = IO { val builder = new StreamsBuilder val snapshots = builder.stream( Config.Topics.Snapshots.name, Consumed.`with`(UuidSerde, SnapshotSerde)) snapshots .map[UUID, InvoiceRecord](ToRecord) .foreach(new SaveInvoiceRecord(invoiceList)) builder.build() } } object ToRecord extends KeyValueMapper[UUID, InvoiceSnapshot, KeyValue[UUID, InvoiceRecord]] { override def apply(id: UUID, snapshot: InvoiceSnapshot): KeyValue[UUID, InvoiceRecord] = KeyValue.pair(id, InvoiceRecord(id, snapshot)) } class SaveInvoiceRecord(invoicesList: InvoiceList[IO]) extends ForeachAction[UUID, InvoiceRecord] { override def apply(id: UUID, value: InvoiceRecord): Unit = invoicesList.save(value).unsafeRunSync() }
Example 3
Source File: resourcesuite.scala From pfps-shopping-cart with Apache License 2.0 | 5 votes |
package suite import cats.effect._ import cats.effect.concurrent.Deferred import org.scalatest.BeforeAndAfterAll trait ResourceSuite[A] extends PureTestSuite with BeforeAndAfterAll { def resources: Resource[IO, A] private[this] var res: A = _ private[this] var cleanUp: IO[Unit] = _ private[this] val latch = Deferred[IO, Unit].unsafeRunSync() override def beforeAll(): Unit = { super.beforeAll() val (r, h) = resources.allocated.unsafeRunSync() res = r cleanUp = h latch.complete(()).unsafeRunSync() } override def afterAll(): Unit = { cleanUp.unsafeRunSync() super.afterAll() } def withResources(f: (=> A) => Unit): Unit = f { //to ensure that the resource has been allocated even before any spec(...) bodies latch.get.unsafeRunSync res } }
Example 4
Source File: PromiseMapper.scala From laserdisc with MIT License | 5 votes |
package laserdisc package fs2 import cats.effect.concurrent.Deferred import cats.effect.syntax.concurrent._ import cats.effect.{Concurrent, Timer} import cats.syntax.flatMap._ import cats.syntax.monadError._ import shapeless.Poly1 import scala.concurrent.TimeoutException object PromiseMapper extends Poly1 { private[this] final def mapper[F[_]: Concurrent: Timer, A](protocol: Protocol.Aux[A]): Env[F] => F[Maybe[A]] = { case (queue, duration) => Deferred[F, Maybe[A]] >>= { promise => queue.enqueue1(Request(protocol, promise.complete)) >> { promise.get .timeout(duration) .adaptError { case _: TimeoutException => RequestTimedOut(protocol) } } } } implicit def mkOne[F[_]: Timer: Concurrent, A]: Case.Aux[Protocol.Aux[A], Env[F] => F[Maybe[A]]] = at[Protocol.Aux[A]](mapper(_)) }
Example 5
Source File: NettySocket.scala From asyncdb with Apache License 2.0 | 5 votes |
package io.asyncdb package netty import cats.syntax.all._ import cats.effect._ import cats.effect.concurrent.Deferred import io.netty.bootstrap.Bootstrap import io.netty.channel.Channel trait NettySocketConfig { val bootstrap: Bootstrap } abstract class NettySocket[F[_], M]( config: NettySocketConfig, channelHolder: Deferred[F, Either[Throwable, Channel]] )( implicit F: Concurrent[F] ) extends Socket[F, M] { protected def open = F.delay(config.bootstrap.connect()).flatMap { f => f.to[F] .attempt .flatMap { e => channelHolder.complete(e.map(_.channel())) } .as(this) } protected def close = channel.flatMap(ch => F.delay(ch.close())) protected def channel = channelHolder.get.rethrow }
Example 6
Source File: ConcurrentEffectLaws.scala From cats-effect with Apache License 2.0 | 5 votes |
package cats package effect package laws import cats.effect.concurrent.Deferred import cats.implicits._ import cats.laws._ import scala.concurrent.Promise trait ConcurrentEffectLaws[F[_]] extends ConcurrentLaws[F] with EffectLaws[F] { implicit def F: ConcurrentEffect[F] def runAsyncRunCancelableCoherence[A](fa: F[A]) = { val fa1 = IO.async[A] { cb => F.runAsync(fa)(r => IO(cb(r))).unsafeRunSync() } val fa2 = IO.cancelable[A] { cb => F.toIO(F.runCancelable(fa)(r => IO(cb(r))).unsafeRunSync()) } fa1 <-> fa2 } def runCancelableIsSynchronous[A] = { val lh = Deferred.uncancelable[F, Unit].flatMap { latch => val spawned = Promise[Unit]() // Never ending task val ff = F.cancelable[A] { _ => spawned.success(()); latch.complete(()) } // Execute, then cancel val token = F.delay(F.runCancelable(ff)(_ => IO.unit).unsafeRunSync()).flatMap { cancel => // Waiting for the task to start before cancelling it Async.fromFuture(F.pure(spawned.future)) >> cancel } F.liftIO(F.runAsync(token)(_ => IO.unit).toIO) *> latch.get } lh <-> F.unit } def runCancelableStartCancelCoherence[A](a: A) = { // Cancellation via runCancelable val f1: F[A] = for { effect1 <- Deferred.uncancelable[F, A] latch <- F.delay(Promise[Unit]()) never = F.cancelable[A] { _ => latch.success(()); effect1.complete(a) } cancel <- F.liftIO(F.runCancelable(never)(_ => IO.unit).toIO) // Waiting for the task to start before cancelling it _ <- Async.fromFuture(F.pure(latch.future)) // TODO get rid of this, IO, and Future here _ <- cancel result <- effect1.get } yield result // Cancellation via start.flatMap(_.cancel) val f2: F[A] = for { effect2 <- Deferred.uncancelable[F, A] // Using a latch to ensure that the task started latch <- Deferred.uncancelable[F, Unit] never = F.bracket(latch.complete(()))(_ => F.never[Unit])(_ => effect2.complete(a)) fiber <- F.start(never) // Waiting for the task to start before cancelling it _ <- latch.get _ <- F.start(fiber.cancel) result <- effect2.get } yield result f1 <-> f2 } def toIORunCancelableConsistency[A](fa: F[A]) = ConcurrentEffect.toIOFromRunCancelable(fa) <-> F.toIO(fa) } object ConcurrentEffectLaws { def apply[F[_]](implicit F0: ConcurrentEffect[F], contextShift0: ContextShift[F]): ConcurrentEffectLaws[F] = new ConcurrentEffectLaws[F] { val F = F0 val contextShift = contextShift0 } }
Example 7
Source File: AsyncLaws.scala From cats-effect with Apache License 2.0 | 5 votes |
package cats package effect package laws import cats.effect.ExitCase.{Completed, Error} import cats.effect.concurrent.Deferred import cats.implicits._ import cats.laws._ import scala.util.Either trait AsyncLaws[F[_]] extends SyncLaws[F] { implicit def F: Async[F] def asyncRightIsPure[A](a: A) = F.async[A](_(Right(a))) <-> F.pure(a) def asyncLeftIsRaiseError[A](e: Throwable) = F.async[A](_(Left(e))) <-> F.raiseError(e) def repeatedAsyncEvaluationNotMemoized[A](a: A, f: A => A) = F.suspend { var cur = a val change: F[Unit] = F.async { cb => cur = f(cur) cb(Right(())) } val read: F[A] = F.delay(cur) change *> change *> read } <-> F.pure(f(f(a))) def repeatedAsyncFEvaluationNotMemoized[A](a: A, f: A => A) = F.suspend { var cur = a val change: F[Unit] = F.asyncF { cb => cur = f(cur) F.delay(cb(Right(()))) } val read: F[A] = F.delay(cur) change *> change *> read } <-> F.pure(f(f(a))) def repeatedCallbackIgnored[A](a: A, f: A => A) = F.suspend { var cur = a val change = F.delay { cur = f(cur) } val readResult = F.delay(cur) val double: F[Unit] = F.async { cb => cb(Right(())) cb(Right(())) } double *> change *> readResult } <-> F.delay(f(a)) def propagateErrorsThroughBindAsync[A](t: Throwable) = { val fa = F.attempt(F.async[A](_(Left(t))).flatMap(x => F.pure(x))) fa <-> F.pure(Left(t)) } def neverIsDerivedFromAsync[A] = F.never[A] <-> F.async[A](_ => ()) def asyncCanBeDerivedFromAsyncF[A](k: (Either[Throwable, A] => Unit) => Unit) = F.async(k) <-> F.asyncF(cb => F.delay(k(cb))) def bracketReleaseIsCalledOnCompletedOrError[A, B](fa: F[A], b: B) = { val lh = Deferred.uncancelable[F, B].flatMap { promise => val br = F.bracketCase(F.delay(promise)) { _ => fa } { case (r, Completed | Error(_)) => r.complete(b) case _ => F.unit } // Start and forget // we attempt br because even if fa fails, we expect the release function // to run and set the promise. F.asyncF[Unit](cb => F.delay(cb(Right(()))) *> br.attempt.as(())) *> promise.get } lh <-> F.pure(b) } } object AsyncLaws { def apply[F[_]](implicit F0: Async[F]): AsyncLaws[F] = new AsyncLaws[F] { val F = F0 } }
Example 8
Source File: SqsSpec.scala From fs2-aws with MIT License | 5 votes |
package fs2.aws import cats.effect.concurrent.Deferred import cats.effect.{ ContextShift, IO } import com.amazon.sqs.javamessaging.SQSConnection import com.amazon.sqs.javamessaging.message.SQSTextMessage import eu.timepit.refined.auto._ import fs2.aws import fs2.aws.sqs.{ ConsumerBuilder, SQSConsumer, SqsConfig } import javax.jms.{ Message, MessageListener, TextMessage } import org.mockito.scalatest.MockitoSugar import org.scalatest.flatspec.AsyncFlatSpec import org.scalatest.matchers.should.Matchers import scala.concurrent.ExecutionContext class SqsSpec extends AsyncFlatSpec with Matchers with MockitoSugar { implicit val ec: ExecutionContext = ExecutionContext.global implicit val ioContextShift: ContextShift[IO] = IO.contextShift(ec) implicit val messageDecoder: Message => Either[Throwable, Int] = { sqs_msg => val text = sqs_msg.asInstanceOf[TextMessage].getText if ("fail" == text) Left(intercept[Exception](())) else Right(text.toInt) } "SQS endpoint" should "stream messages" in { def stream(d: Deferred[IO, MessageListener]) = aws .sqsStream[IO, Int]( SqsConfig("dummy"), (_, listener) => new ConsumerBuilder[IO] { override def start: IO[SQSConsumer] = IO.delay(new SQSConsumer { override def callback: MessageListener = listener override def startConsumer(): Unit = () override def shutdown(): Unit = () override def connection: SQSConnection = mock[SQSConnection] }) }, Some(d) ) .take(4) .compile .toList val r = for { d <- Deferred[IO, MessageListener] res <- IO.racePair(stream(d), d.get).flatMap { case Right((streamFiber, listener)) => listener.onMessage(new SQSTextMessage("1")) listener.onMessage(new SQSTextMessage("2")) listener.onMessage(new SQSTextMessage("fail")) listener.onMessage(new SQSTextMessage("4")) listener.onMessage(new SQSTextMessage("5")) streamFiber.join case _ => IO(Nil) } } yield res val future = r.unsafeToFuture() future.map(_ should be(List(1, 2, 4, 5))) } }
Example 9
Source File: package.scala From fs2-aws with MIT License | 5 votes |
package fs2 import cats.effect.concurrent.Deferred import cats.effect.{ ConcurrentEffect, IO } import fs2.aws.sqs.{ ConsumerBuilder, ReceiverCallback, SqsConfig } import fs2.concurrent.Queue import javax.jms.{ Message, MessageListener } package object aws { def sqsStream[F[_], O]( sqsConfig: SqsConfig, builder: (SqsConfig, MessageListener) => ConsumerBuilder[F], d: Option[Deferred[F, MessageListener]] = None )(implicit F: ConcurrentEffect[F], decoder: Message => Either[Throwable, O]): fs2.Stream[F, O] = for { q <- fs2.Stream.eval(Queue.unbounded[F, Either[Throwable, O]]) callback <- fs2.Stream.eval(callback(q)) _ <- fs2.Stream.eval(d.map(_.complete(callback)).getOrElse(F.unit)) item <- builder(sqsConfig, callback).serve(q.dequeue.rethrow) } yield item def callback[F[_], O](queue: Queue[F, Either[Throwable, O]])( implicit F: ConcurrentEffect[F], decoder: Message => Either[Throwable, O] ): F[ReceiverCallback[Either[Throwable, O]]] = F.delay( new ReceiverCallback[Either[Throwable, O]](r => F.runAsync(queue.enqueue1(r))(_ => IO.unit).unsafeRunSync() ) ) }
Example 10
Source File: package.scala From fs2-aws with MIT License | 5 votes |
package fs2.aws import cats.effect.ConcurrentEffect import cats.effect.concurrent.Deferred import eu.timepit.refined.auto._ import fs2.aws.sqs.SqsConfig import javax.jms.{ Message, MessageListener } import scala.concurrent.duration._ package object testkit { def sqsStream[F[_]: ConcurrentEffect, O]( d: Deferred[F, MessageListener] )(implicit decoder: Message => Either[Throwable, O]): fs2.Stream[F, O] = fs2.aws.sqsStream( SqsConfig("dummy"), (_: SqsConfig, _: MessageListener) => new TestSqsConsumerBuilder[F], Some(d) ) val TestRecordProcessor = new kinesis.SingleRecordProcessor(_ => (), 10.seconds) }
Example 11
Source File: lift.scala From tofu with Apache License 2.0 | 5 votes |
package tofu.syntax import cats.{Functor, ~>} import cats.effect.concurrent.{Deferred, MVar, Ref, Semaphore} import tofu.lift.{IsoK, Lift, Unlift} import cats.tagless.{FunctorK, InvariantK} import tofu.lift.{IsoK, Lift, Unlift} object lift { implicit final class LiftSyntax[F[_], A](private val fa: F[A]) extends AnyVal { def lift[G[_]](implicit lift: Lift[F, G]): G[A] = lift.lift(fa) } implicit final class MVarLiftSyntax[F[_], A](private val mvar: MVar[F, A]) extends AnyVal { def lift[G[_]](implicit lift: Lift[F, G]): MVar[G, A] = mvar.mapK(lift.liftF) } implicit final class RefLiftSyntax[F[_], A](private val ref: Ref[F, A]) extends AnyVal { def lift[G[_]](implicit lift: Lift[F, G], F: Functor[F]): Ref[G, A] = ref.mapK(lift.liftF) } implicit final class DeferredLiftSyntax[F[_], A](private val deferred: Deferred[F, A]) extends AnyVal { def lift[G[_]](implicit lift: Lift[F, G]): Deferred[G, A] = deferred.mapK(lift.liftF) } implicit final class SemaphoreLiftSyntax[F[_]](private val semaphore: Semaphore[F]) extends AnyVal { def ilift[G[_]](implicit lift: IsoK[F, G]): Semaphore[G] = semaphore.imapK(lift.tof, lift.fromF) def unlift[G[_]](implicit unlift: Unlift[F, G], G: Functor[G]): G[Semaphore[G]] = G.map(unlift.unlift)(backf => semaphore.imapK(unlift.liftF, backf)) } implicit final class CatsTaglessLiftSyntax[T[_[_]], F[_]](private val tf: T[F]) extends AnyVal { def lift[G[_]](implicit lift: Lift[F, G], fk: FunctorK[T]): T[G] = fk.mapK(tf)(lift.liftF) def ilift[G[_]](implicit lift: IsoK[F, G], fk: InvariantK[T]): T[G] = fk.imapK(tf)(lift.tof)(lift.fromF) def unlift[G[_]](implicit unlift: Unlift[F, G], G: Functor[G], fk: InvariantK[T]): G[T[G]] = G.map(unlift.unlift)(backf => fk.imapK(tf)(unlift.liftF)(backf)) } implicit final class CatsTagless1LiftSyntax[T[_[_], _], F[_], A](private val tf: T[F, A]) extends AnyVal { def mapK1[G[_]](f: F ~> G)(implicit fk: FunctorK[T[*[_], A]]): T[G, A] = fk.mapK(tf)(f) def imapK1[G[_]](f: F ~> G)(g: G ~> F)(implicit fk: InvariantK[T[*[_], A]]): T[G, A] = fk.imapK(tf)(f)(g) def lift1[G[_]](implicit lift: Lift[F, G], fk: FunctorK[T[*[_], A]]): T[G, A] = fk.mapK(tf)(lift.liftF) def ilift1[G[_]](implicit lift: IsoK[F, G], fk: InvariantK[T[*[_], A]]): T[G, A] = fk.imapK(tf)(lift.tof)(lift.fromF) def unlift1[G[_]](implicit unlift: Unlift[F, G], G: Functor[G], fk: InvariantK[T[*[_], A]]): G[T[G, A]] = G.map(unlift.unlift)(backf => fk.imapK(tf)(unlift.liftF)(backf)) } implicit final class CatsTagless2LiftSyntax[T[_[_], _, _], F[_], A, B](private val tf: T[F, A, B]) extends AnyVal { def mapK2[G[_]](f: F ~> G)(implicit fk: FunctorK[T[*[_], A, B]]): T[G, A, B] = fk.mapK(tf)(f) def imapK2[G[_]](f: F ~> G)(g: G ~> F)(implicit fk: InvariantK[T[*[_], A, B]]): T[G, A, B] = fk.imapK(tf)(f)(g) def lift2[G[_]](implicit lift: Lift[F, G], fk: FunctorK[T[*[_], A, B]]): T[G, A, B] = fk.mapK(tf)(lift.liftF) def ilift2[G[_]](implicit lift: IsoK[F, G], fk: InvariantK[T[*[_], A, B]]): T[G, A, B] = fk.imapK(tf)(lift.tof)(lift.fromF) def unlift2[G[_]](implicit unlift: Unlift[F, G], G: Functor[G], fk: InvariantK[T[*[_], A, B]]): G[T[G, A, B]] = G.map(unlift.unlift)(backf => fk.imapK(tf)(unlift.liftF)(backf)) } }
Example 12
Source File: MakeDeferred.scala From tofu with Apache License 2.0 | 5 votes |
package tofu.concurrent import cats.effect.concurrent.{Deferred, TryableDeferred} import cats.effect.{Concurrent, Sync} trait MakeDeferred[I[_], F[_]] { def deferred[A]: I[Deferred[F, A]] } trait TryableDeferreds[F[_]] extends MakeDeferred[F, F] { def tryable[A]: F[TryableDeferred[F, A]] } object Deferreds { def apply[F[_], A](implicit make: Deferreds[F]): F[Deferred[F, A]] = make.deferred[A] } object MakeDeferred extends PolymorphicMakeDefferedInstance { def apply[I[_], F[_], A](implicit make: MakeDeferred[I, F]): I[Deferred[F, A]] = make.deferred[A] def tryable[F[_], A](implicit make: TryableDeferreds[F]): F[TryableDeferred[F, A]] = make.tryable[A] implicit def concurrentTryableDeferreds[F[_]: Concurrent]: TryableDeferreds[F] = new TryableDeferreds[F] { def deferred[A]: F[Deferred[F, A]] = Deferred[F, A] def tryable[A]: F[TryableDeferred[F, A]] = Deferred.tryable[F, A] } } trait PolymorphicMakeDefferedInstance { implicit def concurrentMakeDeferred[I[_]: Sync, F[_]: Concurrent]: MakeDeferred[I, F] = new MakeDeferred[I, F] { def deferred[A]: I[Deferred[F, A]] = Deferred.in[I, F, A] } }
Example 13
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 14
Source File: ZioTofuConcurrentInstance.scala From tofu with Apache License 2.0 | 5 votes |
package tofu.zioInstances import cats.effect.concurrent.Deferred import tofu.concurrent._ import tofu.zioInstances.ZIODaemon.exitMap import zio.{Exit => _, _} abstract class ZioTofuConcurrentInstance[R1, E1, R, E] extends MakeConcurrent[ZIO[R1, E1, *], ZIO[R, E, *]] with Daemonic[ZIO[R, E, *], Cause[E]] class ZioTofuConcurrentInstanceUIO[R, E] extends ZioTofuConcurrentInstance[Any, Nothing, R, E] { def deferred[A]: UIO[Deferred[ZIO[R, E, *], A]] = Promise.make[E, A].map(ZioDeferred(_)) def qvarOf[A](a: A): ZIO[Any, Nothing, QVar[ZIO[R, E, *], A]] = Queue.bounded[A](1).tap(_.offer(a)).map(ZioQVar(_)) def qvarEmpty[A]: ZIO[Any, Nothing, QVar[ZIO[R, E, *], A]] = Queue.bounded[A](1).map(ZioQVar(_)) def gatekeeper(available: Long): ZIO[Any, Nothing, Gatekeeper[ZIO[R, E, *], Long]] = Semaphore.make(available).map(ZioGatekeeper(_, available)) def atom[A](a: A): ZIO[Any, Nothing, Atom[ZIO[R, E, *], A]] = Ref.make(a).map(ZioAtom(_)) def agentOf[A](a: A): ZIO[Any, Nothing, Agent[ZIO[R, E, *], A]] = RefM.make(a).map(ZioAgent(_)) def daemonize[A](process: ZIO[R, E, A]): ZIO[R, E, Daemon[ZIO[R, E, *], Cause[E], A]] = process.forkDaemon.map(ZIODaemon(_)) } final case class ZioDeferred[R, E, A](p: zio.Promise[E, A]) extends Deferred[ZIO[R, E, *], A] { def get: ZIO[R, E, A] = p.await def complete(a: A): ZIO[R, E, Unit] = p.succeed(a).unit } final case class ZioAtom[R, E, A](r: zio.Ref[A]) extends Atom[ZIO[R, E, *], A] { def get: ZIO[R, E, A] = r.get def set(a: A): ZIO[R, E, Unit] = r.set(a) def getAndSet(a: A): ZIO[R, E, A] = r.modify(a1 => (a1, a)) def update(f: A => A): ZIO[R, E, Unit] = r.update(f).unit def modify[B](f: A => (A, B)): ZIO[R, E, B] = r.modify(f(_).swap) } final case class ZioQVar[R, E, A](r: zio.Queue[A]) extends QVar[ZIO[R, E, *], A] { def isEmpty: ZIO[R, E, Boolean] = r.size.map(_ == 0) def put(a: A): ZIO[R, E, Unit] = r.offer(a).unit def take: ZIO[R, E, A] = r.take def read: ZIO[R, E, A] = r.poll.some.orElse(r.take.tap(r.offer).uninterruptible) } final case class ZioGatekeeper[R, E](r: zio.Semaphore, size: Long) extends Gatekeeper[ZIO[R, E, *], Long] { def available: ZIO[R, E, Long] = r.available def taken: ZIO[R, E, Long] = r.available.map(size - _) def withPermit[B](t: ZIO[R, E, B]): ZIO[R, E, B] = r.withPermit(t) def withPermitN[B](take: Long)(t: ZIO[R, E, B]): ZIO[R, E, B] = r.withPermits(take)(t) } final case class ZIODaemon[R, E, A](fib: zio.Fiber[E, A]) extends Daemon[ZIO[R, E, *], Cause[E], A] { def join: ZIO[R, E, A] = fib.join def cancel: ZIO[R, E, Unit] = fib.interrupt.unit def poll: ZIO[R, E, Option[Exit[Cause[E], A]]] = fib.poll.map(_.map(exitMap)) def exit: ZIO[R, E, Exit[Cause[E], A]] = fib.await.map(exitMap) } final case class ZioAgent[R, E, A](refm: RefM[A]) extends Agent[ZIO[R, E, *], A] { def get: ZIO[R, E, A] = refm.get def updateM(f: A => ZIO[R, E, A]): ZIO[R, E, A] = refm.getAndUpdate(f) def fireUpdateM(f: A => ZIO[R, E, A]): ZIO[R, E, Unit] = refm.update(f).forkDaemon.unit def modifyM[B](f: A => ZIO[R, E, (B, A)]): ZIO[R, E, B] = refm.modify(f) def updateSomeM(f: PartialFunction[A, ZIO[R, E, A]]): ZIO[R, E, A] = refm.getAndUpdateSome(f) def modifySomeM[B](default: B)(f: PartialFunction[A, ZIO[R, E, (B, A)]]): ZIO[R, E, B] = refm.modifySome(default)(f) } object ZIODaemon { private[ZIODaemon] def exitMap[E, A](e: zio.Exit[E, A]): Exit[Cause[E], A] = e match { case zio.Exit.Success(a) => Exit.Completed(a) case zio.Exit.Failure(e) => if (e.interrupted) Exit.Canceled else Exit.Error(e) } }
Example 15
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 16
Source File: Channel.scala From aecor with MIT License | 5 votes |
package aecor.kafkadistributedprocessing.internal import aecor.kafkadistributedprocessing.internal import aecor.kafkadistributedprocessing.internal.Channel.CompletionCallback import cats.effect.Concurrent import cats.effect.concurrent.Deferred import cats.effect.implicits._ import cats.implicits._ private[kafkadistributedprocessing] final case class Channel[F[_]](watch: F[CompletionCallback[F]], close: F[Unit], call: F[Unit]) private[kafkadistributedprocessing] object Channel { type CompletionCallback[F[_]] = F[Unit] def create[F[_]: Concurrent]: F[Channel[F]] = for { deferredCallback <- Deferred[F, CompletionCallback[F]] closed <- Deferred[F, Unit] close = closed.complete(()) watch = deferredCallback.get call = Deferred[F, Unit] .flatMap { deferredCompletion => deferredCallback .complete(deferredCompletion.complete(()).attempt.void) >> deferredCompletion.get } .race(closed.get) .void } yield internal.Channel(watch, close, call) }
Example 17
Source File: IncomingManager.scala From iotchain with MIT License | 5 votes |
package jbok.core.peer import java.net.InetSocketAddress import java.nio.channels.AsynchronousChannelGroup import cats.effect._ import cats.effect.concurrent.Deferred import cats.effect.implicits._ import cats.implicits._ import fs2._ import fs2.io.tcp.Socket import javax.net.ssl.SSLContext import jbok.common.log.Logger import jbok.core.config.FullConfig import jbok.core.ledger.History import jbok.core.queue.Queue import jbok.network.Message import jbok.network.tcp.implicits._ final class IncomingManager[F[_]](config: FullConfig, history: History[F], ssl: Option[SSLContext], val inbound: Queue[F, Peer[F], Message[F]])( implicit F: ConcurrentEffect[F], cs: ContextShift[F], acg: AsynchronousChannelGroup ) extends BaseManager[F](config, history) { private val log = Logger[F] val localBindAddress: Deferred[F, InetSocketAddress] = Deferred.unsafe[F, InetSocketAddress] val localPeerUri: F[PeerUri] = localBindAddress.get.map(addr => PeerUri.fromTcpAddr(addr)) val peers: Stream[F, Resource[F, (Peer[F], Socket[F])]] = Socket .serverWithLocalAddress[F]( address = config.peer.bindAddr, maxQueued = 10, reuseAddress = true, receiveBufferSize = config.peer.bufferSize ) .flatMap { case Left(bound) => Stream.eval_(log.i(s"IncomingManager successfully bound to address ${bound}") >> localBindAddress.complete(bound)) case Right(res) => Stream.emit { for { socket <- res tlsSocket <- Resource.liftF(socket.toTLSSocket(ssl, client = false)) peer <- Resource.liftF(handshake(socket)) _ <- Resource.make(connected.update(_ + (peer.uri -> (peer -> socket))).as(peer))(peer => connected.update(_ - peer.uri)) _ <- Resource.liftF(log.i(s"accepted incoming peer ${peer.uri}")) } yield (peer, tlsSocket) } } val serve: Stream[F, Unit] = peers .map { res => Stream .resource(res) .flatMap { case (peer, socket) => Stream( socket .reads(config.peer.bufferSize, None) .through(Message.decodePipe[F]) .map(m => peer -> m) .through(inbound.sink) .onFinalize(log.i(s"disconnected incoming ${peer.uri}") >> connected.update(_ - peer.uri)), peer.queue.dequeue.through(Message.encodePipe[F]).through(socket.writes(None)) ).parJoinUnbounded } .handleErrorWith(e => Stream.eval(log.w(s"handle incoming peer failure: ${e}", e))) } .parJoin(config.peer.maxIncomingPeers) val resource: Resource[F, PeerUri] = Resource { for { fiber <- serve.compile.drain.start address <- localBindAddress.get } yield PeerUri.fromTcpAddr(address) -> fiber.cancel } }
Example 18
Source File: FS2QueueProcess.scala From aecor with MIT License | 5 votes |
package aecor.example.process import aecor.distributedprocessing.DistributedProcessing.{ Process, RunningProcess } import cats.effect.Concurrent import cats.effect.concurrent.Deferred import cats.implicits._ import fs2._ import fs2.concurrent.Queue import cats.effect.implicits._ object FS2QueueProcess { def create[F[_]: Concurrent, A]( sources: List[Stream[F, A]] ): F[(Stream[F, Stream[F, A]], List[Process[F]])] = for { queue <- Queue.bounded[F, Stream[F, A]](sources.length) processes = sources.map { s => Process { Deferred[F, Either[Throwable, Unit]].flatMap { stopped => queue .enqueue1(s.interruptWhen(stopped)) .flatTap(_ => stopped.get) .start .map { fiber => RunningProcess(fiber.join, stopped.complete(Right(()))) } } } } } yield (queue.dequeue, processes) }
Example 19
Source File: CatsEffectSpecs.scala From cats-effect-testing with Apache License 2.0 | 5 votes |
package cats.effect.testing.specs2 import cats.effect.{IO, Resource} import cats.effect.concurrent.{Ref, Deferred} import cats.implicits._ import org.specs2.mutable.Specification class CatsEffectSpecs extends Specification with CatsEffect { "cats effect specifications" should { "run a non-effectful test" in { true must beTrue } "run a simple effectful test" in IO { true must beTrue false must beFalse } "run a simple resource test" in { true must beTrue }.pure[Resource[IO, *]] "resource must be live for use" in { Resource.make(Ref[IO].of(true))(_.set(false)).map{ _.get.map(_ must beTrue) } } "really execute effects" in { "First, this check creates a deferred value.".br val deferredValue = Deferred.unsafeUncancelable[IO, Boolean] "Then it executes two mutually associated steps:".br.tab "forcibly attempt to get the deferred value" in { deferredValue.get.unsafeRunTimed(Timeout) must beSome(true) } "Since specs2 executes steps in parallel by default, the second step gets executed anyway.".br "complete the deferred value inside IO context" in { deferredValue.complete(true) *> IO.pure(success) } "If effects didn't get executed then the previous step would fail after timeout.".br } // "timeout a failing test" in (IO.never: IO[Boolean]) } }
Example 20
Source File: runner.scala From redis4cats with Apache License 2.0 | 5 votes |
package dev.profunktor.redis4cats import cats.effect._ import cats.effect.concurrent.Deferred import cats.effect.implicits._ import cats.implicits._ import dev.profunktor.redis4cats.effect.Log import dev.profunktor.redis4cats.hlist._ import java.util.UUID import scala.concurrent.duration._ object Runner { type CancelFibers[F[_]] = Throwable => F[Unit] case class Ops[F[_]]( name: String, mainCmd: F[Unit], onComplete: CancelFibers[F] => F[Unit], onError: F[Unit], afterCompletion: F[Unit], mkError: () => Throwable ) def apply[F[_]: Concurrent: Log: Timer]: RunnerPartiallyApplied[F] = new RunnerPartiallyApplied[F] } private[redis4cats] class RunnerPartiallyApplied[F[_]: Concurrent: Log: Timer] { def filterExec[T <: HList, R <: HList, S <: HList](ops: Runner.Ops[F])(commands: T)( implicit w: Witness.Aux[T, R], f: Filter.Aux[R, S] ): F[S] = exec[T, R](ops)(commands).map(_.filterUnit) def exec[T <: HList, R <: HList](ops: Runner.Ops[F])(commands: T)(implicit w: Witness.Aux[T, R]): F[R] = (Deferred[F, Either[Throwable, w.R]], F.delay(UUID.randomUUID)).tupled.flatMap { case (promise, uuid) => def cancelFibers[A](fibs: HList)(err: Throwable): F[Unit] = joinOrCancel(fibs, HNil)(false).void >> promise.complete(err.asLeft) F.debug(s"${ops.name} started - ID: $uuid") >> Resource .makeCase(ops.mainCmd >> runner(commands, HNil)) { case ((fibs: HList), ExitCase.Completed) => for { _ <- F.debug(s"${ops.name} completed - ID: $uuid") _ <- ops.onComplete(cancelFibers(fibs)) tr <- joinOrCancel(fibs, HNil)(true) // Casting here is fine since we have a `Witness` that proves this true _ <- promise.complete(tr.asInstanceOf[w.R].asRight) } yield () case ((fibs: HList), ExitCase.Error(e)) => F.error(s"${ops.name} failed: ${e.getMessage} - ID: $uuid") >> ops.onError.guarantee(cancelFibers(fibs)(ops.mkError())) case ((fibs: HList), ExitCase.Canceled) => F.error(s"${ops.name} canceled - ID: $uuid") >> ops.onError.guarantee(cancelFibers(fibs)(ops.mkError())) case _ => F.error(s"Kernel panic: the impossible happened! - ID: $uuid") } .use(_ => F.unit) .guarantee(ops.afterCompletion) >> promise.get.rethrow.timeout(3.seconds) } // Forks every command in order private def runner[H <: HList, G <: HList](ys: H, res: G): F[Any] = ys match { case HNil => F.pure(res) case HCons((h: F[_] @unchecked), t) => h.start.flatMap(fb => runner(t, fb :: res)) } // Joins or cancel fibers correspondent to previous executed commands private def joinOrCancel[H <: HList, G <: HList](ys: H, res: G)(isJoin: Boolean): F[Any] = ys match { case HNil => F.pure(res) case HCons((h: Fiber[F, Any] @unchecked), t) if isJoin => h.join.flatMap(x => joinOrCancel(t, x :: res)(isJoin)) case HCons((h: Fiber[F, Any] @unchecked), t) => h.cancel.flatMap(x => joinOrCancel(t, x :: res)(isJoin)) case HCons(h, t) => F.error(s"Unexpected result: ${h.toString}") >> joinOrCancel(t, res)(isJoin) } }
Example 21
Source File: Fs2UnaryServerCallListener.scala From fs2-grpc with MIT License | 5 votes |
package org.lyranthe.fs2_grpc package java_runtime package server import cats.effect.{ConcurrentEffect, Effect} import cats.effect.concurrent.{Deferred, Ref} import cats.syntax.all._ import io.grpc._ class Fs2UnaryServerCallListener[F[_], Request, Response] private ( request: Ref[F, Option[Request]], isComplete: Deferred[F, Unit], val isCancelled: Deferred[F, Unit], val call: Fs2ServerCall[F, Request, Response] )(implicit F: Effect[F]) extends ServerCall.Listener[Request] with Fs2ServerCallListener[F, F, Request, Response] { import Fs2UnaryServerCallListener._ override def onCancel(): Unit = { isCancelled.complete(()).unsafeRun() } override def onMessage(message: Request): Unit = { request.access .flatMap[Unit] { case (curValue, modify) => if (curValue.isDefined) F.raiseError(statusException(TooManyRequests)) else modify(message.some).void } .unsafeRun() } override def onHalfClose(): Unit = isComplete.complete(()).unsafeRun() override def source: F[Request] = for { _ <- isComplete.get valueOrNone <- request.get value <- valueOrNone.fold[F[Request]](F.raiseError(statusException(NoMessage)))(F.pure) } yield value } object Fs2UnaryServerCallListener { val TooManyRequests: String = "Too many requests" val NoMessage: String = "No message for unary call" private val statusException: String => StatusRuntimeException = msg => new StatusRuntimeException(Status.INTERNAL.withDescription(msg)) class PartialFs2UnaryServerCallListener[F[_]](val dummy: Boolean = false) extends AnyVal { def apply[Request, Response]( call: ServerCall[Request, Response], options: ServerCallOptions = ServerCallOptions.default )(implicit F: ConcurrentEffect[F] ): F[Fs2UnaryServerCallListener[F, Request, Response]] = for { request <- Ref.of[F, Option[Request]](none) isComplete <- Deferred[F, Unit] isCancelled <- Deferred[F, Unit] serverCall <- Fs2ServerCall[F, Request, Response](call, options) } yield new Fs2UnaryServerCallListener[F, Request, Response](request, isComplete, isCancelled, serverCall) } def apply[F[_]] = new PartialFs2UnaryServerCallListener[F] }
Example 22
Source File: Fs2StreamServerCallListener.scala From fs2-grpc with MIT License | 5 votes |
package org.lyranthe.fs2_grpc package java_runtime package server import cats.effect.concurrent.Deferred import cats.effect.{ConcurrentEffect, Effect} import cats.implicits._ import io.grpc.ServerCall import fs2.concurrent.Queue import fs2._ class Fs2StreamServerCallListener[F[_], Request, Response] private ( requestQ: Queue[F, Option[Request]], val isCancelled: Deferred[F, Unit], val call: Fs2ServerCall[F, Request, Response] )(implicit F: Effect[F]) extends ServerCall.Listener[Request] with Fs2ServerCallListener[F, Stream[F, ?], Request, Response] { override def onCancel(): Unit = { isCancelled.complete(()).unsafeRun() } override def onMessage(message: Request): Unit = { call.call.request(1) requestQ.enqueue1(message.some).unsafeRun() } override def onHalfClose(): Unit = requestQ.enqueue1(none).unsafeRun() override def source: Stream[F, Request] = requestQ.dequeue.unNoneTerminate } object Fs2StreamServerCallListener { class PartialFs2StreamServerCallListener[F[_]](val dummy: Boolean = false) extends AnyVal { def apply[Request, Response]( call: ServerCall[Request, Response], options: ServerCallOptions = ServerCallOptions.default )(implicit F: ConcurrentEffect[F] ): F[Fs2StreamServerCallListener[F, Request, Response]] = for { inputQ <- Queue.unbounded[F, Option[Request]] isCancelled <- Deferred[F, Unit] serverCall <- Fs2ServerCall[F, Request, Response](call, options) } yield new Fs2StreamServerCallListener[F, Request, Response](inputQ, isCancelled, serverCall) } def apply[F[_]] = new PartialFs2StreamServerCallListener[F] }
Example 23
Source File: Fs2ServerCallListener.scala From fs2-grpc with MIT License | 5 votes |
package org.lyranthe.fs2_grpc package java_runtime package server import cats.effect._ import cats.effect.concurrent.Deferred import cats.implicits._ import fs2.Stream import io.grpc.{Metadata, Status, StatusException, StatusRuntimeException} private[server] trait Fs2ServerCallListener[F[_], G[_], Request, Response] { def source: G[Request] def isCancelled: Deferred[F, Unit] def call: Fs2ServerCall[F, Request, Response] private def reportError(t: Throwable)(implicit F: Sync[F]): F[Unit] = { t match { case ex: StatusException => call.closeStream(ex.getStatus, Option(ex.getTrailers).getOrElse(new Metadata())) case ex: StatusRuntimeException => call.closeStream(ex.getStatus, Option(ex.getTrailers).getOrElse(new Metadata())) case ex => // TODO: Customize failure trailers? call.closeStream(Status.INTERNAL.withDescription(ex.getMessage).withCause(ex), new Metadata()) } } private def handleUnaryResponse(headers: Metadata, response: F[Response])(implicit F: Sync[F]): F[Unit] = call.sendHeaders(headers) *> call.request(1) *> response >>= call.sendMessage private def handleStreamResponse(headers: Metadata, response: Stream[F, Response])(implicit F: Sync[F]): F[Unit] = call.sendHeaders(headers) *> call.request(1) *> response.evalMap(call.sendMessage).compile.drain private def unsafeRun(f: F[Unit])(implicit F: ConcurrentEffect[F]): Unit = { val bracketed = F.guaranteeCase(f) { case ExitCase.Completed => call.closeStream(Status.OK, new Metadata()) case ExitCase.Canceled => call.closeStream(Status.CANCELLED, new Metadata()) case ExitCase.Error(t) => reportError(t) } // Exceptions are reported by closing the call F.runAsync(F.race(bracketed, isCancelled.get))(_ => IO.unit).unsafeRunSync() } def unsafeUnaryResponse(headers: Metadata, implementation: G[Request] => F[Response])(implicit F: ConcurrentEffect[F] ): Unit = unsafeRun(handleUnaryResponse(headers, implementation(source))) def unsafeStreamResponse(headers: Metadata, implementation: G[Request] => Stream[F, Response])(implicit F: ConcurrentEffect[F] ): Unit = unsafeRun(handleStreamResponse(headers, implementation(source))) }
Example 24
Source File: Fs2UnaryClientCallListener.scala From fs2-grpc with MIT License | 5 votes |
package org.lyranthe.fs2_grpc package java_runtime package client import cats.effect._ import cats.effect.concurrent.{Deferred, Ref} import cats.implicits._ import io.grpc._ class Fs2UnaryClientCallListener[F[_], Response](grpcStatus: Deferred[F, GrpcStatus], value: Ref[F, Option[Response]])( implicit F: Effect[F] ) extends ClientCall.Listener[Response] { override def onClose(status: Status, trailers: Metadata): Unit = grpcStatus.complete(GrpcStatus(status, trailers)).unsafeRun() override def onMessage(message: Response): Unit = value.set(message.some).unsafeRun() def getValue: F[Response] = { for { r <- grpcStatus.get v <- value.get result <- { if (!r.status.isOk) F.raiseError(r.status.asRuntimeException(r.trailers)) else { v match { case None => F.raiseError( Status.INTERNAL .withDescription("No value received for unary call") .asRuntimeException(r.trailers) ) case Some(v1) => F.pure(v1) } } } } yield result } } object Fs2UnaryClientCallListener { def apply[F[_]: ConcurrentEffect, Response]: F[Fs2UnaryClientCallListener[F, Response]] = { (Deferred[F, GrpcStatus], Ref.of[F, Option[Response]](none)).mapN((response, value) => new Fs2UnaryClientCallListener[F, Response](response, value) ) } }
Example 25
Source File: StartResourceSpec.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal.util import cats.effect._ import cats.effect.concurrent.{Deferred, Ref} import cats.implicits._ import com.evolutiongaming.kafka.journal.IOSuite._ import org.scalatest.funsuite.AsyncFunSuite import org.scalatest.matchers.should.Matchers class StartResourceSpec extends AsyncFunSuite with Matchers { test("StartResource") { val result = for { deferred <- Deferred[IO, Unit] ref <- Ref.of[IO, Boolean](false) res = Resource.make(IO.unit)(_ => ref.set(true)) fiber <- StartResource(res)(_ => deferred.complete(()) *> IO.never.as(())) _ <- deferred.get _ <- fiber.cancel result <- ref.get } yield { result shouldEqual true } result.run() } }
Example 26
Source File: GracefulFiberSpec.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal.util import cats.effect._ import cats.effect.concurrent.{Deferred, Ref} import cats.implicits._ import com.evolutiongaming.kafka.journal.IOSuite._ import org.scalatest.funsuite.AsyncFunSuite import org.scalatest.matchers.should.Matchers class GracefulFiberSpec extends AsyncFunSuite with Matchers { test("GracefulFiber") { val result = for { deferred <- Deferred[IO, Unit] ref <- Ref.of[IO, Boolean](false) fiber <- GracefulFiber[IO].apply { cancel => Concurrent[IO].start[Unit] { val loop = for { cancel <- cancel _ <- ref.set(cancel) } yield { if (cancel) ().some else none } for { _ <- deferred.complete(()) _ <- loop.untilDefinedM } yield {} } } _ <- fiber.cancel result <- ref.get } yield { result shouldEqual true } result.run() } }
Example 27
Source File: ResourceRegistrySpec.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal.util import cats.effect._ import cats.effect.concurrent.{Deferred, Ref} import cats.implicits._ import cats.{Applicative, Foldable} import com.evolutiongaming.kafka.journal.IOSuite._ import org.scalatest.funsuite.AsyncFunSuite import org.scalatest.matchers.should.Matchers import scala.util.control.NoStackTrace class ResourceRegistrySpec extends AsyncFunSuite with Matchers { val error: Throwable = new RuntimeException with NoStackTrace for { exitCase <- List( ExitCase.complete, ExitCase.error(error), ExitCase.canceled) } yield { test(s"ResRegistry releases resources, exitCase: $exitCase") { val result = exitCase match { case ExitCase.Completed => testError(none) case ExitCase.Canceled => testCancel case ExitCase.Error(error) => testError(error.some) } result.run() } } private def testError(error: Option[Throwable]) = { val n = 3 def logic(release: IO[Unit]) = { ResourceRegistry.of[IO].use { registry => val resource = Resource.make(().pure[IO]) { _ => release } val fa = registry.allocate(resource) implicit val monoidUnit = Applicative.monoid[IO, Unit] for { _ <- Foldable[List].fold(List.fill(n)(fa)) _ <- error.fold(().pure[IO])(_.raiseError[IO, Unit]) } yield {} } } for { ref <- Ref.of[IO, Int](0) fa = logic(ref.update(_ + 1)) result <- fa.redeem(_.some, _ => none) releases <- ref.get } yield { result shouldEqual result releases shouldEqual n } } private def testCancel = { for { released <- Ref.of[IO, Int](0) started <- Deferred[IO, Unit] fiber <- Concurrent[IO].start { ResourceRegistry.of[IO].use { registry => val resource = Resource.make(().pure[IO]) { _ => released.update(_ + 1) } for { _ <- registry.allocate(resource) _ <- started.complete(()) _ <- IO.never.as(()) } yield {} } } _ <- started.get _ <- fiber.cancel released <- released.get } yield { released shouldEqual 1 } } }
Example 28
Source File: StartResource.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal.util import cats.effect._ import cats.effect.concurrent.Deferred import cats.effect.implicits._ import cats.implicits._ object StartResource { def apply[F[_] : Concurrent, A, B]( res: Resource[F, A])( use: A => F[B] ): F[Fiber[F, B]] = { res.allocated.bracketCase { case (a, release) => for { released <- Deferred[F, Unit] fiber <- Concurrent[F].start { use(a).guarantee { release.guarantee { released.complete(()) } } } } yield { new Fiber[F, B] { def cancel = fiber.cancel *> released.get def join = fiber.join } } } { case ((_, release), exitCase) => exitCase match { case ExitCase.Completed => ().pure[F] case _: ExitCase.Error[Throwable] => release case ExitCase.Canceled => release } } } }
Example 29
Source File: TopicCommitTest.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal.replicator import cats.data.{NonEmptyMap => Nem} import cats.implicits._ import cats.effect.{Clock, IO} import com.evolutiongaming.kafka.journal.IOSuite._ import cats.effect.concurrent.{Deferred, Ref} import com.evolutiongaming.skafka.{Offset, Partition} import org.scalatest.funsuite.AsyncFunSuite import org.scalatest.matchers.should.Matchers import scala.concurrent.duration._ class TopicCommitTest extends AsyncFunSuite with Matchers{ test("delayed") { def commitOf( deferred: Deferred[IO, Unit], commitsRef: Ref[IO, List[Nem[Partition, Offset]]])(implicit clock: Clock[IO] ) = { val commit = new TopicCommit[IO] { def apply(offsets: Nem[Partition, Offset]) = { commitsRef.update { offsets :: _ } *> deferred.complete(()) } } TopicCommit.delayed(10.millis, commit) } def clockOf(ref: Ref[IO, FiniteDuration]): Clock[IO] = { new Clock[IO] { def realTime(unit: TimeUnit): IO[Long] = monotonic(unit) def monotonic(unit: TimeUnit): IO[Long] = ref.get.map { _.toUnit(unit).toLong } } } val result = for { commitsRef <- Ref[IO].of(List.empty[Nem[Partition, Offset]]) deferred <- Deferred[IO, Unit] clockRef <- Ref[IO].of(0.millis) clock = clockOf(clockRef) commit <- commitOf(deferred, commitsRef)(clock) _ <- commit(Nem.of((Partition.min, Offset.min))) offsets <- commitsRef.get _ = offsets shouldEqual List.empty _ <- clockRef.set(20.millis) _ <- commit(Nem.of((Partition.unsafe(1), Offset.unsafe(1)))) _ <- deferred.get offsets <- commitsRef.get _ = offsets shouldEqual List(Nem.of((Partition.min, Offset.min), (Partition.unsafe(1), Offset.unsafe(1)))) } yield {} result.run() } }
Example 30
Source File: KafkaSingletonTest.scala From kafka-journal with MIT License | 5 votes |
package com.evolutiongaming.kafka.journal.replicator import cats.data.{NonEmptySet => Nes} import cats.effect.concurrent.{Deferred, Ref} import cats.effect.{Concurrent, IO, Resource, Timer} import cats.implicits._ import com.evolutiongaming.catshelper.Log import com.evolutiongaming.kafka.journal.IOSuite._ import com.evolutiongaming.skafka.consumer.RebalanceListener import com.evolutiongaming.skafka.{Partition, TopicPartition} import com.evolutiongaming.sstream.Stream import org.scalatest.funsuite.AsyncFunSuite import org.scalatest.matchers.should.Matchers import scala.concurrent.duration._ class KafkaSingletonTest extends AsyncFunSuite with Matchers { test("allocate & release when partition assigned or revoked") { `allocate & release when partition assigned or revoked`[IO]().run() } private def `allocate & release when partition assigned or revoked`[F[_] : Concurrent : Timer](): F[Unit] = { val topic = "topic" def consumer(deferred: Deferred[F, RebalanceListener[F]]) = { new TopicConsumer[F] { def subscribe(listener: RebalanceListener[F]) = deferred.complete(listener) def poll = Stream.empty def commit = TopicCommit.empty } } def topicPartition(partition: Partition) = TopicPartition(topic, partition) val result = for { listener <- Resource.liftF(Deferred[F, RebalanceListener[F]]) allocated <- Resource.liftF(Ref[F].of(false)) resource = Resource.make { allocated.set(true) } { _ => allocated.set(false) } singleton <- KafkaSingleton.of(topic, consumer(listener).pure[Resource[F, *]], resource, Log.empty[F]) listener <- Resource.liftF(listener.get) _ <- Resource.liftF { for { a <- singleton.get _ = a shouldEqual none[Unit] a <- allocated.get _ = a shouldEqual false _ <- listener.onPartitionsAssigned(Nes.of(topicPartition(Partition.max))) a <- singleton.get _ = a shouldEqual none[Unit] a <- allocated.get _ = a shouldEqual false _ <- listener.onPartitionsAssigned(Nes.of(topicPartition(Partition.min))) _ <- Timer[F].sleep(10.millis) a <- singleton.get _ = a shouldEqual ().some a <- allocated.get _ = a shouldEqual true _ <- listener.onPartitionsRevoked(Nes.of(topicPartition(Partition.max))) a <- singleton.get _ = a shouldEqual ().some a <- allocated.get _ = a shouldEqual true _ <- listener.onPartitionsRevoked(Nes.of(topicPartition(Partition.min))) _ <- Timer[F].sleep(10.millis) a <- singleton.get _ = a shouldEqual none[Unit] a <- allocated.get _ = a shouldEqual false } yield {} } } yield {} result.use { _ => ().pure[F] } } }
Example 31
Source File: actors.scala From actors-cats-effect-fs2 with Apache License 2.0 | 5 votes |
package app import app.syntax._ import cats.effect.Concurrent import cats.effect.concurrent.{Deferred, Ref} import cats.effect.syntax.concurrent._ import cats.syntax.flatMap._ import cats.syntax.functor._ import fs2.concurrent.Queue object actors { def actor[F[_], S, O]( initialState: S, receive: Ref[F, S] => F[O] )(implicit F: Concurrent[F]): F[F[O]] = for { ref <- Ref.of[F, S](initialState) queue <- Queue.unbounded[F, Deferred[F, O]] fiber <- (for { deferred <- queue.dequeue1 output <- receive(ref) _ <- deferred.complete(output) } yield ()).foreverM.void.start ask = for { deferred <- Deferred[F, O] _ <- queue.offer1(deferred) output <- (fiber.join race deferred.get) .collect { case Right(o) => o } } yield output } yield ask def actorWithInput[F[_], S, I, O]( initialState: S, receive: (I, Ref[F, S]) => F[O] )(implicit F: Concurrent[F]): F[I => F[O]] = for { ref <- Ref.of[F, S](initialState) queue <- Queue.unbounded[F, (I, Deferred[F, O])] fiber <- (for { inputAndDeferred <- queue.dequeue1 (input, deferred) = inputAndDeferred output <- receive(input, ref) _ <- deferred.complete(output) } yield ()).foreverM.void.start ask = (input: I) => for { deferred <- Deferred[F, O] _ <- queue.offer1((input, deferred)) output <- (fiber.join race deferred.get) .collect { case Right(o) => o } } yield output } yield ask }
Example 32
Source File: IOForkInterruptBenchmark.scala From zio with Apache License 2.0 | 5 votes |
package zio import java.util.concurrent.TimeUnit import cats.effect.concurrent.Deferred import org.openjdk.jmh.annotations._ import zio.IOBenchmarks._ @State(Scope.Thread) @BenchmarkMode(Array(Mode.Throughput)) @OutputTimeUnit(TimeUnit.SECONDS) @Warmup(iterations = 10, time = 3, timeUnit = TimeUnit.SECONDS) @Measurement(iterations = 10, time = 3, timeUnit = TimeUnit.SECONDS) @Fork(1) @Threads(1) class IOForkInterruptBenchmark { @Param(Array("100")) var size: Int = _ @Benchmark def monixForkInterrupt(): Unit = { import monix.eval.Task def loop(i: Int): monix.eval.Task[Unit] = if (i < size) Deferred[Task, Unit].flatMap { p1 => Deferred[Task, Unit].flatMap { p2 => p1.complete(()) .flatMap(_ => Task.never) .guarantee(p2.complete(())) .start .flatMap(f => p1.get.flatMap(_ => f.cancel.flatMap(_ => p2.get.flatMap(_ => loop(i + 1))))) } } else Task.unit loop(0).runSyncUnsafe() } @Benchmark def catsForkInterrupt(): Unit = { import cats.effect.IO def loop(i: Int): IO[Unit] = if (i < size) Deferred[IO, Unit].flatMap { p1 => Deferred[IO, Unit].flatMap { p2 => p1.complete(()) .flatMap(_ => IO.never) .guarantee(p2.complete(())) .start .flatMap(f => p1.get.flatMap(_ => f.cancel.flatMap(_ => p2.get.flatMap(_ => loop(i + 1))))) } } else IO.unit loop(0).unsafeRunSync() } @Benchmark def zioForkInterrupt(): Unit = zioForkInterrupt(IOBenchmarks) @Benchmark def zioTracedForkInterrupt(): Unit = zioForkInterrupt(TracedRuntime) private[this] def zioForkInterrupt(runtime: Runtime[Any]): Unit = { def loop(i: Int): UIO[Unit] = if (i < size) IO.never.fork.flatMap(_.interrupt *> loop(i + 1)) else IO.unit runtime.unsafeRun(loop(0)) } }