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:
master
2026-04-06 08:51:04 +03:00
parent 517fa0a92d
commit ccdfd41e4f
64 changed files with 625 additions and 178 deletions

View File

@@ -11,16 +11,16 @@ namespace StellaOps.Concelier.ProofService.Postgres;
/// PostgreSQL implementation of distro advisory repository.
/// Queries the vuln.distro_advisories table for CVE + package evidence.
/// </summary>
public sealed class PostgresDistroAdvisoryRepository : IDistroAdvisoryRepository
public sealed class PostgresDistroAdvisoryRepository : IDistroAdvisoryRepository, IAsyncDisposable
{
private readonly string _connectionString;
private readonly NpgsqlDataSource _dataSource;
private readonly ILogger<PostgresDistroAdvisoryRepository> _logger;
public PostgresDistroAdvisoryRepository(
string connectionString,
ILogger<PostgresDistroAdvisoryRepository> logger)
{
_connectionString = connectionString;
_dataSource = CreateDataSource(connectionString);
_logger = logger;
}
@@ -48,8 +48,7 @@ public sealed class PostgresDistroAdvisoryRepository : IDistroAdvisoryRepository
try
{
await using var connection = new NpgsqlConnection(_connectionString);
await connection.OpenAsync(ct);
await using var connection = await _dataSource.OpenConnectionAsync(ct);
var result = await connection.QuerySingleOrDefaultAsync<DistroAdvisoryDto>(
new CommandDefinition(sql, new { CveId = cveId, PackagePurl = packagePurl }, cancellationToken: ct));
@@ -71,4 +70,18 @@ public sealed class PostgresDistroAdvisoryRepository : IDistroAdvisoryRepository
throw;
}
}
public ValueTask DisposeAsync() => _dataSource.DisposeAsync();
private static NpgsqlDataSource CreateDataSource(string connectionString)
{
ArgumentException.ThrowIfNullOrWhiteSpace(connectionString);
var connectionStringBuilder = new NpgsqlConnectionStringBuilder(connectionString)
{
ApplicationName = "stellaops-concelier-proofservice-distro-advisories"
};
return new NpgsqlDataSourceBuilder(connectionStringBuilder.ConnectionString).Build();
}
}

View File

@@ -11,16 +11,16 @@ namespace StellaOps.Concelier.ProofService.Postgres;
/// PostgreSQL implementation of patch repository.
/// Queries vuln.patch_evidence and feedser.binary_fingerprints tables.
/// </summary>
public sealed class PostgresPatchRepository : IPatchRepository
public sealed class PostgresPatchRepository : IPatchRepository, IAsyncDisposable
{
private readonly string _connectionString;
private readonly NpgsqlDataSource _dataSource;
private readonly ILogger<PostgresPatchRepository> _logger;
public PostgresPatchRepository(
string connectionString,
ILogger<PostgresPatchRepository> logger)
{
_connectionString = connectionString;
_dataSource = CreateDataSource(connectionString);
_logger = logger;
}
@@ -45,8 +45,7 @@ public sealed class PostgresPatchRepository : IPatchRepository
try
{
await using var connection = new NpgsqlConnection(_connectionString);
await connection.OpenAsync(ct);
await using var connection = await _dataSource.OpenConnectionAsync(ct);
var results = await connection.QueryAsync<PatchHeaderDto>(
new CommandDefinition(sql, new { CveId = cveId }, cancellationToken: ct));
@@ -89,8 +88,7 @@ public sealed class PostgresPatchRepository : IPatchRepository
try
{
await using var connection = new NpgsqlConnection(_connectionString);
await connection.OpenAsync(ct);
await using var connection = await _dataSource.OpenConnectionAsync(ct);
var results = await connection.QueryAsync<PatchSigDto>(
new CommandDefinition(sql, new { CveId = cveId }, cancellationToken: ct));
@@ -144,8 +142,7 @@ public sealed class PostgresPatchRepository : IPatchRepository
try
{
await using var connection = new NpgsqlConnection(_connectionString);
await connection.OpenAsync(ct);
await using var connection = await _dataSource.OpenConnectionAsync(ct);
var results = await connection.QueryAsync<BinaryFingerprintRow>(
new CommandDefinition(sql, new { CveId = cveId }, cancellationToken: ct));
@@ -206,4 +203,18 @@ public sealed class PostgresPatchRepository : IPatchRepository
public required DateTimeOffset ExtractedAt { get; init; }
public required string ExtractorVersion { get; init; }
}
public ValueTask DisposeAsync() => _dataSource.DisposeAsync();
private static NpgsqlDataSource CreateDataSource(string connectionString)
{
ArgumentException.ThrowIfNullOrWhiteSpace(connectionString);
var connectionStringBuilder = new NpgsqlConnectionStringBuilder(connectionString)
{
ApplicationName = "stellaops-concelier-proofservice-patches"
};
return new NpgsqlDataSourceBuilder(connectionStringBuilder.ConnectionString).Build();
}
}

View File

@@ -10,16 +10,16 @@ namespace StellaOps.Concelier.ProofService.Postgres;
/// PostgreSQL implementation of source artifact repository.
/// Queries vuln.changelog_evidence for CVE mentions in changelogs.
/// </summary>
public sealed class PostgresSourceArtifactRepository : ISourceArtifactRepository
public sealed class PostgresSourceArtifactRepository : ISourceArtifactRepository, IAsyncDisposable
{
private readonly string _connectionString;
private readonly NpgsqlDataSource _dataSource;
private readonly ILogger<PostgresSourceArtifactRepository> _logger;
public PostgresSourceArtifactRepository(
string connectionString,
ILogger<PostgresSourceArtifactRepository> logger)
{
_connectionString = connectionString;
_dataSource = CreateDataSource(connectionString);
_logger = logger;
}
@@ -46,8 +46,7 @@ public sealed class PostgresSourceArtifactRepository : ISourceArtifactRepository
try
{
await using var connection = new NpgsqlConnection(_connectionString);
await connection.OpenAsync(ct);
await using var connection = await _dataSource.OpenConnectionAsync(ct);
var results = await connection.QueryAsync<ChangelogDto>(
new CommandDefinition(sql, new { CveId = cveId, PackagePurl = packagePurl }, cancellationToken: ct));
@@ -68,4 +67,18 @@ public sealed class PostgresSourceArtifactRepository : ISourceArtifactRepository
throw;
}
}
public ValueTask DisposeAsync() => _dataSource.DisposeAsync();
private static NpgsqlDataSource CreateDataSource(string connectionString)
{
ArgumentException.ThrowIfNullOrWhiteSpace(connectionString);
var connectionStringBuilder = new NpgsqlConnectionStringBuilder(connectionString)
{
ApplicationName = "stellaops-concelier-proofservice-source-artifacts"
};
return new NpgsqlDataSourceBuilder(connectionStringBuilder.ConnectionString).Build();
}
}

View File

@@ -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 | DONE | `docs/implplan/SPRINT_20260405_011___Libraries_transport_pooling_and_attribution_hardening.md`: replaced raw PostgreSQL connection construction with named reusable proof-service data sources. |
| AUDIT-0233-M | DONE | Revalidated 2026-01-07. |
| AUDIT-0233-T | DONE | Revalidated 2026-01-07. |
| AUDIT-0233-A | TODO | Revalidated 2026-01-07 (open findings). |