Skip to content

refactor(integrationTests): extract waitForRouteReady from restartHttpWorkers#1904

Open
kriszyp wants to merge 2 commits into
mainfrom
refactor/waitForRouteReady-helper
Open

refactor(integrationTests): extract waitForRouteReady from restartHttpWorkers#1904
kriszyp wants to merge 2 commits into
mainfrom
refactor/waitForRouteReady-helper

Conversation

@kriszyp

@kriszyp kriszyp commented Jul 23, 2026

Copy link
Copy Markdown
Member

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() in integrationTests/apiTests/utils/lifecycle.mjs has the ~15-line poll loop inline, and integrationTests/database/eviction-secondary-index.test.ts re-implements the same loop verbatim for its no-restart-needed case (the component is pre-installed there, so it can't call restartHttpWorkers — it only needs the readiness poll, not the restart).

This extracts the poll loop into a standalone exported waitForRouteReady(client, probePath, timeoutMs), which restartHttpWorkers() now calls internally, and which eviction-secondary-index.test.ts calls directly instead of duplicating the block. Behavior is unchanged — restartHttpWorkers()'s timeout budgeting and error message are preserved (the error message gets after restart_service appended, 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 in integrationTests/apiTests/utils/lifecycle.mjs within this repo (already the shared home for restartHttpWorkers and other test-lifecycle helpers) — not in the external package, which is only used here for setupHarperWithFixture/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 to main), so they aren't touched here; once that PR lands they'd be natural candidates to adopt waitForRouteReady too 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 new waitForRouteReady call site).
  • npm run test:integration -- "integrationTests/database/multi-condition-query.test.ts" — 7/7 pass (exercises restartHttpWorkers, confirming the refactor didn't change its behavior).
  • prettier --check / oxlint clean on both changed files.

Generated by Claude Sonnet 5 (dev-agent, dispatch finding-fix-harper-sorr).

🤖 Generated with Claude Code

…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>
@kriszyp
kriszyp requested a review from Ethan-Arrowood July 23, 2026 01:54
@claude

claude Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Reviewed; no blockers found. One non-blocking suggestion posted inline.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +35 to +38
throw new Error(
`Probe ${probePath} did not become ready within ${timeoutMs}ms ` +
`(last status=${lastStatus ?? 'none'}, last error=${lastError?.message ?? 'none'})`
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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
  1. 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.

Comment thread integrationTests/apiTests/utils/lifecycle.mjs
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@kriszyp
kriszyp marked this pull request as ready for review July 23, 2026 14:13
}
throw new Error(
`Probe ${probePath} did not become ready within ${timeoutMs}ms ` +
`(last status=${lastStatus ?? 'none'}, last error=${lastError?.message ?? 'none'})`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
`(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 }
);

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