Skip to content

Read recent failures with NUL-bearing PostgreSQL history - #921

Merged
rmcdaniel merged 2 commits into
mainfrom
fix/225-postgresql-failure-diagnostics
Oct 24, 2026
Merged

rmcdaniel merged 2 commits into
mainfrom
fix/225-postgresql-failure-diagnostics

Conversation

@rmcdaniel

@rmcdaniel rmcdaniel commented Oct 24, 2026 •

Copy link
Copy Markdown
Member

Reading recent failures on PostgreSQL fails when a retained event contains a NUL-bearing message. PostgreSQL accepts the escaped NUL in its json storage, but SQL JSON extraction reparses other string fields and raises 22P05 before returning the selected failure identity.

This is a concrete local reproduction on exact merged main f8103d19: V2ActivityExceptionCodecTest::testLargeTerminalFailureKeepsFullCanonicalMessageAndHistory errors at RunRecentFailures.php:85; the other eight codec cases pass. A focused regression also fails on the unchanged runtime and covers adjacent NULs, nested messages, literal backslash escapes and Unicode identities. The migration controls separately pass two PostgreSQL cases, with one MySQL-only skip.

Exact source 9b16b20, whole tree 6eda2a38e24f0f15b4868dea181ec427b35b2d8c, corrects PostgreSQL metadata expressions for recent failure links and history-budget fallback. It masks actual NUL escapes in a temporary SQL expression, preserves paired literal backslashes, uses PostgreSQL's normal JSON parser for metadata and restores the exact canonical byte difference in budget accounting. It does not rewrite stored history, transfer full payloads into diagnostic readers, add an event producer or alter completion authority. The combined prospective patch remains unpublished 2.12.2.

The independent history-budget missing/stale-summary regressions also fail on the preceding runtime with 22P05. Final component results are 43 executable checks / 241 assertions on each PostgreSQL and SQLite, with two explicit MySQL-only skips on each driver. The cases cover original exception delivery, selected failure links, literal escapes, Unicode identities, original history bytes, exact budget counts, configured model scope and bounded header hydration. Full src/tests PHPStan passes; full ECS applies only test formatting and reports no remaining errors. The earlier formatting failure and every failing counterfactual remain distinct evidence.

Final exact-head qualification is complete: 16 hosted checks succeed, with 6 explicit skips; build 40070198191 is terminal success. The unchanged original PostgreSQL shard 2 completes 757 cases / 5,846 assertions, with two explicit driver-specific skips, zero failures/errors and exit 0, within the original ten-minute budget (482.7 seconds of test time). This includes the original large terminal failure case. The independent MySQL component passes 45 tests / 249 assertions. Earlier exact-head PostgreSQL/SQLite components each pass 43 executable checks / 241 assertions. Direct Sonar review reports gate OK, 0.0% new duplication and zero issues. No source, expected assertion or business deadline was relaxed. This qualifies the source correction, not a new package, runtime image or rollout. The recovered original hosted failures match this diagnosis; their failed outcomes remain unchanged. Merged normally as e6b9ad812561fb5a3ee9ec373cf43cf974b56a02, with the exact qualified tree 6eda2a38e24f0f15b4868dea181ec427b35b2d8c; the completed remote branch is absent. Independent main build 40071278691 is live, so publication remains pending. The reader branch must integrate the resulting main revision and qualify its new tree.

Owning issue: durable-workflow/.github#225. Both original main failures now have recovered JUnit evidence matching the local diagnosis. Original assertions and fresh-main PostgreSQL success. The failed originals remain failed; no rerun, source/assertion/deadline relaxation or publication occurred. Core 2.12.2 remains unpublished pending the final independent-main aggregate and installed acceptance.

PostgreSQL documents the distinction between storing escaped Unicode in json and processing it with JSON functions: https://www.postgresql.org/docs/17/datatype-json.html .

@sonarqubecloud

Copy link
Copy Markdown

@rmcdaniel

Copy link
Copy Markdown
Member Author

Final exact-head qualification is complete: 16 hosted checks succeed, with 6 explicit skips; build 40070198191 is terminal success. The unchanged original PostgreSQL shard 2 completes 757 cases / 5,846 assertions, with two explicit driver-specific skips, zero failures/errors and exit 0, within the original ten-minute budget (482.7 seconds of test time). This includes the original large terminal failure case. The independent MySQL component passes 45 tests / 249 assertions. Earlier exact-head PostgreSQL/SQLite components each pass 43 executable checks / 241 assertions. Direct Sonar review reports gate OK, 0.0% new duplication and zero issues. No source, expected assertion or business deadline was relaxed. This qualifies the source correction, not a new package, runtime image or rollout. The inaccessible original hosted failures remain separate failed originals; no common cause is inferred.

@rmcdaniel
rmcdaniel marked this pull request as ready for review October 24, 2026 06:42
@rmcdaniel
rmcdaniel merged commit e6b9ad8 into main Oct 24, 2026
22 checks passed
@rmcdaniel
rmcdaniel deleted the fix/225-postgresql-failure-diagnostics branch October 24, 2026 06:42
@rmcdaniel

Copy link
Copy Markdown
Member Author

The two original main PostgreSQL shard-2 failures now have recovered JUnit evidence. Artifact 12550120778 (31,556 bytes) belongs to run 40066693736, exact f8103d194e8fb0e09ef6f2f73568c3609e013277. Artifact 12546474946 (31,713 bytes) belongs to run 40060294140, exact a93e97bf425263c73fa88281897a888e0415e4eb. Authenticated artifact metadata verifies both associations.

Both originals identify V2ActivityExceptionCodecTest::testLargeTerminalFailureKeepsFullCanonicalMessageAndHistory, Illuminate\Database\QueryException, SQLSTATE 22P05, with \u0000 cannot be converted to text while selecting payload->>'failure_id'. This establishes the same cause as the independent local reproduction corrected by #921. The old runs remain failed and were not rerun or changed.

Fresh independent main e6b9ad8, run 40071278691, has now passed PostgreSQL shard 2, job 120805230264. Other PostgreSQL shards and all five Laravel upgrade jobs also pass; final MySQL/aggregate qualification remains live. This closes the missing-assertion diagnosis, while normal 2.12.2 publication and installed acceptance remain pending. Raw archives and expiring download URLs were not retained.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Independent main e6b9ad8 / tree 6eda2a38e24f0f15b4868dea181ec427b35b2d8c is fully qualified. Build 40071278691 is terminal success: 22 jobs pass, two are intentionally skipped. All exact-commit GitHub checks are terminal: 27 successful, two skipped. Coverage and the unchanged v2 ratchet pass.

Sonar analysis 29bc1106-2ba1-49a2-8700-788d4a7cf92d identifies this exact revision, with gate OK, 88.7% new-code coverage and 0.4% new duplication. Review of the three release PRs confirms the two #918 exception findings are fixed, #920 retains only its explicitly accepted ordered-guard php:S1142 maintainability tradeoff, and #921 has no findings. There are no new open/confirmed issues in files changed since 2.12.0; historical main debt is separate and has not been dismissed or hidden. No rule, threshold, profile or pushed finding was suppressed.

Committed product-train metadata is exactly 2.12.2. The repository source-mirror contract command also passes against the live suite-47 authority and immutable worker-protocol resolvers. Existing 2.12.0 remains the latest artifact until the normal immutable release action. Normal published-package verification, installed canonical-storage/metadata behavior and downstream image/UI adoption remain required. This source result does not close #225 or #878 or admit the rejected-outcome emitter.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Published Core 2.12.2 installed-package acceptance is complete for the affected module controls. Normal Composer resolves source/dist e6b9ad812561fb5a3ee9ec373cf43cf974b56a02; all 2,173 installed package files match that source both before and after the run. Stock Composer autoload resolves the failure storage, recent-failure diagnostics, PostgreSQL metadata and SQLite transaction classes from the installed package. Test helpers/fixtures come from the same source; production package files were unchanged. The consumer resolves Laravel 13.38.0 / Testbench 11.3.0 / PHPUnit 12.5.40 on PHP 8.3.36; Composer audit reports zero advisories.

The unchanged six-suite cohort covers activity-outcome retention, canonical failure messages, bounded recent failures, history budgets, the activity exception codec and the failure-message storage migration:

Database Executed Driver skips Assertions Elapsed
File-backed SQLite 62 36 344 31.164 s
PostgreSQL 93 5 833 72.866 s
MySQL 96 2 844 64.921 s

Each invocation discovers 98 cases and exits successfully with warnings/deprecations treated as failures; the original test process budgets are unchanged. The normal published verification 40073230062 also passed all 17 jobs. Independent main 40071278691 passed; its exact Sonar gate is OK with 88.7% new coverage and 0.4% duplication. Historical main debt and the failed original runs remain separate.

This proves the released module's affected installed behavior. Server images, embedded application/SDK/Waterline acceptance, the draft #919 reader rollout, and the #901 emitter contract retain their own requirements under #878 and durable-workflow/.github#225. No image adoption or Cloud deployment is implied.

Task databases were dropped and their containers stopped cleanly (exit 0, no OOM) and removed. The task network and newly built Composer tool image were removed; shared images and other owners' resources were preserved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant