All Downloads are FREE. Search and download functionalities are using the official Maven repository.

polynote.kernel.util.Publish.scala Maven / Gradle / Ivy

The newest version!
package polynote.kernel.util

import zio.{Chunk, ZHub, ZIO, ZQueue}
import zio.stream.Take

/**
  * Captures only the ability to Publish, but without the ability to subscribe. This means it can
  * be contravariant.
  */
trait Publish[-R, +E, -T] {

  def publish(t: T): ZIO[R, E, Unit]

  def publishAll(ts: Iterable[T]): ZIO[R, E, Unit] = ZIO.foreach_(ts)(publish)

  def contramap[U](fn: U => T): Publish[R, E, U] = new Publish[R, E, U] {
    override def publish(t: U): ZIO[R, E, Unit] = Publish.this.publish(fn(t))
  }

  def contraFlatMap[R1 <: R, E1 >: E, U](fn: U => ZIO[R1, E1, T]): Publish[R1, E1, U] = new Publish[R1, E1, U] {
    override def publish(t: U): ZIO[R1, E1, Unit] = fn(t).flatMap(u => Publish.this.publish(u))
  }

  def tap[R1 <: R, E1 >: E, T1 <: T](into: T1 => ZIO[R1, E1, Unit]): Publish[R1, E1, T1] = new Publish[R1, E1, T1] {
    def publish(t: T1): ZIO[R1, E1, Unit] = Publish.this.publish(t) *> into(t)
  }

  def tap[R1 <: R, E1 >: E, T1 <: T](into: Publish[R1, E1, T1]): Publish[R1, E1, T1] = new Publish[R1, E1, T1] {
    def publish(t: T1): ZIO[R1, E1, Unit] = Publish.this.publish(t) *> into.publish(t)
  }

  def catchAll[R1 <: R](fn: E => ZIO[R1, Nothing, Unit]): Publish[R1, Nothing, T] = new Publish[R1, Nothing, T] {
    override def publish(t: T): ZIO[R1, Nothing, Unit] = Publish.this.publish(t).catchAll(fn)
  }

  def provide(env: R): Publish[Any, E, T] = new Publish[Any, E, T] {
    override def publish(t: T): ZIO[Any, E, Unit] = Publish.this.publish(t).provide(env)
  }

}

object Publish {
  
  def fn[R, E, T](fn: T => ZIO[R, E, Unit]): Publish[R, E, T] = new Publish[R, E, T] {
    override def publish(t: T): ZIO[R, E, Unit] = fn(t)
  }

  final case class PublishZHub[-RA, -RB, +EA, +EB, -A, +B](hub: ZHub[RA, RB, EA, EB, A, B]) extends Publish[RA, EA, A] {
    override def publish(t: A): ZIO[RA, EA, Unit] = ZIO.unlessM(hub.isShutdown)(hub.publish(t).flip.retryUntilEquals(true).flip.unit)
    override def publishAll(ts: Iterable[A]): ZIO[RA, EA, Unit] = ZIO.unlessM(hub.isShutdown)(hub.publishAll(ts).flip.retryUntilEquals(true).flip.unit)
  }

  implicit def zHubToPublish[RA, RB, EA, EB, A, B](hub: ZHub[RA, RB, EA, EB, A, B]): Publish[RA, EA, A] = PublishZHub(hub)

  def apply[RA, RB, EA, EB, A, B](hub: ZHub[RA, RB, EA, EB, A, B]): Publish[RA, EA, A] = PublishZHub(hub)

  def ignore[T]: Publish[Any, Nothing, T] = fn(_ => ZIO.unit)

  final case class PublishZQueueTake[RA, EA, RB, EB, ET <: EA, A, B](queue: ZQueue[RA, RB, EA, EB, Take[ET, A], B]) extends Publish[RA, EA, A] {
    override def publish(t: A): ZIO[RA, EA, Unit] = queue.offer(Take.single(t)).flip.retryUntilEquals(true).flip.unit
    override def publishAll(ts: Iterable[A]): ZIO[RA, EA, Unit] = queue.offer(Take.chunk(Chunk.fromIterable(ts))).flip.retryUntilEquals(true).flip.unit
  }

  implicit def zqueueTakeToPublish[RA, RB, EA, EB, ET <: EA, A, B](queue: ZQueue[RA, RB, EA, EB, Take[ET, A], B]): Publish[RA, EA, A] = PublishZQueueTake(queue)

  def apply[E, E1 <: E, A](queue: zio.Queue[Take[E1, A]])(implicit dummyImplicit: DummyImplicit): Publish[Any, E1, A] = PublishZQueueTake(queue)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy