fix: reject truncated receive batches - #366
Conversation
Refs #365. Backport frozen SQL to 0.2.1; preserve complete-batch semantics across plain, cooperative and partitioned receives.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Refs #365. Replace truncation expectations with complete retry and acknowledgment checks.
samorev Code Review ReportReviewed head:
BLOCKING ISSUES (5)HIGH [bugs] The default
MEDIUM [bugs] The overflow error reuses the generic SQLSTATE P0001, so clients can only tell it apart from other
MEDIUM [bugs] The frozen TLE artifact moves from 0.2.0 to 0.2.1, but there is no pg_tle upgrade path (
MEDIUM [bugs]
LOW [guidelines] This feature PR edits the frozen release artifacts
Summary
Note:
Review metadataContested / dropped
samorev-assisted review (AI analysis by Tanya301/samorev) |
Refs #365. Classify overflow as SQLSTATE54000, extend boundary and slot-filter tests, and provide a non-destructive stable pg_tle update.
samorev Code Review Report — full AI reviewReviewed head:
Verdict: ❌ CHANGES REQUESTED. There are 2 blocking findings, both documentation and guideline issues. The SQL fix, rollback semantics, partition probe and pg_tle update wrapper held up against full-source review. Separately, reviewer coverage was incomplete (see below), so this review would not report PASS even with zero findings. BLOCKING ISSUES (2)MEDIUM
MEDIUM
NON-BLOCKING (2)LOW
LOW
POTENTIAL ISSUES (13)These are moderate-confidence findings. Review them manually; some may be false positives. MEDIUM
MEDIUM
MEDIUM
MEDIUM
MEDIUM
LOW
LOW
LOW
LOW LOW
LOW LOW
LOW
Validation of the deterministic CLI gate report (
|
| Gate finding | Verdict | Evidence |
|---|---|---|
#1 Default max_return=100 < ticker_max_count=500 → default callers stall |
CONFIRMED (intentional) | Owner-declared design in the PR. Kept only as a potential docs clarification (above), not a defect. |
#2 Python/Ruby/Go Consumer loops don't roll back after 54000 |
REFUTED | Python with conn.transaction() (autocommit) rolls back. Ruby conn.transaction do rolls back and re-raises. Go uses pool implicit transactions. TS catches and sleeps. The consumers default to INT_MAX. |
#3 Go *pgque.SQLError / SQLSTATE may not exist; integration test may not compile |
REFUTED | clients/go/errors.go defines SQLError{Op, SQLSTATE, Err}, and wrapSQLError fills it from pgconn.PgError.Code. integration_test.go has no build tag, so CI's go test -race ./... compiles and runs it. |
| Dropped by gate defender: frozen-installer byte-match to v0.2.1 not CI-enforced | Agree it is not a defect of this PR | The merge-order gate (#367 tag first) is explicit in the PR. #367 is still OPEN (head 22e0b24), so do not merge #366 until #367 is merged and tagged. |
Prior review (round 1 @ 6e87070) follow-up
| Round-1 finding | Status at 6544e35 |
|---|---|
| Default 100 vs 500 | Deliberate owner decision; not re-flagged as a bug |
| Overflow used generic P0001 | Resolved: errcode = '54000' in all three variants, asserted in SQL, Go, Python and Ruby tests |
| No pg_tle 0.2.0→0.2.1 path | Resolved: install_update_path + set_default_version; CI test covers populated ALTER EXTENSION UPDATE and fresh create |
receive_partitioned probe may see other-slot rows |
Resolved / verified: get_batch_cursor(4) applies the slot predicate inside the cursor SQL (… _evs where <pred> order by 1) and fetches exactly i_max. The probe can only see matching rows. A multi-slot regression was added. |
| Frozen artifacts without tag | Handled by the stated merge order (#367 first) |
Specialized agent results
| Agent | Model | Status | Raw result |
|---|---|---|---|
| Security | opus | ✅ complete | No CRITICAL, HIGH or MEDIUM findings. Every replaced function keeps security definer set search_path = pgque, pg_catalog. Signatures are unchanged, so create or replace preserves ACLs and no PUBLIC-executable overload is created. The dynamic fetch/close use quote_ident on an internal bigint-derived name. The CI step uses no untrusted ${{ }} and is not pull_request_target. 2 LOW at 4/10 (pre-planted update path → potential; availability shift → duplicate of the intentional design). |
| Bug Hunter | opus | ✅ complete | No CRITICAL, HIGH or MEDIUM findings. Verified that partition probe placement, GET DIAGNOSTICS row_count and the empty-slice finish are ordered correctly. Overflow is raised before any finish_batch, and allocation, takeover, auto-registration and lease renewal all roll back. All 4 wrapper branches are correct. A script confirmed the embedded install body equals sql/pgque.sql (260466 bytes) and the update bodies are byte-identical. The only deltas from v0.2.0 are 3 functions plus the header. 2 LOW (stale client docs → merged into blocking #1; hand-maintained "auto-generated" headers → non-blocking). |
| Test Analyzer | sonnet | ✅ complete | 4 MEDIUM, 3 LOW. All are coverage gaps, none is a failing test. They are listed above as potential issues: stable CI overflow, upgrade branches, non-empty INT_MAX, partitioned/coop rollback assertions, NULL/N-1 per variant, when others catches, consumer-loop and TS tests. |
| Guidelines | sonnet | 2 MEDIUM (README migration framing → blocking #2; installation version tag → potential), 4 LOW, 1 INFO. SQL style, search_path, lowercase and left-aligned keywords, shell set -Eeuo pipefail and commit subjects all pass. devel sources match the generated devel SQL. |
|
| Docs | sonnet | ✅ complete | 6 MEDIUM, 3 LOW. Stale SDK docs (blocking #1), examples.md contradiction (non-blocking), default-vs-threshold note, TS README, migration framing, version tag, tutorial receive(…, 1), plain-upgrade note, and receive_partitioned undocumented (pre-existing → filtered). |
| Sqitch Migration Checker | — | N/A | postgres-ai/platform only |
| Visual Evidence | — | N/A | No UI or visual paths changed (docs .md only, no site/ changes) |
Coverage and incompleteness
- Diff: all 1903 diff lines (78 KiB) were read in full by the orchestrator and every agent. Nothing was truncated. Where diff context was insufficient, full source was read at the head SHA:
partition_keys.sql,get_batch_cursor, stablesql/againstgit show v0.2.0:…,build/transform.sh,ci.yml, and the Go/Python/Ruby/TS client sources and tests. ⚠️ Guidelines coverage was incomplete. The organizationalpostgres-ai/rulesfiles could not be loaded (the fetch was denied in this environment). The Guidelines agent checked against PgQueCLAUDE.mdonly, which restates the core of the Postgres.AI SQL style guide and takes precedence on conflict.⚠️ The review was static. No agent ran databases or test suites. Runtime behavior relies on the green CI at6544e35(18/18) and the author's local logs.⚠️ Validation was not independent. The orchestrator validated findings against full source in a single pass instead of spawning a separate validator subagent per finding.- SOC2 was skipped, as PgQue's CLAUDE.md requires.
Summary
| Area | Findings | Potential | Filtered |
|---|---|---|---|
| CI/Pipeline | 0 | 0 | 0 |
| Security | 0 | 1 | 1 |
| Bugs | 1 | 0 | 0 |
| Tests | 0 | 7 | 0 |
| Guidelines | 1 | 2 | 2 |
| Docs | 2 | 3 | 2 |
| Metadata | 0 | 0 | 0 |
Note:
- Findings are high-confidence issues (8-10/10), blocking or non-blocking according to severity. This table counts the 4 high-confidence findings (2 blocking, 2 non-blocking) by area, and each cross-agent finding is counted once.
- Potential are medium-confidence issues (4-7/10) to review manually.
- Filtered are low-confidence, pre-existing or duplicate findings: the Security availability note (duplicate of the intentional default), the Guidelines multi-line
--comment style and long hint strings,receive_partitionedabsent from the reference (pre-existing), and tutorial0.2.0version output (pre-existing, not touched by this PR).
Merge gate: fix the 2 blocking items, then re-review the delta. Merge only after #367 is merged and v0.2.1 is tagged, and confirm that the frozen sql/ files match the tag byte-for-byte.
samorev-assisted review (AI analysis by Tanya301/samorev)
Resolve review findings on SDK documentation and default ceilings.\n\nRefs #365.
samorev Code Review Report — round 3 (delta review)Reviewed head:
Verdict: ✅ PASSED. There are no blocking findings at
Round-2 blocking findings: validation
Other round-2 items:
Validation of the CLI gate report (
|
| Gate finding | Verdict | Evidence |
|---|---|---|
#1 No CI check that frozen sql/ byte-matches the v0.2.1 tag |
CONFIRMED as fact; intentional process gate, not a defect | .github/workflows/ci.yml references only v0.2.0 (git show v0.2.0:sql/pgque-tle.sql). There is no v0.2.1 tag. The PR description defines an explicit release-operator gate instead. A CI step remains advisable but optional. See the merge gate above. |
| #2 No CHANGELOG or release notes for the new failure mode | REFUTED as a missing file in this PR | PgQue has no CHANGELOG.md. Per CLAUDE.md, release notes are GitHub releases. #367's draft release notes contain the default-100 / 54000 / "size ceilings before upgrading" warning, which I verified in the #367 description. #366 now also documents the current behavior in reference.md:127, :185 and installation.md:383-386. Correction to the gate's wording: the defaults did not change. SQL and TypeScript were already 100 at v0.2.0 (git show v0.2.0:sql/pgque.sql, client.ts). What changed is that overflow now raises 54000 where it used to truncate. |
| Note | The gate report does not record its head SHA. Its timestamp follows the 1df5e36 commit. Either way, both findings were re-checked against source at 1df5e36. |
NON-BLOCKING (4)
High-confidence LOW/INFO findings, which can be addressed later. All were independently validated as TRUE.
LOW clients/go/concurrency_test.go:48-49 - The new comment says "maximum producer count", but the ceiling bounds the message count (2*expected, where expected = goroutines*perGoroutine). The code is correct. (Bugs; validated 9/10; introduced by delta)
Suggestion: "This test knows its maximum message count, so use a ceiling above that count."
LOW clients/python/README.md:73, clients/ruby/README.md:88 - Both still open with "controls the per-receive limit", and the next sentence calls the same value a "complete-batch safety ceiling". "Limit" suggests the pagination model this PR removes. (Guidelines + Docs + Bugs; validated 8/10; untouched context line next to the rewritten text)
Suggestion: "sets the complete-batch safety ceiling for each
receive."
LOW sql/pgque-tle-updates/pgque--0.2.0--0.2.1.sql:2, sql/pgque-tle.sql:2 - Previously flagged, still unresolved. The headers say "Auto-generated by build/transform.sh", but transform.sh never generates install_update_path, set_default_version or the update body. (Docs + Guidelines; validated 8/10; in PR, outside delta)
Suggestion: Label these files hand-maintained, or generate them in the #367 source, and keep the byte-for-byte tag match.
INFO commit 1df5e36 message body - The body contains a literal \n\n ("…default ceilings.\n\nRefs #365.") where it should have real newlines, confirmed with od -c. The subject is compliant. (Guidelines; validated 10/10; development__git-commit-standards.mdc)
Suggestion: Don't amend (both CLAUDE.md and the rules say so). Fix it in the squash-merge message if one is used.
POTENTIAL ISSUES
Moderate-confidence findings (4-7/10). Review them manually.
New in this delta, or newly surfaced:
P1 LOW clients/go/pgque.go:153-158, :327-330, options.go:22-25, :129-132, clients/go/README.md:96, :242, clients/typescript/src/client.ts:152-156, :375-378, types.ts:63-65, clients/typescript/README.md:77, :124; also the Python README Consumer section - "Roll back and retry" is accurate for the Python low-level client, which defaults to autocommit=False (client.py:22). It doesn't fit Go/TS pool calls, which are single autocommit statements with no caller transaction to roll back, or the Python Consumer (autocommit=True, consumer.py:187) and Ruby (autocommit-like). It is harmless, because retrying returns the same batch and nothing is lost, but it can confuse readers. (confidence 7/10; introduced by delta)
Suggestion: For pool-based APIs, write: "The failed call changed nothing; retry with a larger resource-safe ceiling. If you call it inside your own transaction, roll back first."
P2 LOW clients/typescript/src/consumer.ts:7-11 - The DEFAULT_MAX_MESSAGES rationale still says the default exists so ack(batch_id) "does not strand events the client never saw". With the overflow guard, the real reason is avoiding 54000. This is pre-existing (the PR doesn't touch the file). The Python, Go and Ruby counterparts are accurate. (confidence 7/10)
Suggestion: "Request the whole batch so normal bursts do not raise SQLSTATE 54000."
P3 INFO Terminology drift in the delta: "ticker thresholds", "ticker threshold of 500", "ticker event-count threshold" and ticker_max_count; also "safety ceiling" alongside "complete-batch safety ceiling". (confidence 7/10; writing__terminology-consistency.mdc)
Suggestion: Use one term per concept, for example "
ticker_max_count(event-count threshold)" and "complete-batch safety ceiling" at first mention.
P4 LOW docs/installation.md:446 - Previously flagged, still unresolved. alter extension pgque update to '0.2.1'; hard-codes a version tag in docs/. The wrapper calls set_default_version, so alter extension pgque update; works. (confidence 6/10)
Carried forward unchanged from round 2 (files untouched by the delta; details in the round-2 report):
- Tests (7):
- no overflow assertion on the frozen stable installer in
stable-smoke; - upgrade-wrapper branches untested (fresh registration, post-update rerun, unsupported origin, plain 0.2.0→0.2.1 with data);
- INT_MAX exercised only on empty batches;
- no rollback-state assertions after partitioned/coop overflow;
- NULL/N-1 tested only for plain
receive; when otherscatches without SQLSTATE asserts;- no consumer-loop overflow test, and no TS overflow test.
- no overflow assertion on the frozen stable installer in
- Docs:
tutorial.md:232,:271usereceive(…, 1) limit 1, which is safe but an anti-pattern; the pg_tle snippet should name the supported origin. - Guidelines:
sql/pgque-tle.sql:7258has the constant tautology'0.2.1' = '0.2.1'. - Security (4/10):
sql/pgque-tle.sql:7258-7263reuses a pre-registered update path without comparing it toupdate_sql. Exploiting this requirespgtle_admin.
Specialized agent results
| Agent | Model | Status | Raw result |
|---|---|---|---|
| Security | opus | ✅ complete | NO_FINDINGS. Confirmed the delta is byte-identical to git diff 6544e35 1df5e36 and that every Go/Python/TS hunk is comment or docstring only. No signature, default, SQL string or logic changes. The only SQL snippet change (100→1000) uses literal arguments, and the clients still use parameterised queries. The guidance steers users away from null (unbounded) and toward resource-safe ceilings plus alerting on 54000, so the DoS-relevant guidance improved. Prior LOW (pre-planted pg_tle path) unchanged. |
| Bug Hunter | opus | ✅ complete | No MEDIUM+. Verified every factual claim against source: • SQL receive/receive_coop default 100 (receive.sql:30, cooperative_consumers.sql:1116, frozen sql/pgque.sql:5343, :6595); queue_ticker_max_count default 500 (devel/sql/pgque.sql:110).• The ticker only gates whether to tick ( :760), so "thresholds do not cap batch size" is true.• 54000 is raised before any finish_batch in all three variants, so no partial result reaches the caller.• receive() auto-finishes empty batches.• All Go/Python/TS/Ruby client and consumer defaults match the docs. 3 LOW (pool "roll back" wording → P1; test comment → non-blocking; TS consumer comment → P2). B1 FIXED. Gate #1 confirmed/intentional, #2 refuted with the defaults correction. |
| Test Analyzer | sonnet | ✅ complete | NO_FINDINGS. No executable code or test bodies changed; the only test-file edit is a comment, and the Receive(…, 2*expected) call is unchanged. New doc claims are covered: empty-batch auto-finish (tests/test_receive_empty_batch.sql), 54000 in SQL plus Python/Ruby/Go client tests. All 7 round-2 test potentials are unchanged. Note: it took the round-2 list from the prompt and did not open the round-2 report itself. |
| Guidelines | sonnet | ✅ complete | 5 INFO (per-receive "limit" wording; installation version tag; tautology; literal \n in commit body; terminology drift). B2 FIXED; no new migration framing, PR/issue numbers or version tags in the README/docs/. Org rules loaded locally from pgai-rules/rules (round 2 couldn't load them): professional-communication, terminology-consistency, binary-units, title-capitalization, git-commit-standards, ai-coding-guidelines, core-principles. The agent skipped python-style-guide and db-sql-style-guide, so the orchestrator checked them: added Python docstring lines are ≤79 chars (max 75), and the single changed SQL snippet is lowercase and schema-qualified. |
| Docs | sonnet | ✅ complete | No new defects in the delta. Carried: version tag (P4), auto-generated headers (N4), tutorial receive(…,1). New LOW: per-receive "limit" wording. Defaults verified against SQL/Go/Python/TS/Ruby sources. The installation paragraph is correctly placed in plain-SQL Upgrading; INFO: the pg_tle subsection lacks an equivalent note. Full prior-validation table: B1 fixed, B2 fixed, examples.md fixed, 4 potentials fixed. Gate #2: partial, not a blocker. |
| Validator (independent) | opus | ✅ complete | All 8 findings TRUE. Confidences: F1 8, F2 7, F3 9, F4 7, F5 10, F6 7, F7 6, F8 8. None reaches MEDIUM+ or blocking. |
| Sqitch Migration Checker | — | N/A | postgres-ai/platform only |
| Visual Evidence | — | N/A | No UI or visual paths changed (Markdown and code comments only; no web/ or site/ changes) |
Prior evidence carried forward
- Round 2 (full source at
6544e35) reviewed the SQL fix (all three receive variants, the partition probe that applies the slot predicate insideget_batch_cursor, statement rollback of allocation/takeover/registration), the pg_tle 0.2.0→0.2.1 wrapper (all 4 branches), the frozen-artifact identity (embedded TLE body ==sql/pgque.sql; update bodies byte-identical; only 3 functions plus the header differ fromv0.2.0), CI wiring, and the client sources and tests. No CRITICAL/HIGH/MEDIUM defects were found in executable code. These files are byte-identical at1df5e36, so the conclusions carry forward. - Runtime evidence: CI 18/18 green at
6544e35(run 36878058582) and re-run 18/18 green at the exact reviewed head1df5e36(run 36880437185). The re-run covered PG 14–19beta1 regression, Go/Python/Ruby/TS client tests, the pg_tle install path (including the 0.2.0→0.2.1 upgrade test), the frozen stable install smoke, the v0.1.0→HEAD upgrade, pg_cron, pg_timetable, verify and build. - Not carried forward: the author's local Postgres 18.3 and pg_tle v1.5.2 logs. They don't identify an exact SHA, so they are cited only as author claims.
Coverage and incompleteness
- Diff: all 347 lines (23 KiB) of
git diff 6544e35 1df5e36were read in full by the orchestrator and every agent. Nothing was truncated or clipped. Full source at1df5e36was read wherever a claim needed checking: SQL receive/coop/partitioned/ticker, frozensql/,v0.2.0artifacts, all four client libraries and consumers, the touched docs sections,ci.yml,transform.shandCLAUDE.md. - This is a delta review. Files outside the delta were not re-reviewed line by line in this round. Their coverage comes from round 2 (identical bytes) and CI at the exact head.
- This review was static. No agent ran databases or test suites. Runtime behavior relies on CI at
1df5e36. - Out of scope: fix: backport receive safety to 0.2.1 #367's own delta (
22e0b24..dc0b698, including its newdocs/upgrading.md) was not reviewed here. Only the byte-identity of the three frozensql/files and the release-notes text in its description were checked. - All five specialized reviewers and the validator completed. The one rule-coverage gap (two rule files skipped by the Guidelines agent) was closed by the orchestrator. SOC2 was skipped, as PgQue's CLAUDE.md requires.
Summary
| Area | Findings | Potential | Filtered |
|---|---|---|---|
| CI/Pipeline | 0 | 0 | 0 |
| Security | 0 | 1 (carried) | 0 |
| Bugs | 1 | 2 | 0 |
| Tests | 0 | 7 (carried) | 0 |
| Guidelines | 1 | 2 (1 new, 1 carried) | 0 |
| Docs | 2 (1 carried) | 3 (carried) | 0 |
| Metadata | 0 | 0 | 0 |
Notes:
- Findings are high-confidence issues (8-10/10), all non-blocking here (LOW/INFO). Cross-agent findings are counted once. The Docs row covers the per-receive wording (new) and the auto-generated headers (carried).
- Potential are moderate-confidence issues (4-7/10).
- Filtered: none. The Docs INFO (pg_tle subsection lacks a sizing note) and the "Monitor 54000" actionability remark were judged below the reporting bar and are listed in the agent table only.
Merge gate: there is no review blocker at 1df5e36. Merge only after #367 is merged and v0.2.1 is tagged, and only after the release operator posts a successful git diff --exit-code v0.2.1 -- sql/pgque.sql sql/pgque-tle.sql sql/pgque-tle-updates/pgque--0.2.0--0.2.1.sql. Any further commit to #366 needs a delta re-review.
samorev-assisted review (AI analysis by Tanya301/samorev)
Clarify ticker thresholds and consumer comments. Refs #365.
samorev Code Review Report — round 4 (delta review)Reviewed head: Companion delta also reviewed: #367 head
Verdict: ✅ PASSED. There are no blocking findings at
Prior findings: validation at the new headsBlocking: round 3 had no open blocking findings on either PR. Round 2's B1 and B2 on both PRs were validated FIXED in round 3, and this delta does not touch those files' fixed text, so they stay fixed. The CLI gate items (no CI tag byte-match; missing release notes) were validated in round 3 as an explicit operator gate and as present in the #367 description. They are not new findings, and both gates are kept above. Non-blocking and potential items this delta targets:
Carried forward unchanged (files untouched by this delta; details in the round-3 reports):
BLOCKING ISSUES (0)None. NON-BLOCKING (0 new)None new. The round-3 non-blocking items still open are listed under "Carried forward" above. POTENTIAL ISSUES (0 new)None survived validation. Filtered item, shown for transparency:
Informational, not a finding (Bug Hunter): the inherited upstream PgQ table comment Specialized agent results (all 5 completed on the delta)
Prior evidence carried forward
Coverage and incompleteness
Summary
Notes:
Result: PASSED (delta scope) at #366 This is a review verdict, not merge approval. Merge #366 only after #367 is merged (with its v0.2.0 reapply evidence posted), samorev-assisted review (AI analysis by Tanya301/samorev) |
Post-review real-test evidenceExact reviewed/tested head: Environment: isolated Postgres 18.6 containers, no published ports, localhost listening, connection logging enabled. pg_tle upgrade uses v1.5.2. Commands and resultsFrom the candidate checkout, the regression harness executes: psql -X -v ON_ERROR_STOP=1 -f devel/sql/pgque.sql
psql -X -v ON_ERROR_STOP=1 -f tests/run_all.sql
psql -X -v ON_ERROR_STOP=1 -f tests/acceptance/run_acceptance.sql
psql -X -v ON_ERROR_STOP=1 -f devel/sql/pgque.sql -f tests/test_install_idempotency.sqlOutputs: Additional executable harnesses (all exit 0):
The upgrade harnesses use the maintenance candidate; its three frozen release SQL files are byte-identical to this PR's frozen files. No throughput benchmark or client package publication is claimed. Non-blocking review dispositions
Evidence integrityLogs retained in Release sequencing remains: merge maintenance, verify exact merge CI, publish and verify v0.2.1, prove frozen artifacts match the tag, then merge development. |
Published-tag gate: PASS
At development PR #366 head git diff --exit-code v0.2.1 -- sql/pgque.sql sql/pgque-tle.sql sql/pgque-tle-updates/pgque--0.2.0--0.2.1.sqlExit 0, no diff. The frozen SQL/tag-match release-operator gate is satisfied. A fresh detached checkout of the published tag also passed (all exit 0):
Output markers: No client packages were published. Real pagination remains tracked separately in #364. |
Summary
Refs #365. Make convenience receives return the complete batch or raise on N+1. Exactly N remains valid; INT_MAX does not require overflowing arithmetic. Covers plain, cooperative and partitioned receives. Errors include actionable recovery hints, and statement rollback preserves consumer state and ownership.
Correct reference/examples/tutorial/client guidance: ticker thresholds are not batch-size caps; repeated receive calls are not pagination; never acknowledge a failed receive. Real pagination is tracked separately in #364.
Frozen
sql/pgque.sqlandsql/pgque-tle.sqlcontain the minimal v0.2.1 backport generated from v0.2.0, not alpha features. Development remains 0.3.0-devel. A separate maintenance PR will provide the stable source/tag.Verification
On fresh local Postgres 18.3 databases:
bash build/transform.shpsql -X -v ON_ERROR_STOP=1 -d "$db_name" -f devel/sql/pgque.sqlpsql -X -v ON_ERROR_STOP=1 -d "$db_name" -f tests/test_receive_overflow.sqlpsql -X -v ON_ERROR_STOP=1 -d "$db_name" -f tests/run_all.sqlpsql -X -v ON_ERROR_STOP=1 -d "$db_name" -f tests/acceptance/run_acceptance.sqlgit diff --checkAll local suites pass. Regression covers N-1/N/N+1, NULL compatibility, INT_MAX, allocated/unallocated batch rollback, payload completeness, and failed/successful cooperative takeover. CI and SamoRev must pass on the exact head before merge; review and post-review real-test evidence will be posted here.
Intentional scope and review context
The owner explicitly selected the minimal fail-closed overflow solution, not a new pagination protocol or an unbounded default. Keep existing default ceilings/signatures. Stalling an undersized consumer with a visible, monitorable error is intentional; increasing the default to INT_MAX or silently escalating a caller's limit would replace a resource safety ceiling with potential memory pressure. Docs and release notes require rollback/retry with an operator-chosen ceiling. Ticker thresholds cannot guarantee successful reads.
receive_partitioned()passes its hash-slot predicate intoget_batch_cursor(..., extra_where); the cursor itself is filtered before the N+1 probe. Review the completedevel/sql/pgque-api/partition_keys.sqlif the provider diff is truncated. The multi-slot regression checks matching rows separately from other slots.Release ordering: merge the maintenance source PR #367 and publish its reviewed v0.2.1 tag before merging this PR. The frozen stable installers here must match those tagged artifacts byte-for-byte; they are not an independent development build. Source and generated devel SQL remain separately versioned.
pg_tle update verification
The v0.2.0→v0.2.1 wrapper now registers a function-only update edge via the documented pg_tle
install_update_pathAPI and sets the new default version. PostgreSQL can create the default version through the existing base install plus that edge; a redundant standaloneinstall_extension_version_sqlregistration is not required. This was executed on pg_tle v1.5.2: both an in-place populated ALTER EXTENSION UPDATE and a fresh CREATE EXTENSION after registration pass. The regression also reruns wrapper registration, preserves active subscription state, and verifies both plain/cooperative overflow return SQLSTATE54000 followed by successful full recovery. The same test is wired into CI, with tagged v0.2.0 fetched via full checkout history.The overflow SQLSTATE change was red/green tested (old P0001 fails the new assertion). The multi-slot partition test establishes that the probe sees only matching-slot rows; other-slot rows do not cause overflow. INT_MAX now explicitly checks zero returned rows and no active batch.
Release publication gate
The complete v0.2.1 GitHub release notes, including the default-100 ceiling compatibility warning, are included in maintenance PR #367. Before merging this PR, the release operator must verify the published tag exists and run
git diff --exit-code v0.2.1 -- sql/pgque.sql sql/pgque-tle.sql sql/pgque-tle-updates/pgque--0.2.0--0.2.1.sql, posting the exact tag/head and successful result. This is an explicit release-operator gate, not an assertion that CI already enforces it.