CQRS and Domain Events for integration

Giorgio Sironi

Giorgio Sironi (@giorgiosironi)

I work for eLife Sciences
  • I'm a developer (writes code, design stuff)
  • Interested in
    • Automated testing and TDD
    • Object-oriented programming
    • Distributed systems

If you are looking at these slides on your pc, press S to see the notes

Context

Context diagram of Onebip components Onebip logo

Implications

  • many different logical and physical databases
  • continuous need for integration e.g. for reporting needs
  • no single services fits the bill

Bloody solutions (1/2)

Mega SQL query
  • on which database, since they are all small?
  • how to avoid thrashing the database machines?
When the ETL job to pull payments into the data warehouse starts, we go down for 10 minutes

Bloody solutions (2/2)

Joining CSV files
  • they become very large with historical data
  • inefficient even on a single day as data could be filtered
  • process of joining and filtering them becomes fragile as a consequence
Every morning at 7am I run a few MongoDB `touch` commands to warm up the database in RAM before the circus starts
Conceptual model of CQRS by @ziobrando
The source-of-truth service: Demetra

It works! Why?

  • there is all the data there, forever
  • decoupling over delivery and calculation of Domain Events
  • consolidation of data processing infrastructure in a single codebase

How: schema


{
    "id": "20ec0521-d127-4038-92ed-a4196c33705b",
    "meta": {
        "service": "core",
        "type": "payment-completed",
        "created_at": "2016-01-01T12:00:00.000Z",
        "received_at": "2016-01-01T12:00:00.200Z",
        "aggregate_id": "payment/23"
        "correlation_id": "container/subscription/42",
    },
    "payload": {
        "amount": "3.0000/EUR",
        ...
    }
}
          

How: technologies

MongoDB PostgreSQL

How: projections


{
    "meta.type": { "$in" : interesting_types },
    "received_at": { "$gt": last_checkpoint, "$lt": stable_timestamp }
}
      

How: processes


      * * * * * www-data /var/www/demetra/bin/demetra projection:my-report
      * * * * * www-data sleep 10 && /var/www/demetra/bin/demetra projection:my-report
      * * * * * www-data sleep 20 && /var/www/demetra/bin/demetra projection:my-report
      ...
      

Issues: delivery


      Request::to('https://source-of-truth.com/events', 'POST')
          ->withTheUsualAuthentication(...)
          ->asOptimisticJob()
          ->ensureIs(200, 409)
          ->retryPolicyIs(ExponentialBackoff::upTo('P1Y'))
          ->send()
      

Issues: out-of-order

  • purchase-landed, created 14:00:00, received 14:02:08 after N retries
  • purchase-completed, created 14:01:50, received 14:01:51

Issues: events are forever

Even James Bond knows

Issues: importing

Excavate dirt (data) and put it into a standard form

Issues: archival

Conclusions

  • Domain Events are non-intrusive
  • A Source Of Truth very often comes up
  • Be prepared

Thanks!

@giorgiosironi @eLife

g.sironi@elifesciences.org

elifesciences.org (of course, we're hiring)