Repository navigation
Repair the decode-drop-recovery stress test so the job can pass (backport #745 to v5.2) - #759
Conversation
…rdown (#745) The `decode-drop-recovery` stress job could never pass. Two defects in the test, both dating to when it was added in #691: `add_node` was authorized with `ctx.nodeA.HDB_ADMIN_USERNAME` / `HDB_ADMIN_PASSWORD`. Those properties do not exist on the integration-testing harness's node object, which exposes `admin: { username, password }` — the name appears in exactly one file in `integrationTests/`, this one. Both values were `undefined`, so the operation went out as `authorization: {}` and `add_node_back` followed with `authorization: null`. Node B then presented its still-self-signed certificate to A with no credentials behind it, and A — installed with the prod config profile, so certificate validation is enforced — closed the connection 1008 Unauthorized. The test died in ~230ms at its first operation, never reaching any decode-drop behavior. `after()` called `teardownHarper(ctx.nodeA)`, passing the node where the harness expects a context. `teardownHarper` opens with `if (!ctx.harper) return`, so both calls were silent no-ops and both Harper children survived the suite. The leaked-child backstop in `integrationTests/run.mjs` then forced a non-zero exit, which would have kept the job red even once the join was fixed. Teardown now also runs both nodes concurrently, matching the sibling suites, so a hang on A cannot strand B. Neither surfaced earlier because the job's three runs before 2026-08-20 were all cancelled; the 2026-08-20 run was its first completed run. Co-authored-by: Claude Opus 5 <noreply@anthropic.com> (cherry picked from commit 4bd15ec)
There was a problem hiding this comment.
Code Review
This pull request refactors the test cleanup in decodeDropRecovery.test.mjs to tear down Harper nodes concurrently using Promise.all and simplifies the authorization configuration. The review feedback recommends logging any teardown errors with identifying information instead of silently swallowing them in the .catch block.
| await Promise.all( | ||
| [ctx.nodeA, ctx.nodeB].filter(Boolean).map((node) => teardownHarper({ harper: node }).catch(() => {})) | ||
| ); |
There was a problem hiding this comment.
In test cleanup hooks, any failures during process termination or cleanup should be logged with identifying information (such as hostnames) for easier diagnosis, rather than being silently swallowed with an empty .catch(() => {}) block.
| await Promise.all( | |
| [ctx.nodeA, ctx.nodeB].filter(Boolean).map((node) => teardownHarper({ harper: node }).catch(() => {})) | |
| ); | |
| await Promise.all( | |
| [ctx.nodeA, ctx.nodeB].filter(Boolean).map((node) => | |
| teardownHarper({ harper: node }).catch((err) => { | |
| console.error('Failed to teardown Harper node ' + (node.hostname || 'unknown') + ':', err); | |
| }) | |
| ) | |
| ); |
References
- In test cleanup hooks, wrap individual process termination or cleanup steps in separate try-catch blocks to ensure they are attempted independently, and log any failures with identifying information (such as hostnames) for easier diagnosis.
|
Reviewed; no blockers found. |
|
Reviewed Verified independently on
So the repair restores detection rather than lowering the bar: the base test detected nothing at all (it died at its first operation, never reaching decode-drop behavior), and the repaired test catches both a recovery regression and a dead injection. The four decisions you carried over from #745 are still open and still pre-existing (log-string coupling in assertions (3)/(4), convergence by — |
Backport of Repair the decode-drop-recovery stress test so the job can pass (#745, merged to
mainas 4bd15ec) ontov5.2, so thedecode-drop-recoverystress job can go green on the release line.Clean cherry-pick —
git diffagainst the original merge commit is byte-identical, so the rationale and the four open decisions raised for the reviewer in #745 carry over unchanged. Test-only: one.mjsfile, no product code.v5.2 is affected
Both defects are present on
v5.2(both date to #691, which is on this branch):integrationTests/cluster/decodeDropRecovery.test.mjs:151authorizesadd_nodewithctx.nodeA.HDB_ADMIN_USERNAME/HDB_ADMIN_PASSWORD— property names the harness does not expose, so the join goes out unauthenticated and A closes it1008 Unauthorized.after()passes bare node objects toteardownHarper, which early-returns on a falsyctx.harper, so both Harper children leak past teardown.Verified against the installed harness on this branch (
@harperfast/integration-testing0.7.1): the node object exposesadmin: { username, password }(dist/harperLifecycle.js:452) andteardownHarper(ctx)early-returns on!ctx.harper(dist/harperLifecycle.js:608). Anddecode-drop-recoveryis in this branch's stress matrix (.github/workflows/stress-tests.yaml:135), so the job runs here and is red for exactly these two reasons.Verification
Ran the stress test itself on this branch, at all three states, reproducing #745's table on
v5.2:origin/v5.2file)add_node,Connection closed Unauthorized 1008 and connection was required to sign certificate, HTTP 500So both hunks are independently load-bearing on this branch, not just on
main.The pass is non-vacuous. With logs pinned to a known directory, node B logged
Error decoding replication messageexactly 3 times (=POISON_COUNT) and node A 0 times, with 0Error handling incoming replication messageclose lines on either node — assertion (3) ruled on real decode drops, not on an injection that never fired. This is structural as well as observed: assertion (3) isok(/Error decoding replication message/.test(logB)), so the test cannot pass without a real drop.Not run: the full integration gate. This is a single stress-gated file that no other suite imports, so the blast radius is that file.
Complexity: easy