Top Banner
Concursus Event Sourcing Evolved GOTO London 2016
44

GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Apr 16, 2017

Download

Technology

opencredo
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

ConcursusEvent Sourcing EvolvedGOTO  London  2016

Page 2: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Introductions

Dominic Fox

Twitter: @dynamic_proxy

Email: [email protected]

Tareq Abedrabbo

Twitter: @tareq_abedrabbo

Email: [email protected]

Concursus

Page: https://opencredo.com/publications/concursus/

Github: http://github.com/opencredo/concursus

Page 3: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Agenda• History

• Concepts

• Example

• Domain model

• Processing model

• Programming model

• Future directions

Page 4: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

What is Concursus?

A toolkit for processing and organising messy data in an distributed context.

Page 5: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

The Concursus TimelineObservations

Conception and design

Prototype

Open source implementation

Technical report and blogs

Page 6: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Event Sourcing

“Event Sourcing ensures that all changes to application state are stored as a sequence of events. Not just can we query these events, we can also use the event log to reconstruct past states, and as a foundation to automatically adjust the state to cope with retroactive changes.”

http://martinfowler.com/eaaDev/EventSourcing.html

Page 7: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

What is Concursus?Problems Concursus addresses:

ü Processing events in a scalable and reliable way

ü Processing guarantees and ordering: exactly once, out of order, repeated or missed delivery, etc..

ü Building meaningful domain models to reason about and build business logic around

ü Flexibility: building additional views as needed

Page 8: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Tendencies:

• From internet of users to internet of things

• From “presence” to “presents”

• From monoliths to microservices

Why Concursus?

Page 9: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

From Internet of Users to Internet of Things

Page 10: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

From Presence to Presents

Page 11: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

From Monoliths to Microservices

Page 12: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

“Write First, Reason Later”

2016-­‐10-­‐12  09:06:31.432Received  at  Depot

2016-­‐10-­‐12  09:06:32.106Received  at  Depot

2016-­‐10-­‐12  09:06:34.740Received  at  Depot

2016-­‐10-­‐12  11:35:02.163Loaded  onto  Truck

2016-­‐10-­‐12  11:40:21.032Loaded  onto  Truck

2016-­‐10-­‐12  11:38:51.204Loaded  onto  Truck

2016-­‐10-­‐12  14:12:44.021Delivery  Failed

2016-­‐10-­‐12  15:00:31.322Delivered

2016-­‐10-­‐12  15:11:05.038Delivered

Page 13: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

“Write First, Reason Later”

Page 14: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Handling Eventsü Delivery constraints

out of order, repeated, delayed or missed delivery

ü Processing guarantees

at least once or exactly once processing, idempotency

ü Ordering

partial ordering across aggregates (with reasonable assumptions)

Page 15: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Data Processing Layersü Durable

sufficiently durable buffer for async processing (what’s happening)

ü Persistent

a permanent record of everything that has happened (what happened)

ü Transient

fast and consistent, but also disposable state (what happens)

Page 16: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Building Blocks• Java 8 and Kotlin: APIs

• Cassandra: Persistent state (Event store)

• Kafka: Durable state (Message broker)

• Hazelcast: Transient state (cache, idempotency filters)

• Also, RabbitMQ and Redis

Page 17: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Sources of InspirationStream processing frameworks such as Apache Storm and Spark

Google papers: Cloud dataflow, MillWheel

Apache Spark papers

The Axon CQRS framework

Domain Driven Design

Functional programming

Page 18: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Summary

Concursus=

Event sourcing+

Stream processing+

Bounded contexts (DDD)+

Distributed computing

Page 19: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Received  atDepot

Loaded  onto  Truck

Delivered

Delivery  Failed

Page 20: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Domain Model: Events

Received  atDepot

Loaded  ontoTruck

DeliveryFailed

Received  atDepot

Loaded  ontoTruck

Delivered

Page 21: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

aggregateType: parcelaggregateId: 69016fb5-1d69-4a34-910b-f8ff5c702ad9

eventTimestamp: 2016-03-31 10:31:17.981parameters: { “depotId”: “Lewisham” }

Domain Model: Events

Received  atDepot

Loaded  ontoTruck

DeliveryFailed

Received  atDepot

Loaded  ontoTruck

Delivered

Page 22: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

aggregateType: parcelaggregateId: 69016fb5-1d69-4a34-910b-f8ff5c702ad9

eventTimestamp: 2016-03-38 08:15:23.104parameters: { “truckId”: “J98 257” }

Domain Model: Events

Received  atDepot

Loaded  ontoTruck

DeliveryFailed

Received  atDepot

Loaded  ontoTruck

Delivered

Page 23: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

eventTimestamp: 2016-03-31T10:36:42.171ZprocessingTimestamp: 2016-03-31T10:36:48.3904Zparameters: { “deliveryAddress”: “123 SudburyAvenue, Droitwich DR4 8PQ”}

Domain Model: EventsaggregateType: parcelaggregateId: 69016fb5-1d69-4a34-910b-f8ff5c702ad9

Received  at  Depot

Loaded  onto  Truck

Delivery  Failed

Received  at  Depot

Loaded  onto  Truck

Delivered

Page 24: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Domain Model: SummaryEvery Event occurs to an Aggregate, identified by its type and id.Every Event has an eventTimestamp, generated by the source of the event.An Event History is a log of Events, ordered by eventTimestamp, with an additional processingTimestamp which records when the Event was captured.

Page 25: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Network

Event sources Event processors

Events arrive:• Partitioned• Interleaved• Out-of-order

Processing Model: Ordering

Page 26: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Log is:• Partitioned by aggregate id• Ordered by event timestamp

Processing Model: Ordering

Page 27: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

CREATE  TABLE  IF  NOT  EXISTS  concursus.Event (aggregateType text,aggregateId text,eventTimestamp timestamp,streamId text,processingId timeuuid,name  text,version  text,parameters  map<text,  text>,characteristics  int,PRIMARY  KEY((aggregateType,  aggregateId),  eventTimestamp,  

streamId))  WITH  CLUSTERING  ORDER  BY  (eventTimestamp DESC);

Cassandra Schema

Page 28: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

CassandraEvent Store

RabbitMQ Topic

DownstreamprocessingLog

events

Publish events

Cassandra & AMQP

Page 29: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

CassandraEvent Store

RabbitMQ Topic

Downstreamprocessing

out-of-order events

ordered query results

Cassandra & AMQP

Page 30: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

CassandraEvent Store

Kafka Topic

Downstreamprocessing

Event store listener

Publish events

Log events

Cassandra & Kafka

Page 31: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Processing Model: SummaryEvents arrive partitioned, interleaved and out-of-order.Events are sorted into event histories by aggregate type and id.Events are sorted within event histories by event timestamp, not processing timestamp.Event consumers need to take into account the possibility that an event history may be incomplete at the time it is read – consider using a watermark to give incoming events time to “settle”.

Page 32: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Programming Model: Core Metaphor

Received  atDepot

Loaded  ontoTruck

DeliveryFailed

Received  atDepot

Loaded  ontoTruck

Delivered

Page 33: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Received  atDepot

Loaded  ontoTruck

DeliveryFailed

Received  atDepot

Loaded  ontoTruck

Delivered

Consumer<Event>

Programming Model: Core Metaphor

Page 34: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

You give me a Consumer<Event>, and I send Events to it one at a time:

Emitting Events

Page 35: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

I implement Consumer<Event>, and handle Events that are sent to me.

Handling Events

Page 36: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Java 8 Mapping

Page 37: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Java 8 Mapping

Page 38: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Java 8 Mapping

Page 39: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Kotlin Mapping

sealed  class  ParcelEvent {class  ReceivedAtDepot(val depotId:  String):  ParcelEvent()class  LoadedOntoTruck(val truckId:  String):  ParcelEvent()class  Delivered(val destinationId:  String):  ParcelEvent()class  DeliveryFailed():  ParcelEvent()

}

Page 40: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Kotlin Mapping

eventBus.dispatchTo(parcelId,ReceivedAtDepot(depotId =  "Lewisham Depot")  at  start,LoadedOntoLorry(lorryId =  "Truck  CU50  ZCV")  at  

start.plus(2,  DAYS))

Page 41: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Kotlin Mapping

fun  describeEvent(event:  ParcelEvent):  Unit  =  when  (event)  {is  ReceivedAtDepot -­‐>  println("Received  at  depot:  

${event.depotId}")is  LoadedOntoTruck -­‐>  println("Loaded  onto  truck:  

${event.truckId}")is  Delivered  -­‐>  println("Delivered  to:  

${event.destinationId}")is  DeliveryFailed -­‐>  println("Delivery  failed")

}

Page 42: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Event-handling middleware is a chain of Consumer<Event>s that transforms, routes, persists and dispatches events. A single event submitted to this chain may be:■ Checked against an idempotency filter (e.g. a Hazelcast distributed cache)■ Serialised to JSON■ Written to a message queue topic■ Retrieved from the topic and deserialised■ Persisted to an event store (e.g. Cassandra)■ Published to an event handler which maintains a query-optimised view of part of the system■ Published to an event handler which maintains an index of aggregates by event property

values (e.g. lightbulbs by wattage)

Event-Handling Middleware

Page 43: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

• Kafka Streams

• Narrative threads across event histories

• Generic Attribute indexing

• State management and caching

• Improved cloud tooling

Future Directions

Page 44: GOTO LONDON 2016: Concursus Event sourcing Evolved (Updated)

Thank you for listeningAny questions?