fix(driver.sql): a post-open query failure is not a reachability verdict (Driver.Sql-005)

This commit is contained in:
Joseph Doherty
2026-08-10 08:00:51 -04:00
parent 90f3016a3e
commit ee1f1b28e8
2 changed files with 73 additions and 9 deletions
@@ -224,6 +224,33 @@ public sealed class SqlDriverTests
}
}
[Fact]
public async Task ReadAsync_whenTheQueryFailsAfterTheConnectionOpened_degradesButLeavesTheEndpointUp()
{
// Driver.Sql-005. BadCommunicationError is minted by GroupResult.Failed, which the reader raises only
// AFTER the connection opened ("the connection opened, so the server is up — this query is what
// failed"). Classifying it as connection-class reported the whole database endpoint Stopped over one
// group failing on a dropped table, a revoked SELECT or an over-long IN list, sending the operator at
// the network instead of at the schema. The driver must still degrade — every tag in that group is
// Bad — but the endpoint is demonstrably up.
using var fixture = new SqlitePollFixture();
await using var driver = NewDriver(fixture, KvEntry("Speed", SqlitePollFixture.PresentKey));
await driver.InitializeAsync(ConfigJson, CancellationToken.None);
driver.GetHostStatuses()[0].State.ShouldBe(HostState.Running);
// The schema drifts out from under a driver whose catalog gate already passed.
fixture.Execute($"DROP TABLE {SqlitePollFixture.KeyValueTable}");
var snapshots = await driver.ReadAsync(["Speed"], CancellationToken.None);
snapshots[0].StatusCode.ShouldBe(SqlStatusCodes.BadCommunicationError);
var health = driver.GetHealth();
health.State.ShouldBe(DriverState.Degraded);
health.LastError.ShouldNotBeNull();
health.LastError.ShouldContain("quer"); // names the query, not the network
driver.GetHostStatuses()[0].State.ShouldBe(HostState.Running); // RED pre-fix: Stopped
}
[Fact]
public async Task ReadAsync_anUnresolvableRef_isNotAConnectivityFact_soHealthAndHostStand()
{