-
Notifications
You must be signed in to change notification settings - Fork 118
Expand file tree
/
Copy pathmemory-queue.ts
More file actions
70 lines (57 loc) · 2.32 KB
/
memory-queue.ts
File metadata and controls
70 lines (57 loc) · 2.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import { error } from "@opennextjs/aws/adapters/logger.js";
import type { Queue, QueueMessage } from "@opennextjs/aws/types/overrides.js";
import { IgnorableError } from "@opennextjs/aws/utils/error.js";
import { getCloudflareContext } from "../../cloudflare-context.js";
import { debugCache } from "../internal.js";
export const DEFAULT_REVALIDATION_TIMEOUT_MS = 10_000;
/**
* The Memory Queue offers basic ISR revalidation by directly requesting a revalidation of a route.
*
* It offers basic support for in-memory de-duping per isolate.
*
* A service binding called `WORKER_SELF_REFERENCE` that points to your worker is required.
*/
export class MemoryQueue implements Queue {
readonly name = "memory-queue";
revalidatedPaths: Set<string> = new Set<string>();
constructor(
private opts: {
revalidationTimeoutMs: number;
} = { revalidationTimeoutMs: DEFAULT_REVALIDATION_TIMEOUT_MS }
) {}
async send({ MessageBody: { host, url }, MessageDeduplicationId }: QueueMessage): Promise<void> {
const service = getCloudflareContext().env.WORKER_SELF_REFERENCE;
if (!service) throw new IgnorableError("No service binding for cache revalidation worker");
if (this.revalidatedPaths.has(MessageDeduplicationId)) return;
this.revalidatedPaths.add(MessageDeduplicationId);
let response: Response | undefined;
try {
const protocol = host.includes("localhost") ? "http" : "https";
response = await service.fetch(`${protocol}://${host}${url}`, {
method: "HEAD",
headers: {
"x-prerender-revalidate": process.env.NEXT_PREVIEW_MODE_ID!,
"x-isr": "1",
},
// We want to timeout the revalidation to avoid hanging the queue
signal: AbortSignal.timeout(this.opts.revalidationTimeoutMs),
});
// Here we want at least to log when the revalidation was not successful
if (response.status !== 200 || response.headers.get("x-nextjs-cache") !== "REVALIDATED") {
error(`Revalidation failed for ${url} with status ${response.status}`);
}
debugCache(`Revalidation successful for ${url}`);
} catch (e) {
error(e);
} finally {
this.revalidatedPaths.delete(MessageDeduplicationId);
// Cancel the stream when it has not been consumed
try {
await response?.body?.cancel();
} catch {
// Ignore errors when the stream was actually consumed
}
}
}
}
export default new MemoryQueue();