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

codata.async.mutable.Topic.scala Maven / Gradle / Ivy

package org.specs2.codata.async.mutable

import org.specs2.codata.Cause._
import org.specs2.codata.{Sink,Process,Cause}
import scalaz.concurrent.Task


/**
 * Represents topic, that asynchronously exchanges messages between one or more publisher(s)
 * and one or more subscriber(s).
 *
 * Guarantees:
 * - Order of messages from publisher is guaranteed to be preserved to all subscribers
 * - Messages from publishers may interleave in non deterministic order before they are read by subscribers
 * - Once the `subscriber` is run it will receive all messages from all `publishers` starting with very first message
 *   arrived AFTER the subscriber was run
 *
 * Please note that topic is `active` even when there are no publishers or subscribers attached to it. However
 * once the `close` or `fail` is called all the publishers and subscribers will terminate or fail.
 *
 * Once topic if closed or failed, all new publish or subscribe attempts will fail with reason that was used to
 * close or fail the topic.
 *
 */
trait Topic[A] {



  /**
   * Gets publisher to this topic. There may be multiple publishers to this topic.
   */
  def publish: Sink[Task, A]

  /**
   * Gets subscriber from this topic. There may be multiple subscribers to this topic. Subscriber
   * subscribes and un-subscribes when it is run or terminated.
   * @return
   */
  def subscribe: Process[Task, A]

  /**
   * publishes single `A` to this topic.
   */
  def publishOne(a:A) : Task[Unit]

  /**
   * Will `close` this topic. Once `closed` all publishers and subscribers are halted via `End`.
   * When this topic is `closed` or `failed` this is no-op
   *
   * The resulting task is completed _after_ all publishers and subscribers are signalled with `End`
   *
   * @return
   */
  def close: Task[Unit] = failWithCause(End)

  /**
   * Causes this topic to be closed and all subscribers to this topic to be killed immediately.
   *
   * he resulting task is completed _after_ all publishers and subscribers are signalled with `Kill`
   *
   * @return
   */
  def kill: Task[Unit] = failWithCause(Kill)

  /**
   * Will `fail` this topic. Once `failed` all publishers and subscribers will terminate with cause `err`.
   * When this topic is `finished` or `failed` this is no-op
   *
   * The resulting task is completed _after_ all publishers and subscribers are signalled with `err`
   *
   */
  def fail(rsn: Throwable): Task[Unit] = failWithCause(Error(rsn))


  private[codata] def failWithCause(c:Cause): Task[Unit]


}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy