This project is a reactive microservices system built using Kotlin, Spring Boot, and Gradle. It leverages Apache Kafka for event-driven communication and Apache Cassandra for data persistence. The entire system is containerized using Docker.
The system follows several architectural design patterns:
- Command Query Responsibility Segregation (CQRS)
- Event Sourcing
- Event-Driven Architecture
- Domain-Driven Design (DDD)
- Reactive Microservices
- Hexagonal Architecture
The microservices in the system are designed following the Hexagonal Architecture.
The interaction between the Customer MS and the Reservation MS is primarily event-driven, with domain events being published into Kafka topics. This approach ensures loose coupling between the services and promotes scalability and resilience.
-
Customer Registration: A
CustomerRegistered
event is published to a Kafka topic when a new customer is registered. -
Reservation Request: A
CustomerReservationRequested
event is published to a Kafka topic when a customer makes a reservation request. The Reservation MS initiates the reservation process upon receiving the event. -
Reservation Confirmation or Declination: The Reservation MS either confirms or declines the reservation based on the availability of the requested time slot. It then publishes a
ReservationAccepted
orReservationDeclined
event to a Kafka topic. The Customer MS updates the customer's reservation status accordingly. -
Time Slot Management: The Reservation MS manages time slots. When a time slot is booked, updated, or created, corresponding events (
TimeSlotBooked
,TimeSlotUpdated
,TimeSlotCreated
) are published to Kafka topics.
There is no direct communication between the Customer MS and the Reservation MS via REST APIs. All interactions are asynchronous and event-driven, which allows each service to operate independently and handle its own failures.
The Customer Microservice is designed to handle all operations related to customers. The microservice follows the principles of Domain-Driven Design (DDD) and Event Sourcing.
The main aggregate in the Customer Microservice is the Customer
aggregate. It is represented by two
states: EmptyCustomer
and ExistingCustomer
.
EmptyCustomer
represents a customer that is not yet registered in the system.ExistingCustomer
represents a customer that is already registered in the system.
The Customer
aggregate handles commands such
as RegisterCustomer
, RequestNewCustomerReservation
, UpdateCustomerReservationAsConfirmed
,
and UpdateCustomerReservationAsDeclined
. These commands trigger events that change the state of the Customer
aggregate.
The main API in the Customer Microservice is the CustomerApi
. It uses the AggregateManager
to handle the customer's
commands and events. It also provides a method to find a customer by their ID.
The CustomerCommand
API defines the commands that can be executed on the Customer
aggregate. These commands
include RegisterCustomer
, RequestNewCustomerReservation
, UpdateCustomerReservationAsConfirmed
,
and UpdateCustomerReservationAsDeclined
.
The CustomerEvent
API defines the events that can occur in the lifecycle of a Customer
aggregate. These events
include CustomerRegistered
, CustomerReservationRequested
, CustomerReservationConfirmed
,
and CustomerReservationDeclined
.
The basic use cases in the Customer Microservice are represented by the RegisterCustomerUseCase
and ReservationToCustomerUseCase
classes.
-
RegisterCustomerUseCase
is responsible for the registration use case of a customer. It uses theAggregateManager
to handle the customer's commands and events. It also uses theCustomerView
to check if a customer already exists before registration. -
ReservationToCustomerUseCase
is responsible for handling reservation use cases. It listens to reservation events and updates theCustomer
aggregate accordingly. It handles events such asReservationAccepted
andReservationDeclined
.
The Reservation Microservice is designed to handle all operations related to reservations. The microservice is designed following the principles of Domain-Driven Design (DDD) and Event Sourcing.
The Reservation Microservice has two main aggregates:
-
ReservationAggregate: This aggregate is responsible for handling all operations related to a reservation. It includes commands such as
RequestReservation
,AcceptReservation
, andDeclineReservation
, and events such asReservationRequested
,ReservationAccepted
, andReservationDeclined
. -
TimeSlotAggregate: This aggregate is responsible for managing time slots. It includes commands such as
BookTimeSlot
,CreateTimeSlot
, andUpdateTimeSlot
, and events such asTimeSlotBooked
,TimeSlotCreated
, andTimeSlotUpdated
.
The Reservation Microservice exposes APIs for managing reservations and time slots:
-
ReservationApi: This API allows executing commands on the
ReservationAggregate
and retrieving reservation documents by their ID. -
TimeSlotApi: This API allows executing commands on the
TimeSlotAggregate
, retrieving time slot documents by their ID, and finding time slots between specific times.
The Reservation Microservice has several basic UseCases:
-
CustomerToReservationUseCase: This UseCase handles the creation of a reservation when a
CustomerReservationRequested
event is received from the Customer Microservice. -
TimeSlotToReservationUseCase: This UseCase handles the booking of a time slot when a
ReservationRequested
event is received from the Reservation Microservice. If no time slot is available, the reservation is declined. -
ReservationToTimeSlotUseCase: This UseCase handles the booking of a time slot when a
ReservationRequested
event is received. If the time slot is already booked, the reservation is declined.
Copyright (2024) Michal Zeman, zeman.michal@yahoo.com
Licensed under the Creative Commons Attribution (CC BY) license. You are free to share, copy, distribute, and adapt this work, provided you give appropriate credit to the original author Michal Zeman, zeman.michal@yahoo.com.
To view a copy of the license, visit https://creativecommons.org/licenses/by/4.0/