Python-Eventsourcing-CQRS
This project is a Python-based implementation of Domain-Driven Design (DDD), Event Sourcing, and CQRS (Command Query Responsibility Segregation) using the FastAPI framework. It showcases the use of repository and aggregate patterns, emphasizing modularity, scalability, and clean architecture principles.
- Domain-Driven Design (DDD): Clear separation of concerns between domain, application, and infrastructure layers.
- Event Sourcing: Persistence of domain events instead of current state, enabling robust historical tracking and debugging.
- CQRS: Segregation of commands (write operations) and queries (read operations) for better scalability and performance.
- Repository Pattern: Abstracts data storage implementation.
- Aggregate Pattern: Ensures domain integrity and consistency.
└── aliseylaneh-Python-Eventsourcing-CQRS/
├── README.md
├── docker-compose.dev.yml
├── docker-compose.yml
├── main.py
├── pyproject.toml
├── adapter/
├── config/
├── docker/
├── internal/ # Domain logic and core business rules
│ ├── domain/ # DDD Aggregates, Commands, Entities, Events, Exceptions
│ ├── es/ # Event sourcing utilities and services
│ └── modules/ # Use-case and layer implementations
└── ...
-
Domain Layer (
internal/domain/
):- Aggregates: Encapsulates business logic and ensures consistency.
- Commands: Represents domain commands (write operations).
- Entities: Core business objects.
- Events: Domain events for event sourcing.
- Exceptions: Custom exceptions for domain logic.
- Interfaces: Defines contracts (e.g., repositories, use cases).
-
Event Sourcing (
internal/es/
):- Reconstructs the current state by replaying domain events.
-
Modules Layer (
internal/modules/
):- Implements use cases and integrates domain logic with infrastructure.
-
Adapters (
adapter/
):- Infrastructure-related implementations (e.g., MongoDB adapters).
-
Configuration (
config/
):- Configuration utilities (e.g., MongoDB, OpenTelemetry).
- Docker and Docker Compose
-
Clone the repository:
git clone <repository-url> cd aliseylaneh-Python-Eventsourcing-CQRS
-
Start the infrastructure using Docker Compose:
docker-compose up -d
This starts the following services:
- MongoDB: Database for event persistence.
- Mongo-Express: MongoDB web UI (accessible at
http://localhost:8081
). - Elasticsearch: Used for logging and tracing.
- Jaeger: Distributed tracing (accessible at
http://localhost:16686
).
-
Run the application:
uvicorn main:app --reload
The FastAPI application will be available at
http://localhost:8000
.
class AggregateRoot(ABC):
def __init__(self, repository: IInventoryRepository):
self.repository = repository
def commit(self):
self.repository.insert(events=self.events)
def _apply(self, event):
self._when(event=event)
self.events.append(event)
@dataclass
class Inventory:
sku: str = field(default='')
soh: int = field(default=0)
available_quantity: int = field(default=0)
reserved: int = field(default=0)
def set_soh(self, soh: int):
if self.reserved >= soh:
raise ReservedStockInProcess()
self.soh = soh
class MongoDBInventoryUtility(IEventSourcingUtility):
@staticmethod
def recreate_state(repository: IInventoryRepository, sku: str) -> Inventory | None:
events = repository.find(sku=sku)
inventory = Inventory(sku='')
for event in events:
# Process events to recreate state
...
return inventory
MongoDB is used as the primary event store. The default connection details are:
- Host:
localhost
- Port:
27017
- Database:
inventory
- Username:
admin
- Password:
1234
- Jaeger is used for distributed tracing.
- Access the Jaeger UI at
http://localhost:16686
.
- Fork the repository.
- Create a feature branch:
git checkout -b feature-name
. - Commit changes:
git commit -m 'Add feature'
. - Push to the branch:
git push origin feature-name
. - Create a pull request.
For questions or support, please open an issue or reach me by emailing or sending message in LinkedIn.