Repository navigation
fix: align the fake client with the real one and return fetched rows oldest first - #233
Merged
Merged
Conversation
Benchmark gate✅ gate passed
Gated (fails the build): |
This was referenced Oct 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
For 0.15.1, no issue: four places where
FakeOutboxClientandTestOutboxBrokerbehaved differently from the real client. Only one changes the real client:fetchnow returns rows oldest first.1.
fetchreturn order (real client)OutboxClient.fetchreturned the claimed rows in whatever orderUPDATE ... RETURNINGproduced. Postgres gives no order there. The fetch statement picks the oldest rows, but they could come back in any order. The fake always sorted them, so a test like "FIFO within a batch withmax_workers=1" passed underTestOutboxBrokerand could fail in production.fetchnow sorts the returned rows by(next_attempt_at, id), the same key the statement selects on. The new contract testtest_fetch_returns_rows_oldest_firstseeds 41 rows across two queues, including an expired lease, with ids running against age. It failed on the real client before the change: the first row back was id 1, while id 40 was the oldest.Perf: sorting a fetched batch takes 0.9 µs at the default batch size of 10 and 13.5 µs at 100, against a fetch round trip of roughly 0.1–1 ms.
just bench-checkpasses.2.
dlq_payloadwithout a DLQ tableThe real client raises
RuntimeErrorwhen it gets adlq_payloadbut has nodlq_table, rather than dropping the audit row. The fake always wrote the audit row.FakeOutboxClient(dlq_enabled=...)is a new keyword argument. It defaults toTrue, so existing direct uses keep their behaviour.TestOutboxBrokersets it from the broker'sdlq_table.contract_without_dlqfixture runs the case against both clients.The subscriber only sends a
dlq_payloadwhen the broker has a DLQ table, so this isn't reachable through normal use. It keeps the two clients from drifting.3.
feed()accepted rows Postgres rejectsThe fake stored queue names and
timer_ids over 255 characters, and headers that JSONB can't hold. Postgres rejects all three at INSERT.feed()now raisesValueErrorfor them.The batch path checks every row before inserting any of them, so a bad body leaves no partial batch, the same as the real single INSERT.
4. The fake's
publishedmetricThe test broker never emitted
published{status="error"}when encoding failed, andduration_secondswas always 0.0. It now emits the same tags asOutboxProducer, includingexception_type, for single and batch publishes, with a measured duration. A rowfeed()rejects counts as an error, the way a failed INSERT does in production. The observability page said the test-mode duration was 0.0; that paragraph is updated.Tests
Every behaviour change has a test that failed first:
feed()cases, the encode-failure metric for single and batch, the measured duration, and theTestOutboxBrokerDLQ wiring all failed on the fake.Verification
ruffandtyare clean, andjust bench-checkpasses.