--- 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: 1. **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. 2. **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 emit `EventBus` events 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` from `RepositoryContext` and `Repositories::new`. - Stripping all `.events.emit(...)` calls from `CategoryRepository`, `ChannelRepository`, `MessageRepository`, `RoleRepository`, `ServerRepository`, `ServerItemOrderRepository`, and `UserRepository`. - 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.rs` and `Services`. - Updating Axum HTTP route handlers in `src/routes/` to delegate write operations (POST, PUT, DELETE) to `state.services` while keeping read operations (GET) on `state.repositories`. - **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 `EventBus` references. - **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**: `EventBus` events 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 - `RepositoryContext` in `src/repositories/mod.rs` holds both `db: DatabaseConnection` and `events: Arc`. - Repositories (`ChannelRepository`, `ServerRepository`, `CategoryRepository`, `MessageRepository`, `UserRepository`, `RoleRepository`, `ServerItemOrderRepository`) execute `active.insert()`, `active.update()`, and delete operations directly and emit events immediately inside repository methods. - Axum route handlers in `src/routes/*/handlers.rs` call repository write methods directly. ### Key Decisions 1. **Command / Query Responsibility Segregation**: - Repositories handle data access, queries, filters, and read models. - Services handle business logic, transactional boundaries (`db.begin()`), and event dispatching. 2. **Post-Commit Event Emission**: - Events are only emitted after `txn.commit().await?` succeeds, preventing ghost/premature events on transaction rollback. ### Proposed Changes & Affected Files 1. **`src/repositories/mod.rs` & Repository Modules**: - Modify `RepositoryContext` to remove `events: Arc`. - Remove `.events.emit(...)` calls from: - `src/repositories/category.rs` - `src/repositories/channel.rs` - `src/repositories/message.rs` - `src/repositories/role.rs` - `src/repositories/server.rs` - `src/repositories/server_item_order.rs` - `src/repositories/user.rs` 2. **`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`) 3. **`src/services/mod.rs`**: - Update `Services` struct and `Services::new` to initialize and expose all domain services. 4. **`src/routes/` Handlers**: - Update write handlers across `src/routes/{channel,server,category,message,user,role}/handlers.rs` to invoke `state.services.*`. ### Architecture Diagram ```mermaid 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` from `RepositoryContext` in `src/repositories/mod.rs` and update `Repositories::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 `EventBus` events 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.rs` to include and initialize the new services (`channel`, `server`, `category`, `message`, `user`, `role`) within the `Services` struct and `ServicesContext`. - Expose the updated `Services` container via `AppState` / `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 on `state.services` instead 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.