Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event...

51
Exploring Lightweight Event Sourcing Erik Rozendaal <[email protected] > @erikrozendaal

Transcript of Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event...

Page 1: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring Lightweight Event Sourcing

Erik Rozendaal <[email protected]>@erikrozendaal

Page 2: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Goals

• Understand event sourcing

• Show why Scala is well-suited as implementation language

2

Page 3: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Event Sourcing

• Documented by Martin Fowler at http://martinfowler.com/eaaDev/EventSourcing.html (2005)

• Made practical by Greg Young (QCon 2008)

• Applied to complex, high volume systems (financial trading)

• But what about small systems?

3

Page 4: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

• Domain-Driven Design An approach to software development that suggests that (1) For most software projects, the primary focus should be on the domain and domain logic; and (2) Complex domain designs should be based on a model.

• Domain Expert A member of a software project whose field is the domain of the application, rather than software development. Not just any user of the software, the domain expert has deep knowledge of the subject.

• Ubiquitous Language A language structured around the domain model and used by all team members to connect all the activities of the team with the software.

4

Page 5: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Durability

5

Page 6: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Durability

• Most applications require durability of data

5

Page 7: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Durability

• Most applications require durability of data

• UPDATE invoice WHERE id = 1234 SET total_amount = 230

5

Page 8: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Durability

• Most applications require durability of data

• UPDATE invoice WHERE id = 1234 SET total_amount = 230

• What happened to previous order amount?

5

Page 9: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Durability

• Most applications require durability of data

• UPDATE invoice WHERE id = 1234 SET total_amount = 230

• What happened to previous order amount?

• What was the reason for the change?

5

Page 10: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

ORMs

• Query and persist current state in DB

• Tightly couples domain and data model

• Leaky abstraction

• Still “lossy” and the intent of the user is not captured

6

Page 11: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Behavior?

7

Page 12: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Invoice

Status: "Draft"

Total: 0.00

Behavior?

7

Page 13: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Invoice

Status: "Draft"

Total: 0.00 Invoice

Status: "Draft"

Recipient: "Erik"

Total: 0.00

Behavior?

7

Page 14: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Invoice

Status: "Draft"

Recipient: "Erik"

Invoice Item

Total: 9.95

Item: "Food"

Amount: 9.95

Invoice

Status: "Draft"

Total: 0.00 Invoice

Status: "Draft"

Recipient: "Erik"

Total: 0.00

Behavior?

7

Page 15: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Invoice

Status: "Draft"

Recipient: "Erik"

Invoice Item

Total: 9.95

Item: "Food"

Amount: 9.95

Invoice

Status: "Draft"

Total: 0.00 Invoice

Status: "Draft"

Recipient: "Erik"

Total: 0.00

It’s just data mutation

8

Page 16: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Invoice

Status: "Draft"

Recipient: "Erik"

Invoice Item

Total: 9.95

Item: "Food"

Amount: 9.95

It’s just data mutation

8

Page 17: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

“Inexperienced programmers love magic because it saves their time. Experienced programmers hate magic because it wastes their time.” – @natpryce

9

ORM implementation

Page 18: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Event Sourcing

10

• All state changes are explicitly captured using domain events

• Events represent the outcome of behavior

• Capture the intent of the user and the related data

• The domain expert understands and can explain the meaning of the domain events

Page 19: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Domain Behavior

11

Page 20: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Draft Invoice Created

create

Domain Behavior

11

Page 21: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Invoice

Status: "Draft"

Total: 0.00

Draft Invoice Created

create

apply

Domain Behavior

11

Page 22: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Invoice

Status: "Draft"

Total: 0.00

Draft Invoice Created

Recipient: "Erik"

Invoice Recipient Changed

create

createapply

Domain Behavior

11

Page 23: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Invoice

Status: "Draft"

Total: 0.00 Invoice

Status: "Draft"

Recipient: "Erik"

Total: 0.00

Draft Invoice Created

Recipient: "Erik"

Invoice Recipient Changed

create

createapply apply

Domain Behavior

11

Page 24: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Invoice

Status: "Draft"

Total: 0.00 Invoice

Status: "Draft"

Recipient: "Erik"

Total: 0.00

Draft Invoice Created

Recipient: "Erik"

Invoice Recipient Changed

Item: "Food"Item amount: 9.95Total amount: 9.95

Invoice Item Added

create

create createapply apply

Domain Behavior

11

Page 25: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Invoice

Status: "Draft"

Recipient: "Erik"

Invoice Item

Total: 9.95

Item: "Food"

Amount: 9.95

Invoice

Status: "Draft"

Total: 0.00 Invoice

Status: "Draft"

Recipient: "Erik"

Total: 0.00

Draft Invoice Created

Recipient: "Erik"

Invoice Recipient Changed

Item: "Food"Item amount: 9.95Total amount: 9.95

Invoice Item Added

create

create createapply apply apply

Domain Behavior

11

Page 26: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Invoice

Status: "Draft"

Recipient: "Erik"

Invoice Item

Total: 9.95

Item: "Food"

Amount: 9.95

Invoice

Status: "Draft"

Total: 0.00 Invoice

Status: "Draft"

Recipient: "Erik"

Total: 0.00

Draft Invoice Created

Recipient: "Erik"

Invoice Recipient Changed

Item: "Food"Item amount: 9.95Total amount: 9.95

Invoice Item Added

Only the events are stored on disk

12

Page 27: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Reloading from history

13

Page 28: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Invoice

Status: "Draft"

Total: 0.00

Draft Invoice Created

apply

Reloading from history

13

Page 29: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Invoice

Status: "Draft"

Total: 0.00 Invoice

Status: "Draft"

Recipient: "Erik"

Total: 0.00

Draft Invoice Created

Recipient: "Erik"

Invoice Recipient Changed

apply apply

Reloading from history

13

Page 30: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Invoice

Status: "Draft"

Recipient: "Erik"

Invoice Item

Total: 9.95

Item: "Food"

Amount: 9.95

Invoice

Status: "Draft"

Total: 0.00 Invoice

Status: "Draft"

Recipient: "Erik"

Total: 0.00

Draft Invoice Created

Recipient: "Erik"

Invoice Recipient Changed

Item: "Food"Item amount: 9.95Total amount: 9.95

Invoice Item Added

apply apply apply

Reloading from history

13

Page 31: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Invoice

Status: "Draft"

Recipient: "Erik"

Invoice Item

Total: 9.95

Item: "Food"

Amount: 9.95

Invoice

Status: "Draft"

Total: 0.00 Invoice

Status: "Draft"

Recipient: "Erik"

Total: 0.00

Draft Invoice Created

Recipient: "Erik"

Invoice Recipient Changed

Item: "Food"Item amount: 9.95Total amount: 9.95

Invoice Item Added

apply apply apply

Reloading from history

13

Page 32: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Aggregates

• A cluster of associated objects that are treated as a unit for the purpose of data changes

• Each aggregate has its own stream of events

• Consistency boundary

14

Page 33: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Aggregates

Invoice

Status: "Draft"

Recipient: "Erik"

Invoice Item

Total: 9.95

Item: "Food"

Amount: 9.95

15

Page 34: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Aggregates

Invoice

Status: "Draft"

Recipient: "Erik"

Invoice Item

Total: 9.95

Item: "Food"

Amount: 9.95

15

Draft Invoice Created

Recipient: "Erik"

Invoice Recipient Changed

Item: "Food"Item amount: 9.95Total amount: 9.95

Invoice Item Added

Page 35: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Event Store

16

• Stores sequence of events per aggregate

• Dispatches events when successfully committed

• Replays events on startup

• It’s your application’s transaction log

Page 36: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Event Store

• No good for queries!

• Use separate views or reports that use the domain events to capture answers to queries

17

Page 37: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Domain Code

18

sealed trait InvoiceEventcase class InvoiceCreated() extends InvoiceEventcase class InvoiceRecipientChanged(recipient: String) extends InvoiceEventcase class InvoiceItemAdded(item: InvoiceItem, totalAmount: BigDecimal) extends InvoiceEventcase class InvoiceSent(sentOn: LocalDate, paymentDueOn: LocalDate) extends InvoiceEvent

Page 38: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Domain Code

18

sealed trait InvoiceEventcase class InvoiceCreated() extends InvoiceEventcase class InvoiceRecipientChanged(recipient: String) extends InvoiceEventcase class InvoiceItemAdded(item: InvoiceItem, totalAmount: BigDecimal) extends InvoiceEventcase class InvoiceSent(sentOn: LocalDate, paymentDueOn: LocalDate) extends InvoiceEvent

sealed trait Invoice extends AggregateRoot { protected[this] type Event = InvoiceEvent}

Page 39: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Domain Code

19

case class DraftInvoice( recipient: Option[String] = None, nextItemId: Int = 1, items: Map[Int, InvoiceItem] = Map.empty) extends Invoice {

def changeRecipient(recipient: String): Behavior[DraftInvoice] = ...

def addItem(description: String, amount: BigDecimal): Behavior[DraftInvoice] = ...

def send(sentOn: LocalDate): Behavior[Either[String, SentInvoice]] = ...

...

private def recipientChanged = when[InvoiceRecipientChanged] { event => copy(recipient = Some(event.recipient)) } private def itemAdded = when[InvoiceItemAdded] { event => copy(nextItemId = event.item.id + 1, items = items + (event.item.id -> event.item)) } private def sent = when[InvoiceSent] { event => SentInvoice(event.sentOn, event.paymentDueOn) }

}

Page 40: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Domain Code

19

case class DraftInvoice( recipient: Option[String] = None, nextItemId: Int = 1, items: Map[Int, InvoiceItem] = Map.empty) extends Invoice {

def changeRecipient(recipient: String): Behavior[DraftInvoice] = ...

def addItem(description: String, amount: BigDecimal): Behavior[DraftInvoice] = ...

def send(sentOn: LocalDate): Behavior[Either[String, SentInvoice]] = ...

...

private def recipientChanged = when[InvoiceRecipientChanged] { event => copy(recipient = Some(event.recipient)) } private def itemAdded = when[InvoiceItemAdded] { event => copy(nextItemId = event.item.id + 1, items = items + (event.item.id -> event.item)) } private def sent = when[InvoiceSent] { event => SentInvoice(event.sentOn, event.paymentDueOn) }

}

The “Brains”

Page 41: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Domain Code

19

case class DraftInvoice( recipient: Option[String] = None, nextItemId: Int = 1, items: Map[Int, InvoiceItem] = Map.empty) extends Invoice {

def changeRecipient(recipient: String): Behavior[DraftInvoice] = ...

def addItem(description: String, amount: BigDecimal): Behavior[DraftInvoice] = ...

def send(sentOn: LocalDate): Behavior[Either[String, SentInvoice]] = ...

...

private def recipientChanged = when[InvoiceRecipientChanged] { event => copy(recipient = Some(event.recipient)) } private def itemAdded = when[InvoiceItemAdded] { event => copy(nextItemId = event.item.id + 1, items = items + (event.item.id -> event.item)) } private def sent = when[InvoiceSent] { event => SentInvoice(event.sentOn, event.paymentDueOn) }

}

The “Brains”

The “Muscle”

Page 42: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Domain Code

20

case class DraftInvoice( recipient: Option[String] = None, nextItemId: Int = 1, items: Map[Int, InvoiceItem] = Map.empty) extends Invoice {

def changeRecipient(recipient: String): Behavior[DraftInvoice] = recipientChanged(InvoiceRecipientChanged(recipient))

def addItem(description: String, amount: BigDecimal): Behavior[DraftInvoice] = itemAdded(InvoiceItemAdded(InvoiceItem(nextItemId, description, amount), totalAmount + amount))

def send(sentOn: LocalDate): Behavior[Either[String, SentInvoice]] = if (readyToSend_?) for (updated <- sent(InvoiceSent(sentOn, paymentDueOn = sentOn.plusDays(14)))) yield Right(updated) else pure(Left("invoice not ready to send"))

private def totalAmount = items.values.map(_.amount).sum

private def readyToSend_? = recipient.isDefined && items.nonEmpty

...}

Page 43: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Domain Code

21

case class DraftInvoice( recipient: Option[String] = None, nextItemId: Int = 1, items: Map[Int, InvoiceItem] = Map.empty) extends Invoice {

...

protected[this] def applyEvent = recipientChanged orElse itemAdded orElse sent

...}

Page 44: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Minimal Infrastructure

• Store only the domain events, replay these on application startup to reconstruct current state

• Keep the current state in-memory

• Use immutability data to reduce need for cloning or locking

22

Page 45: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Simple functionality example

• “CRUD”: no domain logic, so no aggregate

• So we’ll persist events directly from the UI

• Useful to get started

• ... and even complex applications still contain simple functionality

23

Page 46: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Aggregate Example

24

Page 47: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Implementation Limitations

• Serializing (“big lock”) event store

• ~ 50 transactions per second

• Number of events to replay on startup

• ~ 30.000 JSON serialized events per second

• Total number of objects to store in main memory

• JVM can run with large heaps

25

Page 48: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

But ready to scale

• Advanced event store implementations support SQL, MongoDB, Amazon SimpleDB, etc.

• Use persisted view model for high volume objects (fixes startup time and memory usage)

• Easy partitioning of aggregates (consistency boundary with unique identifier)

• Load aggregates on-demand, use snapshotting

26

Page 49: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

Conclusion

• Event Sourcing captures full historical information

• Fully encapsulated domain code highly decoupled from persistence mechanism

• Simpler to implement and fully understand than traditional ORM based approach

• “Paradigm” shift towards Event-Driven

27

Page 50: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Thanks!

Page 51: Exploring Lightweight Event Sourcing - Scaladays2011.scala-lang.org/sites/days2011/files/50. Event sourcing.pdfExploring lightweight event sourcing • Domain-Driven Design An approach

Exploring lightweight event sourcing

References• Example code https://github.com/erikrozendaal/scala-event-sourcing-example

• CQRS http://cqrsinfo.com/

• Greg Young, “Unshackle Your Domain”http://www.infoq.com/presentations/greg-young-unshackle-qcon08

• Pat Helland, “Life Beyond Distributed Transactions: An Apostate's Opinion” http://www.ics.uci.edu/~cs223/papers/cidr07p15.pdf

• Erik Rozendaal, “Towards an immutable domain model” http://blog.zilverline.com/2011/02/10/towards-an-immutable-domain-model-monads-part-5/

• Frameworks: http://www.axonframework.org/ (Java) and http://ncqrs.org/ (.NET)

• Event store: https://github.com/joliver/EventStore (.NET) with over 20 supported data stores

29