Skip to content

Instantly share code, notes, and snippets.

@t3hnar
Created September 4, 2012 18:52
Show Gist options
  • Save t3hnar/3624972 to your computer and use it in GitHub Desktop.
Save t3hnar/3624972 to your computer and use it in GitHub Desktop.
Very simple example of event sourcing
object blog {
object events {
sealed trait PostEvent
case class PostCreated(title: String) extends PostEvent
case class PostRenamed(id: Long, name: String) extends PostEvent
class EventStream() {
val es = new ListBuffer[PostEvent]
def commit(ev: PostEvent) { es += ev }
}
val stream = new EventStream()
}
object domain {
import events._
case class Post(id: Long, title: String)
case class Comment(id: Long, author: String, text: String)
object Posts {
def current: Posts = (Posts() /: stream.es)(_ apply _)
def mostRecent(n: Int): Seq[Post] = current.map.values.takeRight(n).toSeq
}
case class Posts(map: Map[Long, Post] = Map()) {
def apply(event: PostEvent): Posts = event match {
case PostCreated(title) => copy(map = this.map + (nextId -> Post(nextId, title)))
case PostRenamed(id, newTitle) => copy(map = map + (id -> map(id).copy(title = newTitle)))
}
lazy val nextId: Long = map.keys.lastOption.map(_ + 1) getOrElse 0
}
}
object readmodel {
import domain._
def lastPost: Option[Post] = Posts.mostRecent(1).headOption
}
}
object BlogClient extends App {
import blog._
import domain._
import events._
require(readmodel.lastPost == None)
stream.commit(PostCreated("My post"))
require(readmodel.lastPost == Some(Post(0, "My post")))
stream.commit(PostRenamed(0, "My first post"))
require(readmodel.lastPost == Some(Post(0, "My first post")))
stream.commit(PostCreated("My second post"))
require(readmodel.lastPost == Some(Post(1, "My second post")))
stream.commit(PostRenamed(1, "My best post"))
require(readmodel.lastPost == Some(Post(1, "My best post")))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment