Skip to content

Conversation

@johnsimons
Copy link
Member

@johnsimons johnsimons commented Dec 10, 2025

SQL Persistence Implementation for ServiceControl

Summary

Implements SQL persistence layer for ServiceControl with support for SQL Server, PostgreSQL, and MySQL. Introduces Entity Framework Core-based implementation as an alternative to the existing RavenDB persistence.

Key Changes

Core Persistence Infrastructure (ServiceControl.Persistence.Sql.Core)

  • Entity models and EF Core configurations for all ServiceControl data stores
  • Base ServiceControlDbContextBase with 16 entity sets
  • Abstract base classes for provider-specific implementations (BasePersistence, SqlPersisterSettings)
  • Database migrator interface for schema management

Provider-Specific Implementations

Data Store Implementations

All 19+ persistence interfaces implemented including:

  • Message storage (ErrorMessageDataStore, BodyStorage)
  • Retry management (RetryBatchesDataStore, RetryDocumentDataStore, RetryHistoryDataStore)
  • Monitoring (MonitoringDataStore, CustomChecksDataStore)
  • Configuration (EndpointSettingsStore, QueueAddressStore, NotificationsManager)

Testing

  • Spiked using Testcontainers-based integration tests for all three SQL providers

Design Decisions

Data Modeling

  • GUIDs for primary keys: Ensures global uniqueness and prevents ID conflicts across distributed instances
  • Flat table structure: No foreign key relationships between tables to maximize flexibility and simplify queries
  • JSON + denormalization hybrid: Complex nested objects stored as JSON with critical fields extracted to columns for indexing and efficient filtering
    • Example: FailedMessageEntity stores full ProcessingAttemptsJson but denormalizes LastProcessedAt, MessageType, ExceptionType for query performance
  • Separate message body storage: Message bodies stored in dedicated MessageBodies table to keep primary tables lean and improve query performance
  • Singleton entities: Some entities (e.g., RetryHistoryEntity, NotificationsSettingsEntity) use fixed IDs as they represent single configuration records

Query Optimization

  • Strategic indexes on frequently-filtered columns (status, timestamps, endpoint names)
  • Denormalized fields avoid JSON parsing in WHERE clauses
  • Binary message bodies separated from metadata to reduce table bloat

Best Way to Review

1. Start with the abstractions (understand the architecture)

2. Review the data model (entities represent the domain)

3. Check one provider implementation (SQL Server recommended)

4. Review key data store implementations (focus on complex ones)

5. Spot-check tests (verify integration test coverage)

Migration Notes

  • EF migrations generated for all three providers with identical schema
  • No automatic migration from RavenDB - this is a fresh persistence option
  • Connection string and provider selection via configuration

@johnsimons johnsimons changed the title Adding noop implementations for Sql persistence Adding all implementations for SqlServer, MySql and Postgresql persistence Dec 12, 2025
@johnsimons johnsimons changed the title Adding all implementations for SqlServer, MySql and Postgresql persistence [SPIKE] Adding all implementations for SqlServer, MySql and Postgresql persistence Dec 15, 2025
Refactors the upsert logic in several data stores to leverage EF Core's change tracking more efficiently.

Instead of creating a new entity and then calling Update, the code now fetches the existing entity (if any) and modifies its properties directly.
This reduces the overhead and potential issues associated with detached entities.

The RecoverabilityIngestionUnitOfWork is also updated to use change tracking for FailedMessageEntity updates.

This commit was made on the `john/more_interfaces` branch.
Adds data store and entities required for persisting licensing and throughput data.

This includes adding new tables for licensing metadata, throughput endpoints, and daily throughput data, as well as configurations and a data store implementation to interact with these tables.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants