Skip to content
This repository was archived by the owner on May 25, 2026. It is now read-only.

refactor(db): implement ADR002 DbContext composition pattern - #10

Merged
cherninkiy merged 9 commits into
mainfrom
refactor/dbcontext-composition
May 25, 2026
Merged

refactor(db): implement ADR002 DbContext composition pattern#10
cherninkiy merged 9 commits into
mainfrom
refactor/dbcontext-composition

Conversation

@cherninkiy

Copy link
Copy Markdown
Owner

Summary

This PR refactors the database architecture from a shared AppDbContext inheritance model to a composition pattern using IEntityTypeConfiguration<T>. Each service now owns its own DbContext with only the tables it needs, eliminating code duplication while maintaining clean separation of concerns.

What's Changed

Shared

  • Added Microsoft.EntityFrameworkCore 8.0.x and Microsoft.EntityFrameworkCore.Relational packages
  • Created 5 entity configurations in Shared/Configurations/: DocumentConfiguration, ProcessedMessageConfiguration, OutboxConfiguration, WorkflowCheckpointConfiguration, AgentDefinitionConfiguration
  • Split IDocumentRepository into base interface + IOutboxRepository for Outbox-specific operations
  • Created DocumentRepositoryBase<TContext> in Shared/Repositories/ with common SQL operations (GetById, GetAll, TryUpdateStatus, UpdateText, MarkMessageProcessed, IsMessageProcessed)

ApiGateway

  • Created GatewayDbContext with DbSets for Documents, ProcessedMessages, OutboxMessages
  • Created DocumentRepository implementing both IDocumentRepository and IOutboxRepository
  • Updated OutboxPublisher to use IOutboxRepository instead of IDocumentRepository
  • Updated DocumentService to accept IOutboxRepository for CreateDocumentAsync
  • Updated Program.cs to use GatewayDbContext with EnsureCreated()
  • Updated DI registration to bind both interfaces to the same repository instance

Worker

  • Created WorkerDbContext with DbSets for Documents, ProcessedMessages, WorkflowCheckpoints, AgentDefinitions
  • Created DocumentRepository implementing IDocumentRepository with WorkflowCheckpoint query methods
  • Updated Program.cs to use WorkerDbContext with EnsureCreated()
  • Updated PostgreSqlCheckpointStore to use WorkerDbContext

Tests

  • Updated DocumentServiceTests to mock IOutboxRepository
  • Updated OutboxPublisherTests to mock IOutboxRepository

Cleanup

  • Removed old AppDbContext.cs and DocumentRepository.cs from both ApiGateway and Worker

Testing

  • All 37 tests pass (12 ApiGateway + 21 Worker + 4 Integration)
  • dotnet build — success, no warnings

Related

  • ADR-002: docs/adr/ADR002_DbContext_Composition.md

- define composition approach using IEntityTypeConfiguration<T>
- each service owns its DbSet declarations, shared configs in Shared/
- ApiGateway is migration owner for common tables (documents, processed_messages)
- Worker relies on existing schema, does not create migrations for common tables
- add Microsoft.EntityFrameworkCore 8.0.x and Relational to Shared.csproj
- create IEntityTypeConfiguration<T> for all 5 entities in Shared/Configurations/
- split IDocumentRepository into base interface + IOutboxRepository
- create DocumentRepositoryBase<TContext> with common SQL operations
- create GatewayDbContext in ApiGateway with Documents, ProcessedMessages, OutboxMessages
- create WorkerDbContext in Worker with Documents, ProcessedMessages, WorkflowCheckpoints, AgentDefinitions
- each context applies only its required IEntityTypeConfiguration<T>
- remove old shared AppDbContext
- create ApiGateway DocumentRepository with Outbox support (implements IOutboxRepository)
- create Worker DocumentRepository with WorkflowCheckpoint queries
- both inherit from DocumentRepositoryBase<TContext>
…ucture

- update OutboxPublisher to use IOutboxRepository instead of IDocumentRepository
- update DocumentService to accept IOutboxRepository for CreateDocumentAsync
- update Program.cs to use GatewayDbContext with EnsureCreated
- register both IDocumentRepository and IOutboxRepository in DI
- update Program.cs to use WorkerDbContext with EnsureCreated
- update PostgreSqlCheckpointStore to use WorkerDbContext
- register Worker DocumentRepository in DI
- update DocumentServiceTests to use IOutboxRepository mock
- update OutboxPublisherTests to use IOutboxRepository mock
- fix CreateDocumentAsync test to verify outbox repository call
- delete ApiGateway/Data/AppDbContext.cs (replaced by GatewayDbContext)
- delete ApiGateway/Data/DocumentRepository.cs (replaced by Repositories/DocumentRepository)
- delete Worker/Data/AppDbContext.cs (replaced by WorkerDbContext)
- delete Worker/Data/DocumentRepository.cs (replaced by Repositories/DocumentRepository)

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements ADR-002, transitioning the system from DbContext inheritance to a composition-based approach. It introduces shared entity configurations and a base repository class in the Shared project, while creating service-specific contexts (GatewayDbContext and WorkerDbContext). The ApiGateway repository was split to separate outbox concerns, and various service registrations and tests were updated accordingly. Feedback highlights several critical issues in the shared repository base regarding the incorrect usage of ExecuteSqlRawAsync, where the CancellationToken is being treated as a SQL parameter, and the use of application-side timestamps instead of database functions. Additionally, the ApiGateway startup logic incorrectly uses EnsureCreated() instead of MigrateAsync(), contradicting the ADR. Finally, it is recommended to pin NuGet package versions in the Shared project to ensure build determinism.

Comment thread src/Shared/Repositories/DocumentRepositoryBase.cs Outdated
Comment thread src/Shared/Repositories/DocumentRepositoryBase.cs Outdated
Comment thread src/Shared/Repositories/DocumentRepositoryBase.cs Outdated
Comment thread src/ApiGateway/Program.cs Outdated
Comment thread src/Shared/Shared.csproj Outdated
…MigrateAsync, pin EF Core versions

- replace ExecuteSqlRawAsync with ExecuteSqlInterpolatedAsync in DocumentRepositoryBase
- use NOW() database function instead of DateTime.UtcNow application timestamps
- fix CancellationToken not being passed as SQL parameter (ExecuteSqlInterpolatedAsync handles it correctly)
- replace EnsureCreated() with MigrateAsync() in ApiGateway Program.cs (per ADR-002)
- add IsRelational() guard to support in-memory database in tests
- fix config key format in integration tests (colon instead of double underscore)
- pin Microsoft.EntityFrameworkCore and Relational to 8.0.27 for deterministic builds
@cherninkiy
cherninkiy merged commit 467823f into main May 25, 2026
1 check passed
@cherninkiy
cherninkiy deleted the refactor/dbcontext-composition branch May 25, 2026 07:29
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant