Skip to content

Commit 040731c

Browse files
authored
fix: cancel the body stream when not consumed (#789)
1 parent e0f39b6 commit 040731c

File tree

6 files changed

+36
-4
lines changed

6 files changed

+36
-4
lines changed

.changeset/eager-steaks-crash.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@opennextjs/cloudflare": patch
3+
---
4+
5+
cancel the body stream when unconsumed

packages/cloudflare/src/api/durable-objects/queue.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,14 +111,15 @@ export class DOQueueHandler extends DurableObject<CloudflareEnv> {
111111
}
112112

113113
async executeRevalidation(msg: QueueMessage) {
114+
let response: Response | undefined;
114115
try {
115116
debug(`Revalidating ${msg.MessageBody.host}${msg.MessageBody.url}`);
116117
const {
117118
MessageBody: { host, url },
118119
} = msg;
119120
const protocol = host.includes("localhost") ? "http" : "https";
120121

121-
const response = await this.service.fetch(`${protocol}://${host}${url}`, {
122+
response = await this.service.fetch(`${protocol}://${host}${url}`, {
122123
method: "HEAD",
123124
headers: {
124125
// This is defined during build
@@ -177,6 +178,12 @@ export class DOQueueHandler extends DurableObject<CloudflareEnv> {
177178
error(e);
178179
} finally {
179180
this.ongoingRevalidations.delete(msg.MessageDeduplicationId);
181+
// Cancel the stream when it has not been consumed
182+
try {
183+
await response?.body?.cancel();
184+
} catch {
185+
// Ignore errors when the stream was actually consumed
186+
}
180187
}
181188
}
182189

packages/cloudflare/src/api/overrides/asset-resolver/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const resolver: AssetResolver = {
3636
});
3737

3838
if (response.status === 404) {
39+
await response.body?.cancel();
3940
return undefined;
4041
}
4142

packages/cloudflare/src/api/overrides/incremental-cache/static-assets-incremental-cache.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ class StaticAssetsIncrementalCache implements IncrementalCache {
3434

3535
try {
3636
const response = await assets.fetch(this.getAssetUrl(key, cacheType));
37-
if (!response.ok) return null;
37+
if (!response.ok) {
38+
await response.body?.cancel();
39+
return null;
40+
}
3841

3942
return {
4043
value: await response.json(),

packages/cloudflare/src/api/overrides/internal.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,9 @@ export async function internalPurgeCacheByTags(env: CloudflareEnv, tags: string[
5454
return "missing-credentials";
5555
}
5656

57+
let response: Response | undefined;
5758
try {
58-
const response = await fetch(
59+
response = await fetch(
5960
`https://api.cloudflare.com/client/v4/zones/${env.CACHE_PURGE_ZONE_ID}/purge_cache`,
6061
{
6162
headers: {
@@ -90,5 +91,12 @@ export async function internalPurgeCacheByTags(env: CloudflareEnv, tags: string[
9091
} catch (error) {
9192
console.error("Error purging cache by tags:", error);
9293
return "purge-failed";
94+
} finally {
95+
// Cancel the stream when it has not been consumed
96+
try {
97+
await response?.body?.cancel();
98+
} catch {
99+
// Ignore errors when the stream was actually consumed
100+
}
93101
}
94102
}

packages/cloudflare/src/api/overrides/queue/memory-queue.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,15 @@ export class MemoryQueue implements Queue {
2929

3030
this.revalidatedPaths.add(MessageDeduplicationId);
3131

32+
let response: Response | undefined;
33+
3234
try {
3335
const protocol = host.includes("localhost") ? "http" : "https";
3436

3537
// TODO: Drop the import - https://github.com/opennextjs/opennextjs-cloudflare/issues/361
3638
// @ts-ignore
3739
const manifest = await import("./.next/prerender-manifest.json");
38-
const response = await service.fetch(`${protocol}://${host}${url}`, {
40+
response = await service.fetch(`${protocol}://${host}${url}`, {
3941
method: "HEAD",
4042
headers: {
4143
"x-prerender-revalidate": manifest.preview.previewModeId,
@@ -54,6 +56,12 @@ export class MemoryQueue implements Queue {
5456
error(e);
5557
} finally {
5658
this.revalidatedPaths.delete(MessageDeduplicationId);
59+
// Cancel the stream when it has not been consumed
60+
try {
61+
await response?.body?.cancel();
62+
} catch {
63+
// Ignore errors when the stream was actually consumed
64+
}
5765
}
5866
}
5967
}

0 commit comments

Comments
 (0)