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

akka.persistence.pg.event.EventStore.scala Maven / Gradle / Ivy

The newest version!
package akka.persistence.pg.event

import java.time.OffsetDateTime

import akka.persistence.pg.{EventStoreConfig, JsonString, PgConfig}
import slick.dbio.Effect.{Read, Transactional}
import slick.jdbc.{ResultSetConcurrency, ResultSetType}

case class Event(
    id: Long,
    persistenceId: String,
    sequenceNr: Long,
    uuid: String,
    created: OffsetDateTime,
    tags: Map[String, String],
    className: String,
    event: JsonString
)

case class StoredEvent(persistenceId: String, event: Any)

trait EventStore {
  self: PgConfig =>

  def eventStoreConfig: EventStoreConfig = pluginConfig.eventStoreConfig

  import driver.api._

  //This is basically just a another mapping on the same journal table, ideally you would create a DB view
  class EventsTable(tag: Tag)
      extends Table[Event](tag, pluginConfig.eventStoreConfig.schemaName, pluginConfig.eventStoreConfig.tableName) {

    def id            = column[Long](pluginConfig.idForQuery)
    def persistenceId = column[String]("persistenceid")
    def sequenceNr    = column[Long]("sequencenr")
    def uuid          = column[String]("uuid")
    def created =
      column[OffsetDateTime]("created")(date2TzTimestampTypeMapper) // use explicit type because slick 3.3.x introduced its own which would use varchar for the db column
    def tags      = column[Map[String, String]]("tags")
    def className = column[String]("manifest")
    def event     = column[JsonString]("event")

    def * = (id, persistenceId, sequenceNr, uuid, created, tags, className, event) <> (Event.tupled, Event.unapply)

  }

  val events: TableQuery[EventsTable] = TableQuery[EventsTable]

  /**
    * find all events for a specific persistenceId
    * @param persistenceId the persistenceId
    */
  def findEvents(persistenceId: String): Query[EventsTable, Event, Seq] =
    events
      .filter(_.persistenceId === persistenceId)
      .filter(_.event.?.isDefined)

  /**
    * find all events starting from a specific id with specific tags
    * @param fromId the id to start from
    * @param tags the tags that must be present
    * @param max maximum number of events to return
    * @return the list of corresponding events
    */
  def findEvents(
      fromId: Long,
      tags: Map[String, String] = Map.empty,
      max: Long = Long.MaxValue
  ): Query[EventsTable, Event, Seq] =
    events
      .filter(_.id >= fromId)
      .filter(_.event.?.isDefined)
      .filter(_.tags @> tags.bind)
      .sortBy(_.id)
      .take(max)

  def allEvents(): DBIOAction[Seq[Event], Streaming[Event], Read with Transactional] =
    findEvents(0).result
      .withStatementParameters(
        rsType = ResultSetType.ForwardOnly,
        rsConcurrency = ResultSetConcurrency.ReadOnly,
        fetchSize = 1000
      )
      .transactionally

  def toDomainEvent[T](e: Event): T = {
    val clazz = Class.forName(e.className)
    eventStoreConfig.eventEncoder.fromJson((e.event, clazz)).asInstanceOf[T]
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy