diff --git a/packages/cloudflare/src/api/memory-queue.spec.ts b/packages/cloudflare/src/api/memory-queue.spec.ts new file mode 100644 index 00000000..ccd277db --- /dev/null +++ b/packages/cloudflare/src/api/memory-queue.spec.ts @@ -0,0 +1,43 @@ +import { generateMessageGroupId } from "@opennextjs/aws/core/routing/queue.js"; +import { beforeAll, describe, expect, it, vi } from "vitest"; + +import cache from "./memory-queue"; + +vi.mock("./.next/prerender-manifest.json", () => ({ + preview: { previewModeId: "id" }, +})); + +const defaultOpts = { + MessageBody: { host: "test.local", url: "/test" }, + MessageGroupId: generateMessageGroupId("/test"), + MessageDeduplicationId: "", +}; + +describe("MemoryQueue", () => { + beforeAll(() => { + vi.useFakeTimers(); + globalThis.internalFetch = vi.fn(); + }); + + it("should de-dupe revalidations", async () => { + await cache.send(defaultOpts); + expect(globalThis.internalFetch).toHaveBeenCalledTimes(1); + await cache.send(defaultOpts); + expect(globalThis.internalFetch).toHaveBeenCalledTimes(1); + + cache.remove("/test"); + + await cache.send(defaultOpts); + expect(globalThis.internalFetch).toHaveBeenCalledTimes(2); + await cache.send(defaultOpts); + expect(globalThis.internalFetch).toHaveBeenCalledTimes(2); + + vi.advanceTimersByTime(10_000); + + await cache.send(defaultOpts); + expect(globalThis.internalFetch).toHaveBeenCalledTimes(3); + + await cache.send({ ...defaultOpts, MessageGroupId: generateMessageGroupId("/other") }); + expect(globalThis.internalFetch).toHaveBeenCalledTimes(4); + }); +}); diff --git a/packages/cloudflare/src/api/memory-queue.ts b/packages/cloudflare/src/api/memory-queue.ts index 8e61627e..c64c4d2f 100644 --- a/packages/cloudflare/src/api/memory-queue.ts +++ b/packages/cloudflare/src/api/memory-queue.ts @@ -13,6 +13,8 @@ class MemoryQueue implements Queue { public revalidatedPaths = new Map>(); public async send({ MessageBody: { host, url }, MessageGroupId }: QueueMessage): Promise { + if (this.revalidatedPaths.has(MessageGroupId)) return; + this.revalidatedPaths.set( MessageGroupId, // force remove to allow new revalidations incase something went wrong