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

akka.persistence.eventstore.Helpers.scala Maven / Gradle / Ivy

package akka.persistence.eventstore

import scala.concurrent.{ ExecutionContext, Future }
import eventstore._

object Helpers {
  type Timestamp = Long
  type PersistenceId = String
  type SequenceNr = Long

  def eventNumber(x: SequenceNr): EventNumber.Exact = EventNumber.Exact(x.toIntOrError - 1)

  def sequenceNumber(x: EventNumber.Exact): SequenceNr = x.value.toLong + 1

  sealed trait Batch {
    def events: List[Event]
  }

  object Batch {
    val Empty: Batch = Last(Nil)

    def apply(x: ReadStreamEventsCompleted): Batch =
      if (x.endOfStream) Last(x.events)
      else NotLast(x.events, x.nextEventNumber)

    case class Last(events: List[Event]) extends Batch
    case class NotLast(events: List[Event], next: EventNumber) extends Batch
  }

  implicit class RichLong(val self: Long) extends AnyVal {
    def toIntOrError: Int =
      if (self == Long.MaxValue) Int.MaxValue
      else {
        if (self.isValidInt) self.toInt
        else sys.error(s"Cannot convert $self to Int")
      }
  }

  implicit class RichConnection(val self: EsConnection) extends AnyVal {
    def foldLeft[T](req: ReadStreamEvents, default: T)(pf: PartialFunction[(T, Event), T])(implicit ex: ExecutionContext): Future[T] = {

      import Batch._

      def readBatch(req: ReadStreamEvents): Future[Batch] = {
        self.future(req).map(Batch(_)).recover {
          case _: StreamNotFoundException => Batch.Empty
        }
      }

      def loop(events: List[Event], t: T, quit: T => Future[T]): Future[T] = events match {
        case Nil     => quit(t)
        case x :: xs => pf.lift(t -> x).fold(Future.successful(t))(loop(xs, _, quit))
      }

      def foldLeft(from: EventNumber, t: T): Future[T] = {
        readBatch(req.copy(fromNumber = from)).flatMap {
          case Last(events)          => loop(events, t, Future.successful)
          case NotLast(events, from) => loop(events, t, foldLeft(from, _))
        }
      }

      foldLeft(req.fromNumber, default)
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy