ParanĂ¡

Release Artifacts Snapshot Artifacts

An event sourcing library on top of ZIO

Installation

We publish to maven central so you just have to add this to your build.sbt file:

libraryDependencies += "dev.palanga" %% "parana-core-local" % "version"

To get snapshot releases:

resolvers += "Sonatype OSS Snapshots" at "https://s01.oss.sonatype.org/content/repositories/snapshots",

A tease:

package palanga.examples.groups

import model.*
import commands.*
import events.*
import eventsourcing.*
import palanga.parana.eventsource.*
import palanga.parana.eventsource.local.*
import palanga.parana.journal.*
import zio.*

object app extends ZIOAppDefault:

  override def run = app.provide(groupsLocal, inMemoryJournal)

  private val app =
    for
      groups       <- ZIO.service[EventSource[Group, Command, Event]]
      ((id, _), _) <- groups.empty.ask(Command.Join(User("Palan")))
      _            <- groups.of(id).ask(Command.Join(User("Nube")))
      _            <- groups.of(id).ask(Command.Leave(User("Palan")))
      _            <- groups.of(id).ask(Command.Join(User("Fruchi")))
      _            <- groups.of(id).get
    yield ()

object model:

  case class Group(members: Set[User]):
    def join(user: User): Group  = copy(members = members + user)
    def leave(user: User): Group = copy(members = members - user)

  case class User(name: String)

object commands:
  enum Command:
    case Join(user: User)
    case Leave(user: User)

object events:
  enum Event:
    case Joined(user: User)
    case Left(user: User)

object eventsourcing:

  val groupsLocal =
    EventSourceLocal
      .of[Group, Command, Event](
        { case Command.Join(user) => Group(Set(user)) -> List(Event.Joined(user)) },
        (group, command) =>
          command match
            case Command.Join(user)  => ZIO.succeed(group.join(user) -> List(Event.Joined(user)))
            case Command.Leave(user) => ZIO.succeed(group.leave(user) -> List(Event.Left(user)))
        ,
        { case Event.Joined(user) => Group(Set(user)) },
        (group, event) =>
          event match
            case Event.Joined(user) => Right(group.join(user))
            case Event.Left(user)   => Right(group.leave(user)),
      )
      .makeLayer

  val inMemoryJournal = InMemoryJournal.makeLayer[Event]

You can find more examples under examples folder.

Contributing:

  • To run tests: sbt test