Skip to content

[Stability: Timeout] NntpDbService does not enforce its startup budget on database operations #118

Open

Description

@enteriaza

Severity: Medium
Classification: Confirmed deadline-enforcement gap.

Location

/home/runner/work/BackFiller/BackFiller/src/BackFiller/NntpDb/NntpDbService.cs:152–208

Code

C#
var deadline = _timeProvider.GetUtcNow() + options.StartupTimeout;
StartupConnectAttempts = 0;
while (true)
{
cancellationToken.ThrowIfCancellationRequested();
StartupConnectAttempts++;
try
{
await using var connection = await _factory
.OpenAsync(options.ConnectionString, cancellationToken)
.ConfigureAwait(false);
var result = await connection.SelectOneAsync(cancellationToken).ConfigureAwait(false);
The deadline is checked only after a retryable exception:

C#
if (_timeProvider.GetUtcNow() >= deadline)
{
throw new NntpDbUnavailableException(
"NntpDB startup connectivity check failed after the configured startup timeout.",
ex);
}
Description

Neither opening the connection nor executing SELECT 1 receives cancellation tied to StartupTimeout. Their duration is governed by the caller token and MySqlConnector’s separately configured behavior.

Consequently:

A single attempt can exceed the advertised startup budget.
An attempt that succeeds after the deadline is accepted.
A retry delay can consume the remaining budget, after which the loop starts another attempt without checking the deadline first.
This delays readiness and recovery during database outages. It is a startup-availability issue, not a demonstrated steady-state throughput bottleneck.

Recommendation

Apply one end-to-end startup deadline to connection opening, health querying, and retry delays. Check expiration before each attempt. Preserve the distinction between caller cancellation, budget expiration, and immediate authentication/configuration failures.

Use monotonic elapsed-time accounting rather than wall-clock comparisons.

Validation

Use controllable connection/session doubles that stall until canceled. Verify that both stalled opening and stalled SELECT 1 terminate within the budget, and that no new attempt starts after expiration.

Activity

  1. self-assigned this
    on Oct 16, 2026
  2. added theissue type on Oct 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions