Dev.to · 3 min read

Your Test Went Red. Can You Read It?

Your Test Went Red. Can You Read It?

Thesis: A gate being green is not enough. When it turns red, it must be readable—and the guard that makes it readable must stand where it cannot disappear. To test my assertion, I deleted SKIP LOCKED from an outbox claiming query in my side project's sync layer, leaving a plain FOR UPDATE. The test turned red in about six seconds, throwing an exception with a distinct Postgres error code: 55P03 (lock_not_available). The gate bit me immediately. But it only bit because of a single decision I had made earlier: setting -c lock_timeout=5000 directly in the database connection string. My repository code (OutboxClaimStore.cs) had a client timeout of 10 seconds configured (CommandTimeout = 10; Npgsql's default is 30). Had lock_timeout been missing, removing SKIP LOCKED wouldn't have hung the runner forever, but it would have hit that 10-second client cutoff. Npgsql would not have handed me a lock error either. On command timeout it sends a real Postgres CancelRequest on a side connection; the server aborts the statement with 57014 query_canceled — and Npgsql then throws that PostgresException away, replacing it with NpgsqlException: Exception while reading from stream, inner TimeoutException: Timeout during reading attempt. Even the code it did get would only have said "somebody cancelled me," never "I was waiting for a row lock." By enforcing lock_timeout at the database level, Postgres explicitly told me why it stopped: SQLSTATE 55P03 (lock_not_available). This is the story of that setting and why where you put your guards determines whether you actually have them. Unless stated otherwise, every timing in this article comes from a single scripted run against PostgreSQL 16.13 (Ubuntu) on 5 August 2026. Configuration values such as CommandTimeout and lock_timeout are quoted from the source file rather than measured, and the mutant-8 result comes from a separate dotnet test run the same day, whose runtime versions I did not record. §1 — The Same Session Proves Nothing If two dispatcher instances share a single database session, testing a SKIP LOCKED clause measures nothing. In my outbox implementation, OutboxClaimStore opens a separate NpgsqlConnection per call — and because the test holds a third connection open across the pump, the pool is forced to hand out a genuinely different backend session. The comment in OutboxClaimStore.cs records why the dispatcher never shares a session: "a session always 'sees' its own uncommitted locks" To demonstrate this, I ran experiment M1, executing a lease-based UPDATE query twice in a row within a single session (reassembled from the repro script's output): run | claimed -------------------------+------------------------------- A1 SKIP LOCKED present | 1,2,3,4,5,6,7,8,9,10 A2 SKIP LOCKED present | 11,12,13,14,15,16,17,18,19,20 B1 SKIP LOCKED REMOVED | 1,2,3,4,5,6,7,8,9,10 B2 SKIP LOCKED REMOVED | 11,12,13,14,15,16,17,18,19,20 A1 matched B1, and A2 matched B2. Deleting SKIP LOCKED inside a single session changed absolutely nothing. The mechanism here is worth clarifying: the reason sequential calls in a single session return distinct items isn't strictly that the session sees its own locks. Rather, the claim query bumps attempts and — more to the point — pushes available_at into the future. The candidate filter is available_at

This is a summary aggregated from Dev.to. Read the complete article on the original site:

Read full article at Dev.to

More Startup & VC News