refactor(integrationTests): extract waitForRouteReady from restartHttpWorkers#1904
refactor(integrationTests): extract waitForRouteReady from restartHttpWorkers#1904kriszyp wants to merge 2 commits into
Conversation
…pWorkers The HTTP-route-readiness polling loop was duplicated: restartHttpWorkers() in lifecycle.mjs has it inline, and eviction-secondary-index.test.ts re-implements the same ~15-line block verbatim for the no-restart-needed case (component pre-installed). Extract the polling loop into a standalone exported waitForRouteReady(client, probePath, timeoutMs), used both by restartHttpWorkers() internally and directly by tests that only need to await route registration without triggering a worker restart. Refs #1886 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Reviewed; no blockers found. One non-blocking suggestion posted inline. |
There was a problem hiding this comment.
Code Review
This pull request extracts the route readiness polling logic into a reusable helper function waitForRouteReady in lifecycle.mjs and refactors restartHttpWorkers and the eviction secondary index test to use it. The review feedback suggests preserving the causal chain of errors by attaching the original error as the cause property when throwing new errors in both waitForRouteReady and restartHttpWorkers.
| throw new Error( | ||
| `Probe ${probePath} did not become ready within ${timeoutMs}ms ` + | ||
| `(last status=${lastStatus ?? 'none'}, last error=${lastError?.message ?? 'none'})` | ||
| ); |
There was a problem hiding this comment.
When throwing a timeout error after polling, attaching the last encountered error ('lastError') as the 'cause' property of the new 'Error' preserves the causal chain, making it much easier to diagnose why the probe failed (e.g., connection refused vs. invalid response).
throw new Error(
'Probe ' + probePath + ' did not become ready within ' + timeoutMs + 'ms ' +
'(last status=' + (lastStatus ?? 'none') + ', last error=' + (lastError?.message ?? 'none') + ')',
{ cause: lastError }
);References
- Avoid mutating the message property of a caught error object. Instead, throw a new custom error with the decorated message and attach the original error as the cause property to preserve the causal chain.
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
| } | ||
| throw new Error( | ||
| `Probe ${probePath} did not become ready within ${timeoutMs}ms ` + | ||
| `(last status=${lastStatus ?? 'none'}, last error=${lastError?.message ?? 'none'})` |
There was a problem hiding this comment.
Suggestion (non-blocking): attach lastError as the cause on this timeout Error (same pattern already applied at line 79 for the restartHttpWorkers wrapper). Preserves the causal chain for debugging a probe failure vs. an unreachable route.
| `(last status=${lastStatus ?? 'none'}, last error=${lastError?.message ?? 'none'})` | |
| throw new Error( | |
| `Probe ${probePath} did not become ready within ${timeoutMs}ms ` + | |
| `(last status=${lastStatus ?? 'none'}, last error=${lastError?.message ?? 'none'})`, | |
| { cause: lastError } | |
| ); |
What / why
Review finding on PR #1886 (test(database): promote 2 QA secondary-index integrity anchors) noted that the "poll for HTTP-route readiness after fixture boot" logic is duplicated:
restartHttpWorkers()inintegrationTests/apiTests/utils/lifecycle.mjshas the ~15-line poll loop inline, andintegrationTests/database/eviction-secondary-index.test.tsre-implements the same loop verbatim for its no-restart-needed case (the component is pre-installed there, so it can't callrestartHttpWorkers— it only needs the readiness poll, not the restart).This extracts the poll loop into a standalone exported
waitForRouteReady(client, probePath, timeoutMs), whichrestartHttpWorkers()now calls internally, and whicheviction-secondary-index.test.tscalls directly instead of duplicating the block. Behavior is unchanged —restartHttpWorkers()'s timeout budgeting and error message are preserved (the error message getsafter restart_serviceappended, same as before).Scope note
The finding's suggested location was a shared helper in
@harperfast/integration-testing(an external published package). The actual duplicated code lives inintegrationTests/apiTests/utils/lifecycle.mjswithin this repo (already the shared home forrestartHttpWorkersand other test-lifecycle helpers) — not in the external package, which is only used here forsetupHarperWithFixture/teardownHarper. Keeping the fix in-repo avoids a cross-repo publish/version-bump coordination for what's a same-repo duplication.The two other files named in the finding (
aborted-update-index-migration.test.ts,eviction-index-atomicity-lmdb.test.ts) exist only on PR #1886's branch (not yet merged tomain), so they aren't touched here; once that PR lands they'd be natural candidates to adoptwaitForRouteReadytoo if they have the same duplicated block.Test plan
npm run build— clean.npm run test:integration -- "integrationTests/database/eviction-secondary-index.test.ts"— 3/3 pass (exercises the newwaitForRouteReadycall site).npm run test:integration -- "integrationTests/database/multi-condition-query.test.ts"— 7/7 pass (exercisesrestartHttpWorkers, confirming the refactor didn't change its behavior).prettier --check/oxlintclean on both changed files.Generated by Claude Sonnet 5 (dev-agent, dispatch
finding-fix-harper-sorr).🤖 Generated with Claude Code