7.2 KiB
7.2 KiB
sessionId
| sessionId |
|---|
| session-260729-174324-a4dc |
Requirements
Overview & Goals
Currently, write operations (mutations) and EventBus emissions take place inside Repositories. This design poses two main challenges:
- Lack of Transactional Atomicity: Multi-table writes (e.g., creating a channel while simultaneously inserting its order record into
server_item_order) cannot share an atomic database transaction. - Premature / Ghost Events: Events are emitted inside Repositories before confirming whether higher-level multi-step operations or surrounding DB transactions committed successfully.
To solve this, we are refactoring to a lightweight Command/Query separation:
- Services (Commands / Write Operations): Perform write operations, manage SeaORM database transactions (
db.begin()), and emitEventBusevents strictly after transaction commits. - Repositories (Queries / Read Operations): Focus on complex reads, queries, and filters. Event bus emissions are completely removed from Repositories.
Scope
- In Scope:
- Removing
events: Arc<EventBus>fromRepositoryContextandRepositories::new. - Stripping all
.events.emit(...)calls fromCategoryRepository,ChannelRepository,MessageRepository,RoleRepository,ServerRepository,ServerItemOrderRepository, andUserRepository. - Creating/expanding dedicated domain services under
src/services/(ChannelService,ServerService,CategoryService,MessageService,UserService,RoleService) with SeaORM transaction support and post-commit event emissions. - Registering all domain services in
src/services/mod.rsandServices. - Updating Axum HTTP route handlers in
src/routes/to delegate write operations (POST, PUT, DELETE) tostate.serviceswhile keeping read operations (GET) onstate.repositories.
- Removing
- Out of Scope:
- Changing API DTO contracts or client-facing response schemas.
- Modifying underlying SeaORM database entities or table schemas.
Functional Requirements
- FR1: Repositories must be strictly read/query-focused and contain zero event emissions or
EventBusreferences. - FR2: Write mutations (create, update, delete) and permission management must be executed inside domain Services.
- FR3: Multi-step writes (such as creating a server/channel and updating
server_item_order) must execute within an atomic SeaORM transaction (db.begin().await?). - FR4:
EventBusevents must only be emitted after the database transaction successfully commits. - FR5: Axum route handlers must invoke service methods for all state-mutating requests (POST, PUT, DELETE) and repository methods for read requests (GET).
Technical Design
Current Implementation
RepositoryContextinsrc/repositories/mod.rsholds bothdb: DatabaseConnectionandevents: Arc<EventBus>.- Repositories (
ChannelRepository,ServerRepository,CategoryRepository,MessageRepository,UserRepository,RoleRepository,ServerItemOrderRepository) executeactive.insert(),active.update(), and delete operations directly and emit events immediately inside repository methods. - Axum route handlers in
src/routes/*/handlers.rscall repository write methods directly.
Key Decisions
- Command / Query Responsibility Segregation:
- Repositories handle data access, queries, filters, and read models.
- Services handle business logic, transactional boundaries (
db.begin()), and event dispatching.
- Post-Commit Event Emission:
- Events are only emitted after
txn.commit().await?succeeds, preventing ghost/premature events on transaction rollback.
- Events are only emitted after
Proposed Changes & Affected Files
src/repositories/mod.rs& Repository Modules:- Modify
RepositoryContextto removeevents: Arc<EventBus>. - Remove
.events.emit(...)calls from:src/repositories/category.rssrc/repositories/channel.rssrc/repositories/message.rssrc/repositories/role.rssrc/repositories/server.rssrc/repositories/server_item_order.rssrc/repositories/user.rs
- Modify
src/services/Modules:- Expand
src/services/with new service files:channel.rs(ChannelService)server.rs(ServerService)category.rs(CategoryService)message.rs(MessageService)user.rs(UserService)role.rs(RoleService)
- Expand
src/services/mod.rs:- Update
Servicesstruct andServices::newto initialize and expose all domain services.
- Update
src/routes/Handlers:- Update write handlers across
src/routes/{channel,server,category,message,user,role}/handlers.rsto invokestate.services.*.
- Update write handlers across
Architecture Diagram
graph LR
HTTP[Axum Handlers] -->|Write mutations| Services[Domain Services]
HTTP[Read requests] -->|Query/Filter| Repositories[Read Repositories]
Services -->|Transaction & DB mutations| DB[(SeaORM Database)]
Services -->|Post-commit emit| Events[EventBus]
Repositories -->|Read query| DB
Delivery Steps
✓ Step 1: Clean up Repositories and Remove Write Event Emissions
Clean up Repositories and RepositoryContext
- Remove
events: Arc<EventBus>fromRepositoryContextinsrc/repositories/mod.rsand updateRepositories::new. - Strip write event emissions (
self.context.events.emit(...)) from all repositories (CategoryRepository,ChannelRepository,MessageRepository,RoleRepository,ServerRepository,ServerItemOrderRepository,UserRepository). - Ensure repository write methods operate purely on database connections/ActiveModels without triggering event bus emissions.
✓ Step 2: Create Domain Services with Transactional Atomicity and Post-Commit Events
Create Domain Services for Write Operations
- Create domain services in
src/services/for channels, servers, categories, messages, users, and roles (e.g.,ChannelService,ServerService,CategoryService,MessageService,UserService,RoleService). - Implement SeaORM transaction management (
db.begin().await?) in service write methods. - Ensure
EventBusevents are emitted strictly after transaction commits. - Handle multi-table transactional writes such as creating a channel while inserting into
server_item_order.
✓ Step 3: Register Services in Services Container
Register Services in Services Container and Update State/Context
- Update
src/services/mod.rsto include and initialize the new services (channel,server,category,message,user,role) within theServicesstruct andServicesContext. - Expose the updated
Servicescontainer viaAppState/ServicesContext.
✓ Step 4: Refactor Axum HTTP Route Handlers to Use Services
Refactor Axum HTTP Route Handlers
- Update write endpoints (POST, PUT, DELETE) across
src/routes/to invoke service methods onstate.servicesinstead of repositories directly. - Keep read endpoints (GET) using repositories for complex queries, filters, and tree generation.
✓ Step 5: Verification and Testing
Verification and Testing
- Run cargo build/check to ensure clean compilation across all modules.
- Verify integration checks: channel creation populates
server_item_order, events are only triggered upon successful DB transaction commit.