Slide 1

Slide 1 text

SAGAS OF ELIXIR

Slide 2

Slide 2 text

ABOUT ME ▸ 14 years in IT, Elixir dev for 2+ years ▸ Worked on NHS of Ukraine and few other large projects ▸ Maintain 20+ public Elixir repos used in production ▸ Contribute back as much as I can

Slide 3

Slide 3 text

WE ARE GOING TO TALK ABOUT ▸ Why do we need distributed transactions? ▸ Sagas pattern ▸ Sage Elixir library ▸ Structuring your domain contexts (bonus)

Slide 4

Slide 4 text

IMAGINE WE ARE BUILDING A SIMPLE BOOKING WEBSITE Invariants: - We should not charge card if request was not fulfilled - We should not hold booking if charge is failed

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

WITH COMPILES TO NESTED CASES

Slide 7

Slide 7 text

HANDLING FAILURES

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

LET'S MAKE IT HARDER

Slide 10

Slide 10 text

OOPS, FAILED TO BOOK A FLIGHT

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

WHAT IS WRONG? ▸ Bad for latency - can't book concurrently ▸ The syntax to track step on which failure occurred is ugly ▸ To test it you need a complex failure injection for API client stubs ▸ Easy to miss some errors - monster else clause

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

DISTRIBUTED TRANSACTIONS ARE EVERYWHERE ▸ CRM and Campaign Automation (Salesforce, Hubspot, Intercom, Autopilot) ▸ Payment Processors (Stripe, Braintree, PayPal) ▸ Analytics (GA, Mixpanel) ▸ Cloud Providers (Google Cloud, AWS) ▸ Any other SaaS integration ▸ Microservices

Slide 15

Slide 15 text

CAN WE DO BETTER? ▸ Refactor ▸ 2PC ▸ Sagas

Slide 16

Slide 16 text

SAGAS PATTERN Failure management pattern that originates from 1987’s paper on long running transactions for databases. A long lived transaction is a Saga if it can be written as a sequence of transactions that can be interleaved with other transactions. The database management system guarantees that either all the transactions in a Saga are successfully completed or compensating transactions are run to amend a partial execution.

Slide 17

Slide 17 text

HOW DOES IT WORK? ▸ Transaction is split into a multiple atomic steps ▸ Each step consist from transaction and compensation ▸ When transaction fails compensation are run to semantically amend it's effects ▸ Compensation and transactions should be idempotent

Slide 18

Slide 18 text

BOOKING SITE WITH SAGAS

Slide 19

Slide 19 text

AWESOME! ANYTHING FOR ELIXIR?

Slide 20

Slide 20 text

SAGE Sage is a dependency-free pure Elixir library inspired by Sagas pattern. Provides set of additional features on top of steps, transactions and compensations defined by the original paper.

Slide 21

Slide 21 text

It's like Ecto.Multi but across business logic and third-party APIs. — @jayjun from #elixir-lang Slack channel

Slide 22

Slide 22 text

BOOKING EXAMPLE WITH SAGE

Slide 23

Slide 23 text

ASYNCHRONOUS TRANSACTIONS

Slide 24

Slide 24 text

RETRIES

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

CIRCUIT BREAKERS

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

AND MORE ▸ Final callback ▸ Tracing ▸ Easier to test ▸ Works with Ecto

Slide 29

Slide 29 text

ERROR HANDLING ▸ Sage transaction abort ▸ Compensation failure ▸ Bugs in Sage

Slide 30

Slide 30 text

THINGS TO COME ▸ Saga execution log ▸ Compile-time type checking

Slide 31

Slide 31 text

AND IT MAKES YOUR DOMAIN CONTEXTS BETTER

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

RECAP Use Sage to: ▸ Synchronize state across microservices ▸ Synchronize state across databases ▸ To run distributed transactions Sage can help to elegantly organize logic in your domain contexts. Still young but well-documented and covered with tests.

Slide 34

Slide 34 text

THANK YOU! QUESTIONS? github.com/nebo15/sage GitHub: AndrewDryga Twitter: andrew_dryga Elixir-Lang Slack: AndrewDryga Email: [email protected]