fix(news): persist publication requests and retry cache delivery
This commit is contained in:
1 parent
c977fe95ba
commit
52f6d1491f
40 files changed
+733
-134
No files matched your search
@@ -53,7 +53,10 @@ export function operationHash(value: unknown) {
|
||||
export function retryDelay(attempt: number) {
|
||||
return Math.min(3600, 60 * 2 ** Math.max(0, attempt - 1));
|
||||
}
|
||||
export type EffectTopic = "catalog.refresh" | "catalog.export.request";
|
||||
export type EffectTopic =
|
||||
| "catalog.refresh"
|
||||
| "catalog.export.request"
|
||||
| "news.refresh";
|
||||
export interface EffectClaim {
|
||||
id: string;
|
||||
token: string;
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import { beforeEach, expect, it, vi } from "vitest";
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
claim: vi.fn(),
|
||||
complete: vi.fn(),
|
||||
fail: vi.fn(),
|
||||
news: vi.fn(),
|
||||
catalog: vi.fn(),
|
||||
exportEnabled: vi.fn(),
|
||||
request: vi.fn(),
|
||||
error: vi.fn(),
|
||||
}));
|
||||
vi.mock("./server", () => ({
|
||||
effectRepository: {
|
||||
claim: mocks.claim,
|
||||
complete: mocks.complete,
|
||||
fail: mocks.fail,
|
||||
},
|
||||
}));
|
||||
vi.mock("@/lib/services/news-cache", () => ({
|
||||
refreshNewsCacheForDelivery: mocks.news,
|
||||
}));
|
||||
vi.mock("@/features/catalog/server/sync-status", () => ({
|
||||
sendCatalogUpdate: mocks.catalog,
|
||||
}));
|
||||
vi.mock("@/lib/services/catalog-git-queue", () => ({
|
||||
catalogExportEnabled: mocks.exportEnabled,
|
||||
catalogExportQueue: () => ({ request: mocks.request }),
|
||||
}));
|
||||
vi.mock("@/lib/logger", () => ({ logger: { error: mocks.error } }));
|
||||
|
||||
import { drainOperationEffects } from "./worker";
|
||||
|
||||
const effect = {
|
||||
id: "one",
|
||||
token: "lease",
|
||||
attempts: 1,
|
||||
topic: "news.refresh",
|
||||
};
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
mocks.claim.mockResolvedValueOnce(effect).mockResolvedValue(null);
|
||||
mocks.news.mockResolvedValue(undefined);
|
||||
});
|
||||
it("invalidates the shared news cache before acknowledging delivery", async () => {
|
||||
await drainOperationEffects();
|
||||
expect(mocks.news).toHaveBeenCalledTimes(1);
|
||||
expect(mocks.complete).toHaveBeenCalledWith(effect);
|
||||
expect(mocks.fail).not.toHaveBeenCalled();
|
||||
});
|
||||
it("keeps a failed news invalidation retryable", async () => {
|
||||
mocks.news.mockRejectedValue(new Error("Redis unavailable"));
|
||||
await drainOperationEffects();
|
||||
expect(mocks.fail).toHaveBeenCalledWith(effect);
|
||||
expect(mocks.complete).not.toHaveBeenCalled();
|
||||
});
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
catalogExportEnabled,
|
||||
catalogExportQueue,
|
||||
} from "@/lib/services/catalog-git-queue";
|
||||
import { refreshNewsCacheForDelivery } from "@/lib/services/news-cache";
|
||||
import { dispatchEffects } from "./dispatcher";
|
||||
import { effectRepository } from "./server";
|
||||
|
||||
@@ -19,6 +20,8 @@ export async function drainOperationEffects() {
|
||||
throw new Error("Hotel update not delivered");
|
||||
} else if (claim.topic === "catalog.export.request") {
|
||||
if (catalogExportEnabled()) await catalogExportQueue().request();
|
||||
} else if (claim.topic === "news.refresh") {
|
||||
await refreshNewsCacheForDelivery();
|
||||
} else throw new Error("Unknown delivery topic");
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
Reference in new issue
Block a user