Giter VIP home page Giter VIP logo

saga-orchestration-go's Introduction

Saga Orchestration Pattern: Use Case Implementation

Transactional Outbox + Change Data Capture with Debezium
Tech Stack: Golang and Apache Kafka

This use case demonstrates how to implement the SAGA Pattern to achieve distributed transactions across multiple microservices, assuming the implementation utilizes a Database per Service approach. The solution employs the Transactional Outbox Pattern in conjunction with Change Data Capture (CDC) and Debezium on top of Kafka Connect, and, Apache Kafka serves as the messaging backbone for the overall architecture.

Context:

Use case: As a guest, I want to make a hotel reservation

There are 3 microservices involved:

  • Reservation Service - initiator and orchestrator of the Saga
  • Hotel Service - ensure the hotel's room requested is available and book it or rejects it if unavailable
  • Payment Service - executes the payment associated to an incoming reservation

And we have the following service configuration: Context Overview

Task:

Use the SAGA Orchestration Pattern to ensure data consistency between services.

Implementation

The reservation process is as follows: Reservation State

The SAGA framework state machine happy path: SagaStateMachine

A detailed component workflow: Use Case Overview

A happy path for making a reservation is illustrated in the following sequence diagram: Happy Path

An unhappy path of making a reservation, when the payment is rejected, and the compensation step is involved you can see in the following sequence diagram: Unhappy Path

Running the Use Case

Start the docker compose (docker-compose.yaml)

/src % docker-compose up --build

During the build process there is a kafka-setup service which creates kafka topics and submit the debezium connectors

Make a reservation

% http POST http://localhost:8080/api/v1/reservations < e2e/room-reservation-placement.json

HTTP/1.1 202
Location: http://localhost:8080/api/v1/reservations/6656d80e-edf0-42ab-b114-ced902bafa36
Retry-After: 0.5

Examine the emitted event for room-booking.inbox.events in Apache Kafka:

% docker run --tty --rm \
    --network go-saga-orchestration-network \
    quay.io/debezium/tooling:1.2 \
    kafkacat -b kafka:9092 -C -o beginning -q \
    -f "{\"key\":%k, \"headers\":\"%h\"}\n%s\n" \
    -t room-booking.inbox.events 
    
{"key":057ceada-02b3-4a65-beb3-3de54d6e29f3, "headers":"id=aed1882e-c6d2-402c-985f-e40d19d4df43,eventType=REQUEST"}
{"type":"REQUEST","roomId":1,"endDate":"2023-12-17","guestId":10000001,"hotelId":1,"startDate":"2023-12-16","paymentDue":1702632793441,"creditCardNo":"************7999","reservationId":"6656d80e-edf0-42ab-b114-ced902bafa36"}

and, the emitted event for payment.inbox.events in Apache Kafka:

% docker run --tty --rm \
    --network go-saga-orchestration-network \
    quay.io/debezium/tooling:1.2 \
    kafkacat -b kafka:9092 -C -o beginning -q \
    -f "{\"key\":%k, \"headers\":\"%h\"}\n%s\n" \
    -t payment.inbox.events 
    
{"key":057ceada-02b3-4a65-beb3-3de54d6e29f3, "headers":"id=e3280316-16b8-4114-98ee-9443d523d2ea,eventType=REQUEST"}
{"type":"REQUEST","roomId":1,"endDate":"2023-12-17","guestId":10000001,"hotelId":1,"startDate":"2023-12-16","paymentDue":1702632793441,"creditCardNo":"************7999","reservationId":"6656d80e-edf0-42ab-b114-ced902bafa36"}

Query the saga state in the reservation service's database:

% docker run --tty --rm -i \
        --network go-saga-orchestration-network \
        quay.io/debezium/tooling:1.2 \
        bash -c 'pgcli postgresql://reservationuser:secret@reservation-db:5432/reservationdb'

SELECT * FROM public.sagastate;

+--------------------------------------+-----------+------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------+-------------------------------------------------------+---------------+
| id                                   | version   | type             | payload                                                                                                                                                                                                                                           | current_step   | step_status                                           | saga_status   |
|--------------------------------------+-----------+------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------+-------------------------------------------------------+---------------|
| 057ceada-02b3-4a65-beb3-3de54d6e29f3 | 3         | room-reservation | {"type": "REQUEST", "roomId": 1, "endDate": "2023-12-17", "guestId": 10000001, "hotelId": 1, "startDate": "2023-12-16", "paymentDue": 1702632793441, "creditCardNo": "************7999", "reservationId": "6656d80e-edf0-42ab-b114-ced902bafa36"} |                | {"payment": "SUCCEEDED", "room-booking": "SUCCEEDED"} | COMPLETED     |
+--------------------------------------+-----------+------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------+-------------------------------------------------------+---------------+

And, also, query the location URL:

% http GET http://localhost:8080/api/v1/reservations/6656d80e-edf0-42ab-b114-ced902bafa36 
HTTP/1.1 200 
Content-Type: application/json

{
    "guestId": 10000001,
    "hotelId": 1,
    "reservationId": "6656d80e-edf0-42ab-b114-ced902bafa36",
    "roomId": 1,
    "status": "SUCCEED"
}

Checkout e2e folder with some unhappy scenarios

saga-orchestration-go's People

Contributors

semotpan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.