Skip to content

test: integration tests for sourcedFrom and allowStaleWhileRevalidate#1208

Open
kriszyp wants to merge 4 commits into
mainfrom
kris/integration-test-cache-patterns
Open

test: integration tests for sourcedFrom and allowStaleWhileRevalidate#1208
kriszyp wants to merge 4 commits into
mainfrom
kris/integration-test-cache-patterns

Conversation

@kriszyp

@kriszyp kriszyp commented Jun 9, 2026

Copy link
Copy Markdown
Member

Closes #1189

Summary

After review feedback from Nathan Heskew: the four tests originally in this PR (cache miss/hit, 404 passthrough, DELETE invalidation, SWR) duplicate coverage already comprehensively provided by unitTests/resources/caching.test.js. This PR has been scoped down accordingly.

The file integrationTests/server/caching.test.ts now contains only an explanatory comment block that:

What changed

  • Removed ~350 lines of test code that duplicated unit coverage.
  • Added a 14-line comment/TODO block explaining the scope and the gap.

What's not here (and why)

replicationSource: true causes sourcedFrom to fetch on a replica node rather than the origin. Testing it end-to-end requires a live 2-node cluster setup. The tracking issue is #1189; a follow-up PR against integrationTests/ can add that once a cluster harness exists.

Generated by Claude Sonnet 4.6 (claude-sonnet-4-6[1m]).

kriszyp and others added 2 commits June 9, 2026 07:42
…date

Closes #1189

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@kriszyp kriszyp requested a review from Ethan-Arrowood June 9, 2026 13:44

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

Copy link
Copy Markdown

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 introduces a new integration test suite (caching.test.ts) to verify caching behaviors such as sourcedFrom() and allowStaleWhileRevalidate() end-to-end using a mock HTTP origin server. The feedback focuses on robust resource management within the tests: specifically, calling server.closeAllConnections() during teardown to prevent hanging connections, and ensuring all fetch response bodies are consumed to avoid potential socket leaks in Node.js.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread integrationTests/server/caching.test.ts Outdated

return {
url,
close: () => new Promise<void>((resolve, reject) => server.close((err) => (err ? reject(err) : resolve()))),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

To prevent hanging connections from keeping the test runner alive or causing timeouts during teardown, call server.closeAllConnections() immediately after calling server.close(). This ensures all active keep-alive connections (such as those from Harper's internal fetch client) are forcefully closed.

Suggested change
close: () => new Promise<void>((resolve, reject) => server.close((err) => (err ? reject(err) : resolve()))),
close: () =>
new Promise<void>((resolve, reject) => {
server.close((err) => (err ? reject(err) : resolve()));
server.closeAllConnections();
}),

Comment thread integrationTests/server/caching.test.ts Outdated
Comment on lines +252 to +254
const r = await fetch(`${baseUrl}/CachedProduct/${id}`, { headers: { Authorization: authHeader } });
strictEqual(r.status, 404, 'Should return 404 when origin returns 404');
strictEqual(origin.fetchCount(id), 1, 'Origin should have been called once');

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The response body of the fetch call is not consumed. In Node.js (via undici), leaving response bodies unconsumed can lead to socket leaks and hanging connections. It is recommended to consume the body (e.g., by calling await r.arrayBuffer() or await r.text()) even for error responses like 404.

		const r = await fetch(`${baseUrl}/CachedProduct/${id}`, { headers: { Authorization: authHeader } });
		strictEqual(r.status, 404, 'Should return 404 when origin returns 404');
		await r.arrayBuffer();
		strictEqual(origin.fetchCount(id), 1, 'Origin should have been called once');

Comment thread integrationTests/server/caching.test.ts Outdated
Comment on lines +269 to +271
const r1 = await fetch(`${baseUrl}/CachedProduct/${id}`, { headers: { Authorization: authHeader } });
strictEqual(r1.status, 200);
strictEqual(origin.fetchCount(id), 1, 'Should fetch from origin on first GET');

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The response body of r1 is not consumed. To prevent socket leaks and ensure the connection is released back to the pool, consume the response body.

Suggested change
const r1 = await fetch(`${baseUrl}/CachedProduct/${id}`, { headers: { Authorization: authHeader } });
strictEqual(r1.status, 200);
strictEqual(origin.fetchCount(id), 1, 'Should fetch from origin on first GET');
const r1 = await fetch(`${baseUrl}/CachedProduct/${id}`, { headers: { Authorization: authHeader } });
strictEqual(r1.status, 200);
await r1.arrayBuffer();
strictEqual(origin.fetchCount(id), 1, 'Should fetch from origin on first GET');

Comment thread integrationTests/server/caching.test.ts Outdated
Comment on lines +274 to +278
const rDel = await fetch(`${baseUrl}/CachedProduct/${id}`, {
method: 'DELETE',
headers: { Authorization: authHeader },
});
ok(rDel.status === 200 || rDel.status === 204, `DELETE should succeed, got ${rDel.status}`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The response body of the DELETE request is not consumed. Consume the response body to prevent potential socket leaks.

Suggested change
const rDel = await fetch(`${baseUrl}/CachedProduct/${id}`, {
method: 'DELETE',
headers: { Authorization: authHeader },
});
ok(rDel.status === 200 || rDel.status === 204, `DELETE should succeed, got ${rDel.status}`);
const rDel = await fetch(`${baseUrl}/CachedProduct/${id}`, {
method: 'DELETE',
headers: { Authorization: authHeader },
});
ok(rDel.status === 200 || rDel.status === 204, `DELETE should succeed, got ${rDel.status}`);
await rDel.arrayBuffer();

@claude

claude Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Reviewed; no blockers found.

@kriszyp kriszyp marked this pull request as ready for review June 9, 2026 14:13
…on teardown, consume fetch bodies

- Call server.closeAllConnections() before server.close() in MockOrigin.close() to
  drain keep-alive sockets immediately on teardown (Node ≥18.2, safe for engine ≥20).
- Consume response bodies with .text() on the three fetch calls that only checked
  status (404 propagation test, DELETE test r1 and rDel) to avoid socket leaks.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…o unit suite (#1208)

The four previous tests (cache miss/hit, 404 passthrough, DELETE invalidation, SWR)
duplicate coverage already in unitTests/resources/caching.test.js. Replace them with
an explanatory comment block and a TODO pointing to issue #1189 for the one genuinely
new scenario (replicationSource: true) that requires a 2-node cluster harness not yet
available in integrationTests/.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

Add integration tests for sourcedFrom, stale-while-revalidate, and replicationSource cache patterns

1 participant