chore: initialize from frontend template 4dc033c
This commit is contained in:
@@ -0,0 +1,251 @@
|
||||
import { QueryClient } from "@tanstack/react-query";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { createOptimisticLayerRuntime } from "../../src/presentation/adapters/query/optimistic-layer-runtime.ts";
|
||||
import { createRuntimeIdentityRegistry } from "../../src/contracts/query-keys.ts";
|
||||
|
||||
function scope() {
|
||||
let current = true;
|
||||
const lifetime = new AbortController();
|
||||
return {
|
||||
snapshot: {
|
||||
generation: 1,
|
||||
fingerprint: "scope-token-00000001",
|
||||
identities: createRuntimeIdentityRegistry({
|
||||
tokenFactory: () => crypto.randomUUID(),
|
||||
}),
|
||||
signal: lifetime.signal,
|
||||
isCurrent: () => current,
|
||||
},
|
||||
expire: () => {
|
||||
current = false;
|
||||
lifetime.abort();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
describe("revision-safe optimistic layer runtime", () => {
|
||||
it.each(["ROLLBACK", "RECONCILE"] as const)(
|
||||
"rejects a composite-invalid candidate without losing prior %s authority",
|
||||
(authority) => {
|
||||
const client = new QueryClient();
|
||||
const key = ["query", "composite-candidate", authority];
|
||||
client.setQueryData(key, ["base"]);
|
||||
const selectedScope = scope();
|
||||
const runtime = createOptimisticLayerRuntime(client);
|
||||
const first = runtime.begin(
|
||||
key,
|
||||
"first",
|
||||
(previous, input) => [...(previous as string[]), input],
|
||||
selectedScope.snapshot,
|
||||
);
|
||||
if (authority === "RECONCILE") first?.markUncertain();
|
||||
|
||||
const second = runtime.begin(
|
||||
key,
|
||||
"second",
|
||||
(previous, input) => {
|
||||
const values = previous as string[];
|
||||
if (values.includes("first")) {
|
||||
throw new Error("candidate composes only over the base");
|
||||
}
|
||||
return [...values, input];
|
||||
},
|
||||
selectedScope.snapshot,
|
||||
);
|
||||
|
||||
expect(second).toBeNull();
|
||||
expect(client.getQueryData(key)).toEqual(["base", "first"]);
|
||||
if (authority === "ROLLBACK") {
|
||||
first?.rollback();
|
||||
} else {
|
||||
first?.reconcile("NOT_APPLIED");
|
||||
}
|
||||
expect(client.getQueryData(key)).toEqual(["base"]);
|
||||
},
|
||||
);
|
||||
|
||||
it("writes a prevalidated candidate without invoking its updater twice", () => {
|
||||
const client = new QueryClient();
|
||||
const key = ["query", "single-candidate-invocation"];
|
||||
client.setQueryData(key, ["base"]);
|
||||
const selectedScope = scope();
|
||||
const runtime = createOptimisticLayerRuntime(client);
|
||||
const first = runtime.begin(
|
||||
key,
|
||||
"first",
|
||||
(previous, input) => [...(previous as string[]), input],
|
||||
selectedScope.snapshot,
|
||||
);
|
||||
let candidateCalls = 0;
|
||||
|
||||
const second = runtime.begin(
|
||||
key,
|
||||
"second",
|
||||
(previous, input) => {
|
||||
candidateCalls += 1;
|
||||
if (candidateCalls > 1) {
|
||||
throw new Error("candidate updater must not be replayed on admission");
|
||||
}
|
||||
return [...(previous as string[]), input];
|
||||
},
|
||||
selectedScope.snapshot,
|
||||
);
|
||||
|
||||
expect(second).not.toBeNull();
|
||||
expect(candidateCalls).toBe(1);
|
||||
expect(client.getQueryData(key)).toEqual(["base", "first", "second"]);
|
||||
second?.rollback();
|
||||
expect(client.getQueryData(key)).toEqual(["base", "first"]);
|
||||
first?.rollback();
|
||||
expect(client.getQueryData(key)).toEqual(["base"]);
|
||||
});
|
||||
|
||||
it("removes only the failed layer when commands settle out of order", () => {
|
||||
const client = new QueryClient();
|
||||
const key = ["query", "resources"];
|
||||
client.setQueryData(key, ["base"]);
|
||||
const selectedScope = scope();
|
||||
const runtime = createOptimisticLayerRuntime(client);
|
||||
const append = (previous: unknown, input: string) => [
|
||||
...(previous as string[]),
|
||||
input,
|
||||
];
|
||||
const first = runtime.begin(
|
||||
key,
|
||||
"first",
|
||||
append,
|
||||
selectedScope.snapshot,
|
||||
);
|
||||
const second = runtime.begin(
|
||||
key,
|
||||
"second",
|
||||
append,
|
||||
selectedScope.snapshot,
|
||||
);
|
||||
expect(client.getQueryData(key)).toEqual(["base", "first", "second"]);
|
||||
|
||||
second?.commit();
|
||||
first?.rollback();
|
||||
expect(client.getQueryData(key)).toEqual(["base", "second"]);
|
||||
});
|
||||
|
||||
it("reapplies pending layers over an authoritative external cache update", () => {
|
||||
const client = new QueryClient();
|
||||
const key = ["query", "resources"];
|
||||
client.setQueryData(key, ["base"]);
|
||||
const selectedScope = scope();
|
||||
const runtime = createOptimisticLayerRuntime(client);
|
||||
runtime.begin(
|
||||
key,
|
||||
"pending",
|
||||
(previous, input) => [...(previous as string[]), input],
|
||||
selectedScope.snapshot,
|
||||
);
|
||||
|
||||
client.setQueryData(key, ["server"]);
|
||||
expect(client.getQueryData(key)).toEqual(["server", "pending"]);
|
||||
});
|
||||
|
||||
it("keeps later committed layers projected while an earlier effect is uncertain", () => {
|
||||
const client = new QueryClient();
|
||||
const key = ["query", "resources"];
|
||||
client.setQueryData(key, ["base"]);
|
||||
const selectedScope = scope();
|
||||
const runtime = createOptimisticLayerRuntime(client);
|
||||
const append = (previous: unknown, input: string) => [
|
||||
...(previous as string[]),
|
||||
input,
|
||||
];
|
||||
const first = runtime.begin(
|
||||
key,
|
||||
"first",
|
||||
append,
|
||||
selectedScope.snapshot,
|
||||
);
|
||||
const second = runtime.begin(
|
||||
key,
|
||||
"second",
|
||||
append,
|
||||
selectedScope.snapshot,
|
||||
);
|
||||
|
||||
first?.markUncertain();
|
||||
first?.commit();
|
||||
first?.rollback();
|
||||
second?.commit();
|
||||
expect(client.getQueryData(key)).toEqual(["base", "first", "second"]);
|
||||
|
||||
first?.reconcile("NOT_APPLIED");
|
||||
expect(client.getQueryData(key)).toEqual(["base", "second"]);
|
||||
});
|
||||
|
||||
it("collapses uncertain and later committed layers in order when reconciled as applied", () => {
|
||||
const client = new QueryClient();
|
||||
const key = ["query", "resources"];
|
||||
client.setQueryData(key, ["base"]);
|
||||
const selectedScope = scope();
|
||||
const runtime = createOptimisticLayerRuntime(client);
|
||||
const append = (previous: unknown, input: string) => [
|
||||
...(previous as string[]),
|
||||
input,
|
||||
];
|
||||
const first = runtime.begin(
|
||||
key,
|
||||
"first",
|
||||
append,
|
||||
selectedScope.snapshot,
|
||||
);
|
||||
const second = runtime.begin(
|
||||
key,
|
||||
"second",
|
||||
append,
|
||||
selectedScope.snapshot,
|
||||
);
|
||||
|
||||
first?.markUncertain();
|
||||
second?.commit();
|
||||
first?.reconcile("APPLIED");
|
||||
expect(client.getQueryData(key)).toEqual(["base", "first", "second"]);
|
||||
|
||||
first?.reconcile("NOT_APPLIED");
|
||||
expect(client.getQueryData(key)).toEqual(["base", "first", "second"]);
|
||||
});
|
||||
|
||||
it("removes scoped data instead of restoring it after scope expiry", () => {
|
||||
const client = new QueryClient();
|
||||
const key = ["query", "resources"];
|
||||
client.setQueryData(key, ["base"]);
|
||||
const selectedScope = scope();
|
||||
const runtime = createOptimisticLayerRuntime(client);
|
||||
const layer = runtime.begin(
|
||||
key,
|
||||
"pending",
|
||||
(previous, input) => [...(previous as string[]), input],
|
||||
selectedScope.snapshot,
|
||||
);
|
||||
selectedScope.expire();
|
||||
layer?.rollback();
|
||||
expect(client.getQueryData(key)).toBeUndefined();
|
||||
});
|
||||
|
||||
it("does not restore an uncertain layer after its scope expires", () => {
|
||||
const client = new QueryClient();
|
||||
const key = ["query", "resources"];
|
||||
client.setQueryData(key, ["base"]);
|
||||
const selectedScope = scope();
|
||||
const runtime = createOptimisticLayerRuntime(client);
|
||||
const layer = runtime.begin(
|
||||
key,
|
||||
"uncertain",
|
||||
(previous, input) => [...(previous as string[]), input],
|
||||
selectedScope.snapshot,
|
||||
);
|
||||
layer?.markUncertain();
|
||||
|
||||
selectedScope.expire();
|
||||
layer?.reconcile("APPLIED");
|
||||
|
||||
expect(client.getQueryData(key)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user