Centralize Postgres connection string policy across all modules
Extract connection string building into PostgresConnectionStringPolicy so all services use consistent pooling, application_name, and timeout settings. Adopt the new policy in 20+ module DataSource/ServiceCollectionExtensions classes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -123,6 +123,7 @@ static IResolutionCacheService CreateResolutionCacheService(IServiceProvider ser
|
||||
redisOptions.ConnectTimeout = 500;
|
||||
redisOptions.SyncTimeout = 500;
|
||||
redisOptions.AsyncTimeout = 500;
|
||||
redisOptions.ClientName ??= "stellaops-binaryindex-resolution-cache";
|
||||
|
||||
var multiplexer = ConnectionMultiplexer.Connect(redisOptions);
|
||||
_ = multiplexer.GetDatabase().Ping();
|
||||
|
||||
@@ -5,6 +5,7 @@ Source of truth: `docs-archived/implplan/2025-12-29-csproj-audit/SPRINT_20251229
|
||||
|
||||
| Task ID | Status | Notes |
|
||||
| --- | --- | --- |
|
||||
| SPRINT_20260405_011-XPORT-VALKEY | DONE | `docs/implplan/SPRINT_20260405_011___Libraries_transport_pooling_and_attribution_hardening.md`: named the BinaryIndex resolution-cache Valkey client. |
|
||||
| QA-BINARYINDEX-VERIFY-029 | DONE | SPRINT_20260211_033 run-001: `patch-coverage-tracking` passed Tier 0/1/2 with patch-coverage controller behavioral evidence (including post-create coverage updates) and was moved to `docs/features/checked/binaryindex/patch-coverage-tracking.md`. |
|
||||
| QA-BINARYINDEX-VERIFY-028 | BLOCKED | SPRINT_20260211_033: `ml-function-embedding-service` is actively owned by another lane (`run-001` in progress); this lane terminalized collision as `skipped` (`owned_by_other_agent`) per FLOW 0.1. |
|
||||
| QA-BINARYINDEX-VERIFY-026 | DONE | SPRINT_20260211_033 run-002: `known-build-binary-catalog` passed Tier 0/1/2 with Build-ID/SHA256/assertion/cache/method-mapping behavioral evidence; dossier verified in `docs/features/checked/binaryindex/known-build-binary-catalog.md`. |
|
||||
|
||||
@@ -10,14 +10,14 @@ namespace StellaOps.BinaryIndex.Validation.Persistence;
|
||||
/// <summary>
|
||||
/// PostgreSQL repository for match results.
|
||||
/// </summary>
|
||||
public sealed class MatchResultRepository : IMatchResultRepository
|
||||
public sealed class MatchResultRepository : IMatchResultRepository, IAsyncDisposable
|
||||
{
|
||||
private readonly string _connectionString;
|
||||
private readonly NpgsqlDataSource _dataSource;
|
||||
private readonly JsonSerializerOptions _jsonOptions;
|
||||
|
||||
public MatchResultRepository(string connectionString)
|
||||
{
|
||||
_connectionString = connectionString;
|
||||
_dataSource = CreateDataSource(connectionString);
|
||||
_jsonOptions = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
|
||||
@@ -30,8 +30,7 @@ public sealed class MatchResultRepository : IMatchResultRepository
|
||||
{
|
||||
if (results.Count == 0) return;
|
||||
|
||||
await using var conn = new NpgsqlConnection(_connectionString);
|
||||
await conn.OpenAsync(ct);
|
||||
await using var conn = await _dataSource.OpenConnectionAsync(ct);
|
||||
|
||||
await using var transaction = await conn.BeginTransactionAsync(ct);
|
||||
|
||||
@@ -105,8 +104,7 @@ public sealed class MatchResultRepository : IMatchResultRepository
|
||||
/// <inheritdoc/>
|
||||
public async Task<IReadOnlyList<MatchResult>> GetForRunAsync(Guid runId, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = new NpgsqlConnection(_connectionString);
|
||||
await conn.OpenAsync(ct);
|
||||
await using var conn = await _dataSource.OpenConnectionAsync(ct);
|
||||
|
||||
const string query = """
|
||||
SELECT
|
||||
@@ -215,4 +213,18 @@ public sealed class MatchResultRepository : IMatchResultRepository
|
||||
string ExpectedName, string? ExpectedDemangledName, long ExpectedAddress, long? ExpectedSize, string ExpectedBuildId, string ExpectedBinaryName,
|
||||
string? ActualName, string? ActualDemangledName, long? ActualAddress, long? ActualSize, string? ActualBuildId, string? ActualBinaryName,
|
||||
string Outcome, double? MatchScore, string? Confidence, string? InferredCause, string? MismatchDetail, double? MatchDurationMs);
|
||||
|
||||
public ValueTask DisposeAsync() => _dataSource.DisposeAsync();
|
||||
|
||||
private static NpgsqlDataSource CreateDataSource(string connectionString)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(connectionString);
|
||||
|
||||
var connectionStringBuilder = new NpgsqlConnectionStringBuilder(connectionString)
|
||||
{
|
||||
ApplicationName = "stellaops-binaryindex-match-results"
|
||||
};
|
||||
|
||||
return new NpgsqlDataSourceBuilder(connectionStringBuilder.ConnectionString).Build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,14 +10,14 @@ namespace StellaOps.BinaryIndex.Validation.Persistence;
|
||||
/// <summary>
|
||||
/// PostgreSQL repository for validation runs.
|
||||
/// </summary>
|
||||
public sealed class ValidationRunRepository : IValidationRunRepository
|
||||
public sealed class ValidationRunRepository : IValidationRunRepository, IAsyncDisposable
|
||||
{
|
||||
private readonly string _connectionString;
|
||||
private readonly NpgsqlDataSource _dataSource;
|
||||
private readonly JsonSerializerOptions _jsonOptions;
|
||||
|
||||
public ValidationRunRepository(string connectionString)
|
||||
{
|
||||
_connectionString = connectionString;
|
||||
_dataSource = CreateDataSource(connectionString);
|
||||
_jsonOptions = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
|
||||
@@ -28,8 +28,7 @@ public sealed class ValidationRunRepository : IValidationRunRepository
|
||||
/// <inheritdoc/>
|
||||
public async Task SaveAsync(ValidationRun run, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = new NpgsqlConnection(_connectionString);
|
||||
await conn.OpenAsync(ct);
|
||||
await using var conn = await _dataSource.OpenConnectionAsync(ct);
|
||||
|
||||
const string upsert = """
|
||||
INSERT INTO groundtruth.validation_runs (
|
||||
@@ -107,8 +106,7 @@ public sealed class ValidationRunRepository : IValidationRunRepository
|
||||
/// <inheritdoc/>
|
||||
public async Task<ValidationRun?> GetAsync(Guid runId, CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = new NpgsqlConnection(_connectionString);
|
||||
await conn.OpenAsync(ct);
|
||||
await using var conn = await _dataSource.OpenConnectionAsync(ct);
|
||||
|
||||
const string query = """
|
||||
SELECT
|
||||
@@ -132,8 +130,7 @@ public sealed class ValidationRunRepository : IValidationRunRepository
|
||||
ValidationRunFilter? filter,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
await using var conn = new NpgsqlConnection(_connectionString);
|
||||
await conn.OpenAsync(ct);
|
||||
await using var conn = await _dataSource.OpenConnectionAsync(ct);
|
||||
|
||||
var sql = new System.Text.StringBuilder("""
|
||||
SELECT id, name, status, created_at, completed_at,
|
||||
@@ -264,4 +261,18 @@ public sealed class ValidationRunRepository : IValidationRunRepository
|
||||
private sealed record ValidationRunSummaryRow(
|
||||
Guid Id, string Name, string Status, DateTimeOffset CreatedAt, DateTimeOffset? CompletedAt,
|
||||
double? MatchRate, double? F1Score, int? PairCount, int? FunctionCount, string[]? Tags);
|
||||
|
||||
public ValueTask DisposeAsync() => _dataSource.DisposeAsync();
|
||||
|
||||
private static NpgsqlDataSource CreateDataSource(string connectionString)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(connectionString);
|
||||
|
||||
var connectionStringBuilder = new NpgsqlConnectionStringBuilder(connectionString)
|
||||
{
|
||||
ApplicationName = "stellaops-binaryindex-validation-runs"
|
||||
};
|
||||
|
||||
return new NpgsqlDataSourceBuilder(connectionStringBuilder.ConnectionString).Build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ Source of truth: `docs/implplan/SPRINT_20260130_002_Tools_csproj_remediation_sol
|
||||
|
||||
| Task ID | Status | Notes |
|
||||
| --- | --- | --- |
|
||||
| SPRINT_20260405_011-XPORT | DONE | `docs/implplan/SPRINT_20260405_011___Libraries_transport_pooling_and_attribution_hardening.md`: named reusable PostgreSQL data sources for validation-run and match-result persistence. |
|
||||
| QA-BINARYINDEX-VERIFY-023 | BLOCKED | SPRINT_20260211_033 run-001: blocked because `AGENTS.md` is missing in this module and related validation modules/tests (repo AGENTS rule 5). |
|
||||
| REMED-05 | TODO | Remediation checklist: docs/implplan/audits/csproj-standards/remediation/checklists/src/BinaryIndex/__Libraries/StellaOps.BinaryIndex.Validation/StellaOps.BinaryIndex.Validation.md. |
|
||||
| REMED-06 | DONE | SOLID review notes captured for SPRINT_20260130_002. |
|
||||
|
||||
Reference in New Issue
Block a user