Eventuate Tram Customers and Orders Examples

repository·master·Indexed 20 days ago

https://github.com/eventuate-tram/eventuate-tram-examples-customers-and-orders

An example implementation of a microservices architecture using the Eventuate Tram framework. It demonstrates the use of choreography-based Sagas for distributed transactions and CQRS for complex queries across service boundaries, featuring a Customer Service, Order Service, and Order History Service. Includes guides for local testing with Skaffold, deployment to Azure via Terraform and AKS, and transactional messaging using Change Data Capture (CDC) with Apache Kafka.

Tokens
2.5K
Snippets
13
Records
18
Agent score
72%

What's inside eventuate-tram-examples-customers-and-orders

  1. Understand the Customer Service capabilities and API

    master

    The Customer Service is responsible for managing customers and their available credit. It provides a synchronous command API and publishes events to specific event channels to communicate state changes to other services.

    ### Service API
    
    **Synchronous Commands:**
    * `createCustomer()`
    
    **Events Published (Customer event channel):**
    * `Credit Reserved`
    * `Credit Reservation Failed`
    * `Customer Validation Failed`
  2. Understand the Order Service API and capabilities

    master

    The Order Service is responsible for managing orders. It provides synchronous command and query APIs and publishes events to an order event channel. It also subscribes to events from the Customer event channel to react to customer-related changes.

    ### Service API
    
    **Commands (Synchronous):**
    * `createOrder()`
    * `cancelOrder()`
    
    **Queries (Synchronous):**
    * `getOrder()`
    
    **Events Published (Order event channel):**
    * `Order Created`
    * `Order Approved`
    * `Order Rejected`
    
    **Subscribed Events (Customer event channel):**
    * `Credit Reserved`
    * `Credit Reservation Failed`
    * `Customer Validation Failed`
  3. How Sagas and CQRS are implemented in this project

    master

    This project demonstrates two microservices patterns:

    Choreography-based Sagas

    Used to maintain data consistency across services (Order Service and Customer Service). Instead of a central orchestrator, services use domain events to coordinate. Example: The Create Order Saga

    1. Order Service: Creates an Order in PENDING state and publishes OrderCreated.
    2. Customer Service: Receives OrderCreated, attempts to reserve credit, and publishes either Credit Reserved or CreditLimitExceeded.
    3. Order Service: Receives the result and updates the order state to APPROVED or REJECTED.

    CQRS (Command Query Responsibility Segregation)

    Used to implement queries that retrieve data from multiple services. Example: Order History Service The Order History Service maintains a queryable replica of data in MongoDB. It subscribes to domain events from both the Order Service and Customer Service to build a view that stores customer information alongside their order details in a single document.

  4. Transactional messaging with Eventuate Tram

    master

    The services use the Eventuate Tram framework for asynchronous communication via events. The framework ensures atomicity between database updates and event publishing using the following flow:

    1. Local Transaction: Eventuate Tram inserts events into a MESSAGE table as part of the same ACID transaction that updates the JPA entity.
    2. CDC (Change Data Capture): The Eventuate Tram CDC service tracks inserts into the MESSAGE table (using MySQL binlog or Postgres WAL) and publishes those messages to Apache Kafka.
    3. Consumption: A subscribing service receives the event from Kafka, updates its own database, and may publish further events.
  5. Interact with the application via curl

    master

    Once the application is running, you can interact with the services through the API Gateway. Note that you must replace 8080 with the actual port assigned to the API Gateway during startup.

    Common tasks include creating customers, creating orders, checking order status, and querying order history.

    # 1. Create a customer
    curl -X POST --header "Content-Type: application/json" -d '{
      "creditLimit": {
        "amount": 5
      },
      "name": "Jane Doe"
    }' http://localhost:8080/customers
    
    # 2. Create an order
    curl -X POST --header "Content-Type: application/json" -d '{
      "customerId": 1,
      "orderTotal": {
        "amount": 4
      }
    }' http://localhost:8080/orders
    
    # 3. Check order status
    curl -X GET http://localhost:8080/orders/1
    
    # 4. Check customer order history (CQRS view)
    curl -X GET --header "Accept: */*" "http://localhost:8080/customers/1/orderhistory"
  6. Build and run the Customers and Orders application

    master

    To start the application along with all required infrastructure services (databases, Kafka, etc.), use the Gradle wrapper. You can choose between MySQL or Postgres as the underlying database. The command will start containers on unique ports and print the home page URL, which contains links to the Swagger UIs and the API Gateway.

    # Using MySQL
    ./gradlew :end-to-end-tests:runApplicationMySQL
    
    # Using Postgres
    ./gradlew :end-to-end-tests:runApplicationPostgres
  7. Clean up Azure and Kubernetes resources

    master

    To avoid ongoing costs, perform the cleanup in the following order:

    1. Delete the main Kubernetes resources.
    2. Delete the Ingress Controller.
    3. Destroy the Terraform-managed Azure resources.
    # 1. Delete main Kubernetes resources
    ./deployment/terraform_azure/terraform_azure-k8s-delete.sh
    
    # 2. Delete the Ingress Controller
    ./deployment/terraform_azure/terraform_azure-k8s-delete-ingress-controller.sh
    
    # 3. Destroy Terraform resources
    ./deployment/terraform_azure/terraform_azure-destroy.sh