chore: initialize from frontend template 4dc033c

This commit is contained in:
DongHyeonka
2026-08-13 18:23:26 +09:00
commit 40107eec84
897 changed files with 234824 additions and 0 deletions
@@ -0,0 +1,876 @@
import { describe, expect, it, vi } from "vitest";
import type { ClockPort } from "../../../src/application/ports/clock-port.ts";
import { definePollLeasePolicy } from "../../../src/application/policies/bounded-polling.ts";
import {
createBoundedPollCoordinator,
type BoundedPollAttemptResult,
type BoundedPollEnvironment,
} from "../../../src/adapters/realtime/polling/bounded-poll-coordinator.ts";
type Sleeper = {
dueAt: number;
resolve(): void;
reject(): void;
signal?: AbortSignal;
onAbort?: () => void;
};
class ManualClock implements ClockPort {
current = 0;
readonly sleepers: Sleeper[] = [];
now(): number {
return this.current;
}
sleep(milliseconds: number, signal?: AbortSignal): Promise<void> {
return new Promise((resolve, reject) => {
if (signal?.aborted) {
reject(new DOMException("Aborted", "AbortError"));
return;
}
const sleeper: Sleeper = {
dueAt: this.current + milliseconds,
resolve: () => {
signal?.removeEventListener("abort", sleeper.onAbort!);
resolve();
},
reject: () => {
signal?.removeEventListener("abort", sleeper.onAbort!);
reject(new DOMException("Aborted", "AbortError"));
},
signal,
};
sleeper.onAbort = () => {
this.remove(sleeper);
sleeper.reject();
};
signal?.addEventListener("abort", sleeper.onAbort, {
once: true,
});
this.sleepers.push(sleeper);
});
}
advance(milliseconds: number): void {
this.current += milliseconds;
const ready = this.sleepers
.filter((sleeper) => sleeper.dueAt <= this.current)
.sort((left, right) => left.dueAt - right.dueAt);
for (const sleeper of ready) {
this.remove(sleeper);
sleeper.resolve();
}
}
private remove(target: Sleeper): void {
const index = this.sleepers.indexOf(target);
if (index >= 0) this.sleepers.splice(index, 1);
}
}
class MutableEnvironment implements BoundedPollEnvironment {
visible = true;
connected = true;
readonly visibilityListeners = new Set<
(visibility: "HIDDEN" | "VISIBLE") => void
>();
readonly onlineListeners = new Set<(online: boolean) => void>();
visibility(): "HIDDEN" | "VISIBLE" {
return this.visible ? "VISIBLE" : "HIDDEN";
}
online(): boolean {
return this.connected;
}
subscribeVisibility(
listener: (visibility: "HIDDEN" | "VISIBLE") => void,
): () => void {
this.visibilityListeners.add(listener);
return () => this.visibilityListeners.delete(listener);
}
subscribeOnline(listener: (online: boolean) => void): () => void {
this.onlineListeners.add(listener);
return () => this.onlineListeners.delete(listener);
}
hide(): void {
this.visible = false;
for (const listener of this.visibilityListeners) listener("HIDDEN");
}
}
const policy = definePollLeasePolicy({
operationId: "GET_JOB_STATUS",
owner: "reference-job",
minimumIntervalMs: 5_000,
successIntervalMs: 5_000,
maxIntervalMs: 60_000,
maxAttempts: 3,
maxElapsedMs: 60_000,
maxResponseBytes: 1_024,
visibility: "VISIBLE_ONLY",
fallbackReason: "CONVERGENCE",
terminalStates: ["COMPLETED", "FAILED"],
});
const operation = {
operationId: "GET_JOB_STATUS",
contractVersion: 2,
protocol: "REST",
semantics: "QUERY",
method: "GET",
replayPolicy: "SAFE",
retry: "never",
maxResponseBytes: 1_024,
transportMaxAttempts: 1,
authRecoveryCount: 0,
maxCumulativeSleepMs: 0,
serverStream: false,
} as const;
async function flush(): Promise<void> {
for (let turn = 0; turn < 12; turn += 1) {
await Promise.resolve();
}
}
describe("bounded poll coordinator", () => {
it("chains completed attempts without overlap and stops at a terminal state", async () => {
const clock = new ManualClock();
const environment = new MutableEnvironment();
let active = 0;
let highWatermark = 0;
const execute = vi
.fn<
(
input: Readonly<{
operationId: string;
attempt: number;
maxResponseBytes: number;
signal: AbortSignal;
}>,
) => Promise<BoundedPollAttemptResult<string>>
>()
.mockImplementation(async ({ attempt }) => {
active += 1;
highWatermark = Math.max(highWatermark, active);
await Promise.resolve();
active -= 1;
return {
ok: true,
value: {
kind: "VALUE",
value: attempt === 1 ? "working" : "done",
responseBytes: 32,
state: attempt === 1 ? "RUNNING" : "COMPLETED",
},
};
});
const onValue = vi.fn();
const coordinator = createBoundedPollCoordinator({
policy,
operation,
execute,
environment,
clock,
random: () => 0.5,
});
const result = coordinator.run({ onValue });
expect(execute).not.toHaveBeenCalled();
clock.advance(5_000);
await flush();
expect(execute).toHaveBeenCalledTimes(1);
expect(clock.sleepers).toHaveLength(1);
clock.advance(5_000);
await flush();
await expect(result).resolves.toEqual({
ok: true,
value: {
kind: "TERMINAL",
attempts: 2,
state: "COMPLETED",
value: "done",
},
});
expect(onValue.mock.calls.map(([value]) => value)).toEqual([
"working",
"done",
]);
expect(highWatermark).toBe(1);
expect(coordinator.getState()).toBe("IDLE");
expect(environment.visibilityListeners.size).toBe(0);
expect(environment.onlineListeners.size).toBe(0);
});
it("passes the strictest response ceiling to the executor before decode", async () => {
const clock = new ManualClock();
const execute = vi.fn(
async ({
maxResponseBytes,
}: Readonly<{ maxResponseBytes: number }>) => ({
ok: true as const,
value: {
kind: "VALUE" as const,
value: "done",
responseBytes: maxResponseBytes,
state: "COMPLETED",
},
}),
);
const coordinator = createBoundedPollCoordinator<string>({
policy,
operation: {
...operation,
maxResponseBytes: 4_096,
},
execute,
environment: new MutableEnvironment(),
clock,
});
const pending = coordinator.run();
clock.advance(5_000);
await expect(pending).resolves.toMatchObject({
ok: true,
value: { state: "COMPLETED" },
});
expect(execute).toHaveBeenCalledWith(
expect.objectContaining({ maxResponseBytes: 1_024 }),
);
});
it("does not start another attempt while a request is unresolved", async () => {
const clock = new ManualClock();
const environment = new MutableEnvironment();
let resolveFirst:
| ((result: BoundedPollAttemptResult<string>) => void)
| undefined;
const execute = vi
.fn()
.mockImplementationOnce(
() =>
new Promise<BoundedPollAttemptResult<string>>((resolve) => {
resolveFirst = resolve;
}),
)
.mockResolvedValue({
ok: true,
value: {
kind: "VALUE",
value: "done",
responseBytes: 10,
state: "COMPLETED",
},
});
const coordinator = createBoundedPollCoordinator<string>({
policy,
operation,
execute,
environment,
clock,
random: () => 0.5,
});
const pending = coordinator.run();
clock.advance(5_000);
await flush();
expect(execute).toHaveBeenCalledTimes(1);
clock.advance(30_000);
await flush();
expect(execute).toHaveBeenCalledTimes(1);
resolveFirst?.({
ok: true,
value: { kind: "UNCHANGED", responseBytes: 0 },
});
await flush();
clock.advance(5_000);
await flush();
expect(execute).toHaveBeenCalledTimes(2);
await expect(pending).resolves.toMatchObject({
ok: true,
value: { attempts: 2, state: "COMPLETED" },
});
});
it("ends the lease when an in-flight executor ignores abort and exceeds max elapsed", async () => {
const clock = new ManualClock();
let attemptSignal: AbortSignal | undefined;
let settleAttempt:
| ((result: BoundedPollAttemptResult<string>) => void)
| undefined;
const execute = vi.fn(
({ signal }: Readonly<{ signal: AbortSignal }>) => {
attemptSignal = signal;
return new Promise<BoundedPollAttemptResult<string>>(
(resolve) => {
settleAttempt = resolve;
},
);
},
);
const coordinator = createBoundedPollCoordinator<string>({
policy,
operation,
execute,
environment: new MutableEnvironment(),
clock,
});
const pending = coordinator.run();
clock.advance(5_000);
await flush();
expect(execute).toHaveBeenCalledTimes(1);
expect(attemptSignal?.aborted).toBe(false);
clock.advance(54_999);
await flush();
expect(coordinator.getState()).toBe("RUNNING");
clock.advance(1);
await flush();
await expect(pending).resolves.toEqual({
ok: false,
error: {
kind: "POLL_BUDGET_EXHAUSTED",
operation: "POLL",
retryable: false,
},
});
expect(attemptSignal?.aborted).toBe(true);
expect(coordinator.getState()).toBe("DRAINING");
await expect(coordinator.run()).resolves.toMatchObject({
ok: false,
error: { kind: "PROTOCOL_MISMATCH" },
});
settleAttempt?.({
ok: false,
error: {
kind: "ABORTED",
operation: "POLL",
retryable: false,
},
});
await flush();
expect(coordinator.getState()).toBe("IDLE");
});
it("returns promptly when a caller aborts an executor that ignores its signal", async () => {
const clock = new ManualClock();
const caller = new AbortController();
let settleAttempt:
| ((result: BoundedPollAttemptResult<string>) => void)
| undefined;
const execute = vi.fn(
() =>
new Promise<BoundedPollAttemptResult<string>>(
(resolve) => {
settleAttempt = resolve;
},
),
);
const coordinator = createBoundedPollCoordinator<string>({
policy,
operation,
execute,
environment: new MutableEnvironment(),
clock,
});
const pending = coordinator.run({ signal: caller.signal });
clock.advance(5_000);
await flush();
expect(execute).toHaveBeenCalledTimes(1);
caller.abort();
await expect(pending).resolves.toEqual({
ok: false,
error: {
kind: "ABORTED",
operation: "POLL",
retryable: false,
},
});
expect(coordinator.getState()).toBe("DRAINING");
settleAttempt?.({
ok: false,
error: {
kind: "ABORTED",
operation: "POLL",
retryable: false,
},
});
await flush();
expect(coordinator.getState()).toBe("IDLE");
});
it("fails closed and aborts the attempt when the lease deadline clock is unavailable", async () => {
let current = 0;
let sleeps = 0;
const clock: ClockPort = {
now: () => current,
sleep: async (milliseconds) => {
sleeps += 1;
if (sleeps > 1) throw new Error("deadline unavailable");
current += milliseconds;
},
};
let attemptSignal: AbortSignal | undefined;
const execute = vi.fn(
async ({ signal }: Readonly<{ signal: AbortSignal }>) => {
attemptSignal = signal;
return {
ok: true as const,
value: {
kind: "UNCHANGED" as const,
responseBytes: 0 as const,
},
};
},
);
const coordinator = createBoundedPollCoordinator<string>({
policy,
operation,
execute,
environment: new MutableEnvironment(),
clock,
});
await expect(coordinator.run()).resolves.toEqual({
ok: false,
error: {
kind: "PROVIDER_UNAVAILABLE",
operation: "POLL",
retryable: false,
},
});
expect(execute).toHaveBeenCalledOnce();
expect(attemptSignal?.aborted).toBe(true);
});
it("fences a non-cooperative apply callback at the lease deadline", async () => {
const clock = new ManualClock();
let applyContext:
| Readonly<{
signal: AbortSignal;
isCurrent(): boolean;
}>
| undefined;
let releaseApply: (() => void) | undefined;
const coordinator = createBoundedPollCoordinator<string>({
policy,
operation,
execute: async () => ({
ok: true,
value: {
kind: "VALUE",
value: "working",
responseBytes: 10,
state: "RUNNING",
},
}),
environment: new MutableEnvironment(),
clock,
});
const pending = coordinator.run({
onValue: (_value, context) => {
applyContext = context;
return new Promise<void>((resolve) => {
releaseApply = resolve;
});
},
});
clock.advance(5_000);
await flush();
expect(applyContext?.isCurrent()).toBe(true);
clock.advance(55_000);
await flush();
await expect(pending).resolves.toEqual({
ok: false,
error: {
kind: "POLL_BUDGET_EXHAUSTED",
operation: "POLL",
retryable: false,
},
});
expect(applyContext?.signal.aborted).toBe(true);
expect(applyContext?.isCurrent()).toBe(false);
expect(coordinator.getState()).toBe("DRAINING");
releaseApply?.();
await flush();
expect(coordinator.getState()).toBe("IDLE");
});
it("honors Retry-After as a floor and exhausts finite attempts", async () => {
const clock = new ManualClock();
const execute = vi
.fn()
.mockResolvedValueOnce({
ok: false,
error: {
kind: "RATE_LIMITED",
operation: "POLL",
retryable: true,
retryAfterMs: 10_000,
},
})
.mockResolvedValue({
ok: true,
value: { kind: "UNCHANGED", responseBytes: 0 },
});
const coordinator = createBoundedPollCoordinator<string>({
policy: definePollLeasePolicy({
...policy,
maxAttempts: 2,
}),
operation,
execute,
environment: new MutableEnvironment(),
clock,
random: () => 0,
});
const pending = coordinator.run();
clock.advance(5_000);
await flush();
expect(execute).toHaveBeenCalledTimes(1);
clock.advance(9_999);
await flush();
expect(execute).toHaveBeenCalledTimes(1);
clock.advance(1);
await flush();
await expect(pending).resolves.toEqual({
ok: false,
error: {
kind: "POLL_BUDGET_EXHAUSTED",
operation: "POLL",
retryable: false,
},
});
expect(execute).toHaveBeenCalledTimes(2);
});
it.each(["RATE_LIMITED", "PROVIDER_UNAVAILABLE"] as const)(
"does not retry %s without a bounded server hint",
async (kind) => {
const clock = new ManualClock();
const execute = vi.fn().mockResolvedValue({
ok: false,
error: {
kind,
operation: "POLL",
retryable: true,
},
});
const coordinator = createBoundedPollCoordinator<string>({
policy,
operation,
execute,
environment: new MutableEnvironment(),
clock,
random: () => 0,
});
const pending = coordinator.run();
clock.advance(5_000);
await flush();
await expect(pending).resolves.toEqual({
ok: false,
error: {
kind,
operation: "POLL",
retryable: false,
},
});
expect(execute).toHaveBeenCalledTimes(1);
},
);
it("ignores Retry-After for retryable failure kinds that cannot carry the hint", async () => {
const clock = new ManualClock();
const execute = vi
.fn()
.mockResolvedValueOnce({
ok: false,
error: {
kind: "CONNECT_TIMEOUT",
operation: "POLL",
retryable: true,
retryAfterMs: 10_000,
},
})
.mockResolvedValue({
ok: true,
value: {
kind: "VALUE",
value: "done",
responseBytes: 10,
state: "COMPLETED",
},
});
const coordinator = createBoundedPollCoordinator<string>({
policy,
operation,
execute,
environment: new MutableEnvironment(),
clock,
random: () => 0,
});
const pending = coordinator.run();
clock.advance(5_000);
await flush();
expect(execute).toHaveBeenCalledTimes(1);
clock.advance(4_999);
await flush();
expect(execute).toHaveBeenCalledTimes(1);
clock.advance(1);
await expect(pending).resolves.toMatchObject({
ok: true,
value: { attempts: 2, state: "COMPLETED" },
});
expect(execute).toHaveBeenCalledTimes(2);
});
it.each(["AUTH_REQUIRED", "FORBIDDEN"] as const)(
"never retries terminal %s failures even when the executor marks them retryable",
async (kind) => {
const clock = new ManualClock();
const execute = vi.fn().mockResolvedValue({
ok: false,
error: {
kind,
operation: "POLL",
retryable: true,
retryAfterMs: 10_000,
},
});
const coordinator = createBoundedPollCoordinator<string>({
policy,
operation,
execute,
environment: new MutableEnvironment(),
clock,
});
const pending = coordinator.run();
clock.advance(5_000);
await expect(pending).resolves.toEqual({
ok: false,
error: {
kind,
operation: "POLL",
retryable: false,
},
});
expect(execute).toHaveBeenCalledOnce();
},
);
it("aborts in-flight work on hidden lifecycle and rejects late scope results", async () => {
const hiddenClock = new ManualClock();
const hiddenEnvironment = new MutableEnvironment();
const hiddenCoordinator = createBoundedPollCoordinator<string>({
policy,
operation,
environment: hiddenEnvironment,
clock: hiddenClock,
execute: ({ signal }) =>
new Promise((resolve) => {
signal.addEventListener(
"abort",
() =>
resolve({
ok: false,
error: {
kind: "ABORTED",
operation: "POLL",
retryable: false,
},
}),
{ once: true },
);
}),
});
const hidden = hiddenCoordinator.run();
hiddenClock.advance(5_000);
await flush();
hiddenEnvironment.hide();
await expect(hidden).resolves.toEqual({
ok: false,
error: {
kind: "ABORTED",
operation: "POLL",
retryable: false,
},
});
const scopeClock = new ManualClock();
let current = true;
let resolveAttempt:
| ((result: BoundedPollAttemptResult<string>) => void)
| undefined;
const onValue = vi.fn();
const scopeCoordinator = createBoundedPollCoordinator<string>({
policy,
operation,
environment: new MutableEnvironment(),
clock: scopeClock,
isCurrent: () => current,
execute: () =>
new Promise((resolve) => {
resolveAttempt = resolve;
}),
});
const fenced = scopeCoordinator.run({ onValue });
scopeClock.advance(5_000);
await flush();
current = false;
resolveAttempt?.({
ok: true,
value: {
kind: "VALUE",
value: "late",
responseBytes: 10,
state: "COMPLETED",
},
});
await expect(fenced).resolves.toEqual({
ok: false,
error: {
kind: "SCOPE_FENCED",
operation: "POLL",
retryable: false,
},
});
expect(onValue).not.toHaveBeenCalled();
});
it("rejects accessor and extra-key attempt results without re-reading them", async () => {
const accessorClock = new ManualClock();
const readOk = vi.fn(() => true);
const accessorResult = Object.defineProperties(
{},
{
ok: {
enumerable: true,
get: readOk,
},
value: {
enumerable: true,
value: {
kind: "VALUE",
value: "unsafe",
responseBytes: 1,
state: "COMPLETED",
},
},
},
) as BoundedPollAttemptResult<string>;
const accessorCoordinator = createBoundedPollCoordinator<string>({
policy,
operation,
environment: new MutableEnvironment(),
clock: accessorClock,
execute: async () => accessorResult,
});
const accessorRun = accessorCoordinator.run();
accessorClock.advance(5_000);
await expect(accessorRun).resolves.toMatchObject({
ok: false,
error: { kind: "PROTOCOL_MISMATCH" },
});
expect(readOk).not.toHaveBeenCalled();
const extraClock = new ManualClock();
const extraCoordinator = createBoundedPollCoordinator<string>({
policy,
operation,
environment: new MutableEnvironment(),
clock: extraClock,
execute: async () =>
({
ok: true,
value: {
kind: "VALUE",
value: "unsafe",
responseBytes: 1,
state: "COMPLETED",
},
extra: true,
}) as BoundedPollAttemptResult<string>,
});
const extraRun = extraCoordinator.run();
extraClock.advance(5_000);
await expect(extraRun).resolves.toMatchObject({
ok: false,
error: { kind: "PROTOCOL_MISMATCH" },
});
});
it("fails closed on response ceilings, concurrent runs and close", async () => {
const clock = new ManualClock();
const coordinator = createBoundedPollCoordinator<string>({
policy,
operation: {
...operation,
maxResponseBytes: 512,
},
environment: new MutableEnvironment(),
clock,
execute: async () => ({
ok: true,
value: {
kind: "VALUE",
value: "oversized",
responseBytes: 513,
state: "RUNNING",
},
}),
});
const first = coordinator.run();
await expect(coordinator.run()).resolves.toEqual({
ok: false,
error: {
kind: "PROTOCOL_MISMATCH",
operation: "POLL",
retryable: false,
},
});
clock.advance(5_000);
await expect(first).resolves.toEqual({
ok: false,
error: {
kind: "PROTOCOL_MISMATCH",
operation: "POLL",
retryable: false,
},
});
const pending = coordinator.run();
coordinator.close();
coordinator.close();
await expect(pending).resolves.toEqual({
ok: false,
error: {
kind: "CLOSED",
operation: "POLL",
retryable: false,
},
});
expect(coordinator.getState()).toBe("CLOSED");
});
});
@@ -0,0 +1,105 @@
import { describe, expect, it } from "vitest";
import {
BOUNDED_POLLING_CEILINGS,
assertBoundedPollOperation,
definePollLeasePolicy,
type BoundedPollOperationContract,
} from "../../../src/application/policies/bounded-polling.ts";
const input = {
operationId: "GET_JOB_STATUS",
owner: "reference-job",
minimumIntervalMs: 5_000,
successIntervalMs: 10_000,
maxIntervalMs: 60_000,
maxAttempts: 5,
maxElapsedMs: 120_000,
maxResponseBytes: 16_384,
visibility: "VISIBLE_ONLY",
fallbackReason: "CONVERGENCE",
terminalStates: ["COMPLETED", "FAILED"],
} as const;
describe("bounded polling policy", () => {
it("copies and freezes a finite immutable lease", () => {
const terminalStates = ["COMPLETED", "FAILED"];
const policy = definePollLeasePolicy({
...input,
terminalStates,
});
terminalStates.push("CANCELLED");
expect(policy.terminalStates).toEqual(["COMPLETED", "FAILED"]);
expect(Object.isFrozen(policy)).toBe(true);
expect(Object.isFrozen(policy.terminalStates)).toBe(true);
});
it("rejects push-like cadence and unbounded convergence", () => {
expect(() =>
definePollLeasePolicy({
...input,
minimumIntervalMs: 4_999,
}),
).toThrow(TypeError);
expect(() =>
definePollLeasePolicy({
...input,
terminalStates: [],
}),
).toThrow(TypeError);
expect(() =>
definePollLeasePolicy({
...input,
maxAttempts: 121,
}),
).toThrow(TypeError);
});
it("admits only a one-request terminal replay-safe REST query", () => {
const policy = definePollLeasePolicy(input);
const operation: BoundedPollOperationContract = {
operationId: "GET_JOB_STATUS",
contractVersion: 2,
protocol: "REST",
semantics: "QUERY",
method: "GET",
replayPolicy: "SAFE",
retry: "never",
maxResponseBytes: 16_384,
transportMaxAttempts: 1,
authRecoveryCount: 0,
maxCumulativeSleepMs: 0,
serverStream: false,
};
expect(() =>
assertBoundedPollOperation(policy, operation),
).not.toThrow();
expect(() =>
assertBoundedPollOperation(policy, {
...operation,
transportMaxAttempts: 2 as 1,
}),
).toThrow(TypeError);
expect(() =>
assertBoundedPollOperation(policy, {
...operation,
maxResponseBytes: 8_192,
}),
).not.toThrow();
expect(() =>
assertBoundedPollOperation(policy, {
...operation,
maxResponseBytes: 0,
}),
).toThrow(TypeError);
expect(() =>
assertBoundedPollOperation(policy, {
...operation,
maxResponseBytes:
BOUNDED_POLLING_CEILINGS.maxResponseBytes + 1,
}),
).toThrow(TypeError);
});
});
+243
View File
@@ -0,0 +1,243 @@
import { describe, expect, it } from "vitest";
import {
compareRealtimeSequences,
isCanonicalRealtimeSequence,
isRealtimeResumeCursor,
isStrictRealtimeTimestamp,
nextRealtimeSequence,
REALTIME_MAX_SEQUENCE,
} from "../../../src/contracts/realtime-events.ts";
import {
isValidatedRealtimeEventDto,
} from "../../../src/adapters/realtime/event-codec.ts";
import {
TEST_LIMITS,
createTestRealtimeCodec,
createTestRealtimeRegistry,
realtimeEventJson,
realtimeEventValue,
} from "./fixture.ts";
describe("REALTIME_EVENT_V1 codec", () => {
it("accepts an exact registered envelope and snapshots schema output", () => {
const codec = createTestRealtimeCodec();
const result = codec.decode(realtimeEventJson());
expect(result).toMatchObject({
ok: true,
value: {
envelope: {
protocol: "REALTIME_EVENT_V1",
sequence: "1",
recoveryMode: "CURSOR",
resumeCursor: "cursor-00000001",
payload: { value: "changed" },
},
},
});
if (!result.ok) return;
expect(isValidatedRealtimeEventDto(result.value)).toBe(true);
expect(Object.isFrozen(result.value)).toBe(true);
expect(Object.isFrozen(result.value.envelope)).toBe(true);
expect(Object.isFrozen(result.value.envelope.payload)).toBe(true);
expect(result.value.wireBytes).toBeGreaterThan(0);
expect(result.value.fingerprintBytes).toBeGreaterThan(0);
});
it("rejects extra keys, unknown registrations and schema failures", () => {
const codec = createTestRealtimeCodec();
expect(
codec.decode(
JSON.stringify({
...realtimeEventValue(),
arbitrary: "override",
}),
),
).toMatchObject({
ok: false,
error: { kind: "MALFORMED_EVENT", operation: "DECODE" },
});
expect(
codec.decode(
realtimeEventJson({ streamId: "UNKNOWN_STREAM" }),
),
).toMatchObject({
ok: false,
error: { kind: "MALFORMED_EVENT" },
});
expect(
codec.decode(
realtimeEventJson({ eventType: "UNKNOWN_EVENT" }),
),
).toMatchObject({
ok: false,
error: { kind: "MALFORMED_EVENT" },
});
expect(
codec.decode(realtimeEventJson({ payload: { value: 42 } })),
).toMatchObject({
ok: false,
error: { kind: "MALFORMED_EVENT" },
});
const duplicateEnvelopeMember =
`{"eventId":"shadowed",${JSON.stringify(
realtimeEventValue(),
).slice(1)}`;
expect(codec.decode(duplicateEnvelopeMember)).toMatchObject({
ok: false,
error: { kind: "MALFORMED_EVENT", operation: "DECODE" },
});
const duplicatePayloadMember = realtimeEventJson().replace(
'"payload":{"value":"changed"}',
'"payload":{"value":"first","\\u0076alue":"changed"}',
);
expect(codec.decode(duplicatePayloadMember)).toMatchObject({
ok: false,
error: { kind: "MALFORMED_EVENT", operation: "DECODE" },
});
});
it("fails closed on version, sequence, timestamp, scope and cursor syntax", () => {
const codec = createTestRealtimeCodec();
expect(
codec.decode(realtimeEventJson({ protocol: "REALTIME_EVENT_V2" })),
).toMatchObject({
ok: false,
error: { kind: "PROTOCOL_MISMATCH" },
});
for (const overrides of [
{ sequence: "01" },
{ sequence: "18446744073709551616" },
{ occurredAt: "2026-02-30T01:02:03Z" },
{ occurredAt: "2026-07-28 01:02:03Z" },
{ scopeBinding: "scope\r\ninjected" },
{ resumeCursor: "" },
{ resumeCursor: "cursor\ninjected" },
{ recoveryMode: "SNAPSHOT_ONLY", resumeCursor: null },
]) {
expect(codec.decode(realtimeEventJson(overrides))).toMatchObject({
ok: false,
error: { kind: "MALFORMED_EVENT" },
});
}
});
it("enforces global, per-stream and payload structure ceilings", () => {
const strictCodec = createTestRealtimeCodec(
createTestRealtimeRegistry({
limits: {
...TEST_LIMITS,
maxEventBytes: 512,
maxPayloadNodes: 1,
},
}),
);
expect(
strictCodec.decode(realtimeEventJson()),
).toMatchObject({
ok: false,
error: { kind: "MALFORMED_EVENT" },
});
const byteBoundCodec = createTestRealtimeCodec(
createTestRealtimeRegistry({
limits: {
...TEST_LIMITS,
maxEventBytes: 512,
},
}),
);
expect(
byteBoundCodec.decode(
realtimeEventJson({ payload: { value: "x".repeat(600) } }),
),
).toMatchObject({
ok: false,
error: { kind: "EVENT_TOO_LARGE" },
});
expect(
createTestRealtimeCodec().decode(
"x".repeat(64 * 1024 + 1),
),
).toMatchObject({
ok: false,
error: { kind: "EVENT_TOO_LARGE" },
});
});
it("supports the exact null-cursor SESSION_REBUILD discriminant", () => {
const registry = createTestRealtimeRegistry({
recovery: {
mode: "SESSION_REBUILD",
rebuildInputId: "referenceRealtimeRebuild",
},
delivery: "EPHEMERAL",
stateBearing: false,
});
const codec = createTestRealtimeCodec(registry);
expect(
codec.decode(
realtimeEventJson({
recoveryMode: "SESSION_REBUILD",
resumeCursor: null,
}),
),
).toMatchObject({
ok: true,
value: {
envelope: {
recoveryMode: "SESSION_REBUILD",
resumeCursor: null,
},
},
});
expect(
codec.decode(
realtimeEventJson({
recoveryMode: "SESSION_REBUILD",
resumeCursor: "synthetic",
}),
),
).toMatchObject({
ok: false,
error: { kind: "MALFORMED_EVENT" },
});
});
it("normalizes semantic identity independently of JSON key order", () => {
const codec = createTestRealtimeCodec();
const value = realtimeEventValue();
const reversed = Object.fromEntries(
Object.entries(value).reverse(),
);
const first = codec.decode(JSON.stringify(value));
const second = codec.decode(JSON.stringify(reversed));
expect(first.ok).toBe(true);
expect(second.ok).toBe(true);
if (!first.ok || !second.ok) return;
expect(first.value.semanticFingerprint).toBe(
second.value.semanticFingerprint,
);
});
it("uses bounded uint64 sequence and header-safe cursor helpers", () => {
expect(isCanonicalRealtimeSequence("0")).toBe(true);
expect(isCanonicalRealtimeSequence(REALTIME_MAX_SEQUENCE)).toBe(true);
expect(isCanonicalRealtimeSequence("00")).toBe(false);
expect(isCanonicalRealtimeSequence("18446744073709551616")).toBe(false);
expect(compareRealtimeSequences("9", "10")).toBe(-1);
expect(nextRealtimeSequence("9")).toBe("10");
expect(nextRealtimeSequence(REALTIME_MAX_SEQUENCE)).toBeNull();
expect(isRealtimeResumeCursor("cursor:/+=._~-")).toBe(true);
expect(isRealtimeResumeCursor("cursor\nunsafe")).toBe(false);
expect(isStrictRealtimeTimestamp("2024-02-29T23:59:59Z")).toBe(true);
expect(isStrictRealtimeTimestamp("2023-02-29T23:59:59Z")).toBe(false);
});
});
+211
View File
@@ -0,0 +1,211 @@
import { describe, expect, it, vi } from "vitest";
import type {
RealtimeAcceptDisposition,
RealtimeRecoveryCheckpoint,
} from "../../../src/application/ports/realtime/event-authority.ts";
import type {
RealtimeResult,
} from "../../../src/application/ports/realtime/shared.ts";
import {
createRealtimeEventConsumer,
} from "../../../src/adapters/realtime/event-consumer.ts";
import type {
RealtimeEventCodec,
ValidatedRealtimeEventDto,
} from "../../../src/adapters/realtime/event-codec.ts";
import {
realtimeFailure,
realtimeSuccess,
} from "../../../src/adapters/realtime/result.ts";
import type {
RealtimeStreamCoordinator,
} from "../../../src/adapters/realtime/stream-coordinator.ts";
function setup(
recoveryMode:
| "CURSOR"
| "SNAPSHOT_ONLY"
| "SESSION_REBUILD",
resumeCursor: string | null,
) {
const dto = {
envelope: {
recoveryMode,
resumeCursor,
streamId: "REFERENCE_STREAM",
},
} as ValidatedRealtimeEventDto;
const codec: RealtimeEventCodec = {
decode: vi.fn(() => realtimeSuccess(dto)),
};
const accept = vi.fn<
(
event: ValidatedRealtimeEventDto,
signal?: AbortSignal,
) => Promise<RealtimeResult<RealtimeAcceptDisposition>>
>(() =>
Promise.resolve(
realtimeSuccess({
outcome: "DROPPED" as const,
reason: "DUPLICATE_EVENT" as const,
}),
),
);
const consumer = createRealtimeEventConsumer({
codec,
coordinator: {
accept,
} as Pick<RealtimeStreamCoordinator, "accept">,
});
return { consumer, accept, codec };
}
describe("realtime transport event consumer", () => {
it("requires exact equality between SSE id and CURSOR envelope", async () => {
const matching = setup("CURSOR", "cursor.0001");
await expect(
matching.consumer.consume("{}", {
kind: "SSE_DIRECT_CURSOR",
eventId: "cursor.0001",
}),
).resolves.toMatchObject({ ok: true });
expect(matching.accept).toHaveBeenCalledTimes(1);
const advanced = setup("CURSOR", "cursor.0002");
await expect(
advanced.consumer.consume("{}", {
kind: "SSE_DIRECT_CURSOR",
eventId: "cursor.0001",
}),
).resolves.toEqual(
realtimeFailure("PROTOCOL_MISMATCH", "RECEIVE"),
);
expect(advanced.accept).not.toHaveBeenCalled();
});
it("forbids SSE id semantics for non-CURSOR recovery", async () => {
const runtime = setup("SNAPSHOT_ONLY", null);
await expect(
runtime.consumer.consume("{}", {
kind: "SSE_NO_CURSOR",
}),
).resolves.toMatchObject({ ok: true });
await expect(
runtime.consumer.consume("{}", {
kind: "SSE_DIRECT_CURSOR",
eventId: "cursor.0001",
}),
).resolves.toEqual(
realtimeFailure("PROTOCOL_MISMATCH", "RECEIVE"),
);
});
it("serializes an encapsulated WebSocket envelope through the codec", async () => {
const runtime = setup("SESSION_REBUILD", null);
await expect(
runtime.consumer.consumeEncapsulated(
Object.freeze({ protocol: "REALTIME_EVENT_V1" }),
),
).resolves.toMatchObject({ ok: true });
expect(runtime.codec.decode).toHaveBeenCalledWith(
'{"protocol":"REALTIME_EVENT_V1"}',
);
});
it("projects common dispositions into the canonical transport outcome", async () => {
const runtime = setup("SNAPSHOT_ONLY", null);
await expect(
runtime.consumer.consumeForTransport("{}", {
kind: "SSE_NO_CURSOR",
}),
).resolves.toEqual({
ok: true,
value: { kind: "CONTINUE" },
});
const checkpoint = Object.freeze({
recoveryMode: "SNAPSHOT_ONLY" as const,
streamEpoch: "stream-epoch.0001",
lastAppliedSequence: "0",
resumeCursor: null,
}) as RealtimeRecoveryCheckpoint;
runtime.accept.mockResolvedValueOnce(
realtimeSuccess({
outcome: "RECOVERED",
reason: "INITIALIZE",
resumeState: checkpoint,
}),
);
await expect(
runtime.consumer.consumeForTransport("{}", {
kind: "SSE_NO_CURSOR",
}),
).resolves.toEqual({
ok: true,
value: {
kind: "RECOVERY_COMMITTED",
streamId: "REFERENCE_STREAM",
checkpoint,
},
});
runtime.accept.mockResolvedValueOnce(
realtimeSuccess({
outcome: "DROPPED",
reason: "RECOVERY_IN_PROGRESS",
}),
);
await expect(
runtime.consumer.consumeForTransport("{}", {
kind: "SSE_NO_CURSOR",
}),
).resolves.toEqual(
realtimeFailure("PROTOCOL_MISMATCH", "RECEIVE"),
);
runtime.accept.mockResolvedValueOnce(
realtimeSuccess({
outcome: "DROPPED",
reason: "SCOPE_FENCED",
}),
);
await expect(
runtime.consumer.consumeForTransport("{}", {
kind: "SSE_NO_CURSOR",
}),
).resolves.toEqual(
realtimeFailure("SCOPE_FENCED", "RECEIVE"),
);
});
it("threads transport cancellation into the common authority", async () => {
const runtime = setup("SNAPSHOT_ONLY", null);
const active = new AbortController();
await runtime.consumer.consume(
"{}",
{ kind: "SSE_NO_CURSOR" },
active.signal,
);
expect(runtime.accept).toHaveBeenLastCalledWith(
expect.anything(),
active.signal,
);
const aborted = new AbortController();
aborted.abort();
await expect(
runtime.consumer.consume(
"{}",
{ kind: "SSE_NO_CURSOR" },
aborted.signal,
),
).resolves.toEqual(
realtimeFailure("ABORTED", "RECEIVE"),
);
expect(runtime.accept).toHaveBeenCalledTimes(1);
});
});
@@ -0,0 +1,568 @@
import { describe, expect, it, vi } from "vitest";
import {
SSE_CONTINUE,
createFetchSseConnection,
} from "../../../src/adapters/realtime/sse/fetch-sse-connection.ts";
import {
realtimeTransportRecoveryCommitted,
type RealtimeRecoveryCheckpoint,
} from "../../../src/application/ports/realtime/event-authority.ts";
import type { RealtimeResult } from "../../../src/application/ports/realtime/shared.ts";
import type {
StreamRegistrationId,
} from "../../../src/contracts/realtime-streams.ts";
import {
realtimeFailure,
realtimeSuccess,
} from "../../../src/adapters/realtime/result.ts";
const encoder = new TextEncoder();
const continueEvent = () => realtimeSuccess(SSE_CONTINUE);
const RECOVERY_CHECKPOINT = Object.freeze({
recoveryMode: "CURSOR" as const,
streamEpoch: "stream-epoch.0001",
lastAppliedSequence: "1",
resumeCursor: "cursor-1",
}) as RealtimeRecoveryCheckpoint;
const RECOVERY_OUTCOME = realtimeTransportRecoveryCommitted(
"REFERENCE_STREAM" as StreamRegistrationId,
RECOVERY_CHECKPOINT,
);
function eventStream(
chunks: readonly string[],
options: Readonly<{
status?: number;
contentType?: string;
}> = {},
): Response {
return new Response(
new ReadableStream<Uint8Array>({
start(controller) {
for (const chunk of chunks) {
controller.enqueue(encoder.encode(chunk));
}
controller.close();
},
}),
{
status: options.status ?? 200,
headers: {
"Content-Type":
options.contentType ?? "text/event-stream; charset=utf-8",
},
},
);
}
function connection(
fetcher: typeof fetch,
recoveryMode: "CURSOR" | "SESSION_REBUILD" | "SNAPSHOT_ONLY" =
"CURSOR",
) {
return createFetchSseConnection({
endpoint: "https://app.example.test/events",
applicationOrigin: "https://app.example.test",
recoveryMode,
fetcher,
});
}
describe("fetch SSE connection", () => {
it("uses the fixed request profile and streams events sequentially", async () => {
const response = eventStream([
": heartbeat\r\n",
"retry: 2500\n",
"id: cursor-1\ndata: first\n",
"data: second\n\n",
]);
const fetcher = vi.fn(
async (_input: RequestInfo | URL, _init?: RequestInit) =>
response,
);
const received: string[] = [];
const comments = vi.fn();
const hints = vi.fn();
const runtime = connection(fetcher as typeof fetch);
await expect(
runtime.read({
resumeCursor: "cursor-0",
onEvent: async (event) => {
received.push(event.data);
return realtimeSuccess(SSE_CONTINUE);
},
onComment: comments,
onRetryHint: hints,
}),
).resolves.toEqual({
ok: true,
value: {
kind: "EOF",
incompleteEventDiscarded: false,
retryHintMs: 2_500,
},
});
expect(received).toEqual(["first\nsecond"]);
expect(comments).toHaveBeenCalledOnce();
expect(hints).toHaveBeenCalledWith(2_500);
const [target, init] = fetcher.mock.calls[0] ?? [];
expect(target).toBe("https://app.example.test/events");
expect(init).toMatchObject({
method: "GET",
credentials: "same-origin",
redirect: "error",
cache: "no-store",
referrerPolicy: "no-referrer",
});
expect(new Headers(init?.headers)).toEqual(
new Headers({
Accept: "text/event-stream",
"Last-Event-ID": "cursor-0",
}),
);
});
it("holds event consumption behind the validated open barrier gate", async () => {
const runtime = connection(
(async () =>
eventStream([
"id: cursor-1\ndata: after-barrier\n\n",
])) as typeof fetch,
);
let release:
| ((result: RealtimeResult<void>) => void)
| undefined;
const gate = new Promise<RealtimeResult<void>>((resolve) => {
release = resolve;
});
const onOpen = vi.fn(() => gate);
const onEvent = vi.fn(continueEvent);
const reading = runtime.read({
resumeCursor: null,
onOpen,
onEvent,
});
await vi.waitFor(() => expect(onOpen).toHaveBeenCalledOnce());
expect(onEvent).not.toHaveBeenCalled();
release?.(realtimeSuccess(undefined));
await expect(reading).resolves.toMatchObject({
ok: true,
value: { kind: "EOF" },
});
expect(onEvent).toHaveBeenCalledOnce();
});
it("propagates an exact open-barrier failure before reading events", async () => {
const runtime = connection(
(async () =>
eventStream([
"id: cursor-1\ndata: unreachable\n\n",
])) as typeof fetch,
);
const barrierFailure = realtimeFailure(
"SCOPE_FENCED",
"RECOVER",
false,
);
const onEvent = vi.fn(continueEvent);
await expect(
runtime.read({
resumeCursor: null,
onOpen: () => barrierFailure,
onEvent,
}),
).resolves.toBe(barrierFailure);
expect(onEvent).not.toHaveBeenCalled();
});
it("treats 204 as terminal and rejects incorrect media types", async () => {
const terminal = connection(
(async () => new Response(null, { status: 204 })) as typeof fetch,
);
await expect(
terminal.read({
resumeCursor: null,
onEvent: continueEvent,
}),
).resolves.toEqual({
ok: true,
value: { kind: "NO_RECONNECT" },
});
const wrongType = connection(
(async () =>
eventStream(["data: value\n\n"], {
contentType: "application/json",
})) as typeof fetch,
);
await expect(
wrongType.read({
resumeCursor: null,
onEvent: continueEvent,
}),
).resolves.toEqual({
ok: false,
error: {
kind: "PROTOCOL_MISMATCH",
operation: "CONNECT",
retryable: false,
},
});
});
it.each([
[401, "AUTH_REQUIRED", false],
[403, "FORBIDDEN", false],
[409, "CURSOR_EXPIRED", false],
[410, "CURSOR_EXPIRED", false],
[429, "RATE_LIMITED", true],
[502, "PROVIDER_UNAVAILABLE", true],
[503, "PROVIDER_UNAVAILABLE", true],
[504, "PROVIDER_UNAVAILABLE", true],
[500, "PROTOCOL_MISMATCH", false],
] as const)(
"maps HTTP %i to %s without exposing a response body",
async (status, kind, retryable) => {
const runtime = connection(
(async () =>
new Response("private backend text", {
status,
headers:
status === 429 || status === 503
? { "Retry-After": "10" }
: undefined,
})) as typeof fetch,
);
const result = await runtime.read({
resumeCursor: null,
onEvent: continueEvent,
});
expect(result).toEqual({
ok: false,
error: {
kind,
operation: "CONNECT",
retryable,
},
});
expect(JSON.stringify(result)).not.toContain("private backend");
},
);
it.each([
[429, "RATE_LIMITED"],
[503, "PROVIDER_UNAVAILABLE"],
] as const)(
"does not retry HTTP %i without a bounded server hint",
async (status, kind) => {
const runtime = connection(
(async () => new Response(null, { status })) as typeof fetch,
);
await expect(
runtime.read({
resumeCursor: null,
onEvent: continueEvent,
}),
).resolves.toEqual({
ok: false,
error: {
kind,
operation: "CONNECT",
retryable: false,
},
});
},
);
it("does not clamp an excessive Retry-After into an early retry", async () => {
const runtime = connection(
(async () =>
new Response(null, {
status: 429,
headers: { "Retry-After": "120" },
})) as typeof fetch,
);
await expect(
runtime.read({
resumeCursor: null,
onEvent: continueEvent,
}),
).resolves.toEqual({
ok: false,
error: {
kind: "RATE_LIMITED",
operation: "CONNECT",
retryable: false,
},
});
});
it("enforces direct event IDs only for CURSOR recovery", async () => {
const missingCursorId = connection(
(async () =>
eventStream(["data: value\n\n"])) as typeof fetch,
);
await expect(
missingCursorId.read({
resumeCursor: null,
onEvent: continueEvent,
}),
).resolves.toEqual({
ok: false,
error: {
kind: "PROTOCOL_MISMATCH",
operation: "DECODE",
retryable: false,
},
});
const unexpectedCursorId = connection(
(async () =>
eventStream([
"id: cursor-1\ndata: value\n\n",
])) as typeof fetch,
"SNAPSHOT_ONLY",
);
await expect(
unexpectedCursorId.read({
resumeCursor: null,
onEvent: continueEvent,
}),
).resolves.toEqual({
ok: false,
error: {
kind: "PROTOCOL_MISMATCH",
operation: "DECODE",
retryable: false,
},
});
});
it("stops the old stream after authority recovery commits", async () => {
const runtime = connection(
(async () =>
eventStream([
"id: cursor-1\ndata: first\n\n",
"id: cursor-2\ndata: stale-generation\n\n",
])) as typeof fetch,
);
const onEvent = vi.fn(() =>
realtimeSuccess(RECOVERY_OUTCOME),
);
await expect(
runtime.read({
resumeCursor: null,
onEvent,
}),
).resolves.toEqual({
ok: true,
value: RECOVERY_OUTCOME,
});
expect(onEvent).toHaveBeenCalledOnce();
});
it("propagates a canonical consumer failure and aborts its event generation", async () => {
const runtime = connection(
(async () =>
eventStream([
"id: cursor-1\ndata: forbidden\n\n",
])) as typeof fetch,
);
let handlerSignal: AbortSignal | undefined;
await expect(
runtime.read({
resumeCursor: null,
onEvent: (_event, signal) => {
handlerSignal = signal;
return realtimeFailure("FORBIDDEN", "RECEIVE");
},
}),
).resolves.toEqual(
realtimeFailure("FORBIDDEN", "RECEIVE"),
);
expect(handlerSignal?.aborted).toBe(true);
});
it("fences recovery immediately and waits for bounded reader cancellation", async () => {
let releaseCancellation: (() => void) | undefined;
let cancellationStarted = false;
const stream = new ReadableStream<Uint8Array>({
start(controller) {
controller.enqueue(
encoder.encode("id: cursor-1\ndata: first\n\n"),
);
},
cancel() {
cancellationStarted = true;
return new Promise<void>((resolve) => {
releaseCancellation = resolve;
});
},
});
const runtime = connection(
(async () =>
new Response(stream, {
headers: { "Content-Type": "text/event-stream" },
})) as typeof fetch,
);
const pending = runtime.read({
resumeCursor: null,
onEvent: () =>
realtimeSuccess(RECOVERY_OUTCOME),
});
let settled = false;
void pending.then(() => {
settled = true;
});
for (let turn = 0; turn < 20; turn += 1) {
await Promise.resolve();
}
expect(cancellationStarted).toBe(true);
expect(settled).toBe(false);
releaseCancellation?.();
await expect(pending).resolves.toEqual({
ok: true,
value: RECOVERY_OUTCOME,
});
});
it("discards incomplete EOF and closes an active reader idempotently", async () => {
const incomplete = connection(
(async () =>
eventStream([
"id: cursor-1\ndata: incomplete\n",
])) as typeof fetch,
);
await expect(
incomplete.read({
resumeCursor: null,
onEvent() {
throw new Error("must not run");
},
}),
).resolves.toEqual({
ok: true,
value: {
kind: "EOF",
incompleteEventDiscarded: true,
retryHintMs: null,
},
});
const pendingStream = new ReadableStream<Uint8Array>({
pull: () => new Promise<void>(() => {}),
});
const active = connection(
(async () =>
new Response(pendingStream, {
headers: { "Content-Type": "text/event-stream" },
})) as typeof fetch,
);
const pending = active.read({
resumeCursor: null,
onEvent: continueEvent,
});
await Promise.resolve();
await Promise.resolve();
active.close();
active.close();
await expect(pending).resolves.toMatchObject({
ok: false,
error: {
kind: "ABORTED",
operation: "CONNECT",
retryable: false,
},
});
await expect(
active.read({
resumeCursor: null,
onEvent: continueEvent,
}),
).resolves.toEqual({
ok: false,
error: {
kind: "CLOSED",
operation: "CONNECT",
retryable: false,
},
});
});
it("dispatches a CR-terminated blank block completed at EOF", async () => {
const runtime = connection(
(async () =>
eventStream([
"id: cursor-1\rdata: final\r\r",
])) as typeof fetch,
);
const received = vi.fn(() =>
realtimeSuccess(SSE_CONTINUE),
);
await expect(
runtime.read({
resumeCursor: null,
onEvent: received,
}),
).resolves.toMatchObject({
ok: true,
value: {
kind: "EOF",
incompleteEventDiscarded: false,
},
});
expect(received).toHaveBeenCalledWith(
expect.objectContaining({ data: "final" }),
expect.any(AbortSignal),
);
});
it("rejects arbitrary endpoints and mode-incoherent cursors before fetch", async () => {
expect(() =>
createFetchSseConnection({
endpoint: "https://other.example.test/events",
applicationOrigin: "https://app.example.test",
recoveryMode: "CURSOR",
}),
).toThrow(TypeError);
expect(() =>
createFetchSseConnection({
endpoint:
"https://app.example.test/events?token=not-allowed",
applicationOrigin: "https://app.example.test",
recoveryMode: "CURSOR",
}),
).toThrow(TypeError);
const fetcher = vi.fn(
async () => eventStream(["data: unreachable\n\n"]),
);
const snapshotOnly = connection(
fetcher as unknown as typeof fetch,
"SNAPSHOT_ONLY",
);
await expect(
snapshotOnly.read({
resumeCursor: "cursor-not-allowed",
onEvent: continueEvent,
}),
).resolves.toEqual({
ok: false,
error: {
kind: "PROTOCOL_MISMATCH",
operation: "CONNECT",
retryable: false,
},
});
expect(fetcher).not.toHaveBeenCalled();
});
});
+252
View File
@@ -0,0 +1,252 @@
import {
mappingSuccess,
type InstalledBoundaryMapper,
} from "../../../src/contracts/boundary-mapper.ts";
import type { ApiOperation } from "../../../src/contracts/api-operations.ts";
import {
createRealtimePolicyRegistry,
defineEventTypeId,
defineExternalEventEffectProfileId,
defineRealtimeEndpointId,
defineRealtimeKillSwitchId,
defineStreamRegistrationId,
type RealtimeEventTypeRegistration,
type RealtimeLimits,
type RealtimePolicyRegistry,
type RealtimeRecoveryProfile,
type RealtimeStreamRegistration,
} from "../../../src/contracts/realtime-streams.ts";
import type { RuntimeSchemaCodec } from "../../../src/contracts/schema-registry.ts";
import {
createRealtimeEventCodec,
type RealtimeEventCodec,
} from "../../../src/adapters/realtime/event-codec.ts";
export const STREAM_ID = defineStreamRegistrationId("REFERENCE_STREAM");
export const EVENT_TYPE = defineEventTypeId("REFERENCE_CHANGED");
export const ENDPOINT_ID = defineRealtimeEndpointId("REFERENCE_ENDPOINT");
export const EFFECT_PROFILE_ID =
defineExternalEventEffectProfileId("REFERENCE_INVALIDATE");
export const KILL_SWITCH_ID =
defineRealtimeKillSwitchId("REFERENCE_KILL_SWITCH");
export const TEST_LIMITS: RealtimeLimits = Object.freeze({
maxEventBytes: 4_096,
maxPayloadDepth: 8,
maxPayloadNodes: 128,
maxQueueEvents: 8,
maxQueueBytes: 32_768,
maxDedupeEntries: 16,
maxDedupeBytes: 32_768,
dedupeTtlMs: 60_000,
});
const eventPayloadCodec: RuntimeSchemaCodec = Object.freeze({
schemaId: "ReferenceRealtimePayload",
parse(value) {
if (
!value ||
typeof value !== "object" ||
Array.isArray(value) ||
Object.keys(value).length !== 1 ||
typeof (value as Readonly<Record<string, unknown>>).value !== "string"
) {
return {
success: false,
issues: [{ path: "value", code: "INVALID_TYPE" }],
};
}
return {
success: true,
data: {
value: (value as Readonly<Record<string, string>>).value,
},
};
},
});
const checkpointCodec: RuntimeSchemaCodec = Object.freeze({
schemaId: "ReferenceRealtimeCheckpoint",
parse: (value) => ({ success: true, data: value }),
});
export const TEST_SCHEMA_CODECS = Object.freeze({
ReferenceRealtimePayload: eventPayloadCodec,
ReferenceRealtimeCheckpoint: checkpointCodec,
});
export const TEST_MAPPER: InstalledBoundaryMapper = Object.freeze({
mapperId: "ReferenceRealtimeMapper",
mapperVersion: 1,
inputSchemaId: "ReferenceRealtimePayload",
outputContractId: "ReferenceRealtimeEvent",
owner: "sample-owner",
maxOutputItems: 1,
map(input) {
if (
!input ||
typeof input !== "object" ||
typeof (input as Readonly<Record<string, unknown>>).value !== "string"
) {
return { ok: false, code: "MAPPING_INVARIANT_REJECTED" };
}
return mappingSuccess(
Object.freeze({
value: (input as Readonly<Record<string, string>>).value,
}),
);
},
});
export const TEST_MAPPERS = Object.freeze({
ReferenceRealtimeMapper: TEST_MAPPER,
});
const snapshotOperation: ApiOperation = Object.freeze({
method: "GET",
path: "/api/reference-snapshot",
operationId: "GET_REFERENCE_REALTIME_SNAPSHOT",
auth: "external-session",
timeoutMs: 10_000,
idempotency: "safe",
retry: "never",
requestSource: "none",
requestSchema: "NoRequest",
responseSchema: "ReferenceRealtimeCheckpoint",
owner: "sample-owner",
contractVersion: 2,
protocol: "REST",
semantics: "QUERY",
replayPolicy: "SAFE",
idempotencyKeyPolicy: "NONE",
mapperId: "ReferenceRealtimeSnapshotMapper",
successStatuses: [200],
responseMediaTypes: ["application/json"],
maxResponseBytes: 16_384,
providerId: "PRIMARY_API",
authProfileId: "EXTERNAL_SESSION",
csrfProfileId: "NONE",
pathSchema: "NoRequest",
pathParameterNames: [],
maxEncodedSearchBytes: 0,
});
export const TEST_API_OPERATIONS = Object.freeze({
GET_REFERENCE_REALTIME_SNAPSHOT: snapshotOperation,
});
export type TestRegistryOptions = Readonly<{
recovery?: RealtimeRecoveryProfile;
delivery?: RealtimeStreamRegistration["delivery"];
stateBearing?: boolean;
limits?: RealtimeLimits;
streamMutator?: (
stream: RealtimeStreamRegistration,
) => RealtimeStreamRegistration;
eventTypeMutator?: (
eventType: RealtimeEventTypeRegistration,
) => RealtimeEventTypeRegistration;
}>;
export function createTestRealtimeRegistry(
options: TestRegistryOptions = {},
): RealtimePolicyRegistry {
const recovery =
options.recovery ??
({
mode: "CURSOR",
snapshotOperationId: "GET_REFERENCE_REALTIME_SNAPSHOT",
checkpointCodecId: "ReferenceRealtimeCheckpoint",
barrier: "REPLAY",
} as const);
const eventType: RealtimeEventTypeRegistration = {
id: EVENT_TYPE,
owner: "sample-owner",
payloadSchemaId: "ReferenceRealtimePayload",
mapperId: "ReferenceRealtimeMapper",
effectProfileId: EFFECT_PROFILE_ID,
stateBearing: options.stateBearing ?? true,
};
const stream: RealtimeStreamRegistration = {
id: STREAM_ID,
protocol: "REALTIME_EVENT_V1",
owner: "sample-owner",
scope: "ACCOUNT_BOUND",
primaryTransport: "SSE",
endpointId: ENDPOINT_ID,
eventTypeIds: [EVENT_TYPE],
delivery: options.delivery ?? "AUTHORITATIVE_DELTA",
recovery,
fallback:
recovery.mode === "SESSION_REBUILD"
? "EXPLICITLY_STALE"
: "BOUNDED_POLLING",
hiddenPolicy: "CLOSE",
limits: options.limits ?? TEST_LIMITS,
killSwitchId: KILL_SWITCH_ID,
};
return createRealtimePolicyRegistry({
streams: [options.streamMutator?.(stream) ?? stream],
eventTypes: [
options.eventTypeMutator?.(eventType) ?? eventType,
],
bindings: {
schemaCodecs: TEST_SCHEMA_CODECS,
mappers: TEST_MAPPERS,
apiOperations: TEST_API_OPERATIONS,
endpointIds: [ENDPOINT_ID],
effectProfileIds: [EFFECT_PROFILE_ID],
killSwitchIds: [KILL_SWITCH_ID],
rebuildInputIds: ["referenceRealtimeRebuild"],
},
});
}
export function createTestRealtimeCodec(
registry = createTestRealtimeRegistry(),
): RealtimeEventCodec {
return createRealtimeEventCodec({
registry,
schemaCodecs: TEST_SCHEMA_CODECS,
});
}
export type EventOverrides = Readonly<{
protocol?: unknown;
streamId?: unknown;
streamEpoch?: unknown;
eventType?: unknown;
eventId?: unknown;
sequence?: unknown;
recoveryMode?: unknown;
resumeCursor?: unknown;
occurredAt?: unknown;
scopeBinding?: unknown;
payload?: unknown;
}>;
export function realtimeEventValue(
overrides: EventOverrides = {},
): Readonly<Record<string, unknown>> {
return {
protocol: "REALTIME_EVENT_V1",
streamId: STREAM_ID,
streamEpoch: "stream-epoch-0001",
eventType: EVENT_TYPE,
eventId: "event-00000001",
sequence: "1",
recoveryMode: "CURSOR",
resumeCursor: "cursor-00000001",
occurredAt: "2026-07-28T01:02:03.123Z",
scopeBinding: "scope-binding-0001",
payload: { value: "changed" },
...overrides,
};
}
export function realtimeEventJson(
overrides: EventOverrides = {},
): string {
return JSON.stringify(realtimeEventValue(overrides));
}
@@ -0,0 +1,548 @@
import { describe, expect, it, vi } from "vitest";
import type { ClockPort } from "../../../src/application/ports/clock-port.ts";
import type { RealtimeResult } from "../../../src/application/ports/realtime/shared.ts";
import {
createLivePollHandoffCoordinator,
type LivePollHandoffCoordinatorDependencies,
type LivePollHandoffLimits,
type LiveProbeLease,
} from "../../../src/adapters/realtime/live-poll-handoff-coordinator.ts";
import {
realtimeFailure,
realtimeSuccess,
} from "../../../src/adapters/realtime/result.ts";
type Sleeper = Readonly<{
dueAt: number;
resolve(): void;
reject(): void;
signal?: AbortSignal;
onAbort(): void;
}>;
class ManualClock implements ClockPort {
current = 0;
readonly sleepers: Sleeper[] = [];
now(): number {
return this.current;
}
sleep(milliseconds: number, signal?: AbortSignal): Promise<void> {
return new Promise((resolve, reject) => {
if (signal?.aborted) {
reject(new DOMException("Aborted", "AbortError"));
return;
}
let sleeper: Sleeper;
const onAbort = () => {
this.remove(sleeper);
reject(new DOMException("Aborted", "AbortError"));
};
sleeper = {
dueAt: this.current + milliseconds,
resolve: () => {
signal?.removeEventListener("abort", onAbort);
resolve();
},
reject: () => {
signal?.removeEventListener("abort", onAbort);
reject(new DOMException("Aborted", "AbortError"));
},
signal,
onAbort,
};
signal?.addEventListener("abort", onAbort, { once: true });
this.sleepers.push(sleeper);
});
}
advance(milliseconds: number): void {
this.current += milliseconds;
const ready = this.sleepers.filter(
(sleeper) => sleeper.dueAt <= this.current,
);
for (const sleeper of ready) {
this.remove(sleeper);
sleeper.resolve();
}
}
private remove(target: Sleeper): void {
const index = this.sleepers.indexOf(target);
if (index >= 0) this.sleepers.splice(index, 1);
}
}
const limits: LivePollHandoffLimits = Object.freeze({
quiescenceTimeoutMs: 100,
maxActiveQueueCount: 3,
maxActiveQueueBytes: 30,
maxProbeBufferedEvents: 3,
maxProbeBufferedBytes: 30,
maxItemBytes: 10,
});
function createHarness(
input: Readonly<{
initial?: "LIVE" | "POLL";
limits?: LivePollHandoffLimits;
apply?: LivePollHandoffCoordinatorDependencies<string>["apply"];
recover?: LivePollHandoffCoordinatorDependencies<string>["establishAuthoritativeCheckpoint"];
}> = {},
) {
const clock = new ManualClock();
const effects: string[] = [];
const recoveries: string[] = [];
const apply =
input.apply ??
vi.fn(async ({ writer, value }) => {
effects.push(`${writer}:${value}`);
return realtimeSuccess(undefined);
});
const recover =
input.recover ??
vi.fn(async ({ from, to }) => {
recoveries.push(`${from}->${to}`);
return realtimeSuccess(undefined);
});
const coordinator = createLivePollHandoffCoordinator({
initial: {
writer: input.initial ?? "LIVE",
authoritativeCheckpointEstablished: true,
},
limits: input.limits ?? limits,
apply,
establishAuthoritativeCheckpoint: recover,
clock,
});
return { apply, clock, coordinator, effects, recover, recoveries };
}
async function flush(): Promise<void> {
for (let turn = 0; turn < 12; turn += 1) {
await Promise.resolve();
}
}
describe("live/poll authoritative writer handoff", () => {
it("serializes effects through the one current writer lease", async () => {
const first = deferred<RealtimeResult<void>>();
const starts: string[] = [];
let activeEffects = 0;
let highWatermark = 0;
const harness = createHarness({
apply: vi.fn(async ({ value }) => {
starts.push(value);
activeEffects += 1;
highWatermark = Math.max(highWatermark, activeEffects);
if (value === "first") await first.promise;
activeEffects -= 1;
return realtimeSuccess(undefined);
}),
});
const writer = harness.coordinator.currentWriter();
expect(writer?.writer).toBe("LIVE");
const firstWrite = writer!.write("first", 5);
const secondWrite = writer!.write("second", 6);
await flush();
expect(starts).toEqual(["first"]);
first.resolve(realtimeSuccess(undefined));
await expect(firstWrite).resolves.toMatchObject({
ok: true,
value: { kind: "APPLIED", writer: "LIVE" },
});
await expect(secondWrite).resolves.toMatchObject({
ok: true,
value: { kind: "APPLIED", writer: "LIVE" },
});
expect(starts).toEqual(["first", "second"]);
expect(highWatermark).toBe(1);
});
it("fails closed when a non-cooperative active writer fills the bounded tail", async () => {
let firstSignal: AbortSignal | undefined;
let firstIsCurrent: (() => boolean) | undefined;
const starts: string[] = [];
const harness = createHarness({
limits: {
...limits,
maxActiveQueueCount: 2,
maxActiveQueueBytes: 10,
},
apply: vi.fn(async ({ value, signal, isCurrent }) => {
starts.push(value);
if (value === "first") {
firstSignal = signal;
firstIsCurrent = isCurrent;
return await new Promise<RealtimeResult<void>>(() => {});
}
return realtimeSuccess(undefined);
}),
});
const writer = harness.coordinator.currentWriter()!;
const first = writer.write("first", 5);
const second = writer.write("second", 5);
await flush();
expect(starts).toEqual(["first"]);
expect(firstIsCurrent?.()).toBe(true);
await expect(writer.write("overflow", 1)).resolves.toMatchObject({
ok: false,
error: {
kind: "QUEUE_OVERFLOW",
operation: "APPLY",
retryable: false,
},
});
expect(firstSignal?.aborted).toBe(true);
expect(firstIsCurrent?.()).toBe(false);
expect(writer.isCurrent()).toBe(false);
expect(harness.coordinator.inspect()).toMatchObject({
state: "CLOSED",
activeWriter: null,
});
expect(starts).toEqual(["first"]);
await expect(writer.write("after-close", 1)).resolves.toMatchObject({
ok: false,
error: { kind: "CLOSED" },
});
void first;
void second;
});
it("fences and aborts live, waits for quiescence, then recovers before activating poll", async () => {
const liveEffect = deferred<RealtimeResult<void>>();
const checkpoint = deferred<RealtimeResult<void>>();
const order: string[] = [];
let liveSignal: AbortSignal | undefined;
let liveIsCurrent: (() => boolean) | undefined;
const harness = createHarness({
apply: vi.fn(async ({ writer, value, signal, isCurrent }) => {
order.push(`apply:${writer}:${value}`);
if (writer === "LIVE") {
liveSignal = signal;
liveIsCurrent = isCurrent;
return await liveEffect.promise;
}
return realtimeSuccess(undefined);
}),
recover: vi.fn(async ({ from, to }) => {
order.push(`recover:${from}->${to}`);
return await checkpoint.promise;
}),
});
const live = harness.coordinator.currentWriter()!;
const pendingEffect = live.write("in-flight", 9);
await flush();
const transition = harness.coordinator.switchToPoll();
expect(liveSignal?.aborted).toBe(true);
expect(liveIsCurrent?.()).toBe(false);
expect(live.isCurrent()).toBe(false);
await expect(live.write("stale", 999)).resolves.toMatchObject({
ok: false,
error: { kind: "SCOPE_FENCED" },
});
expect(harness.recover).not.toHaveBeenCalled();
await expect(
harness.coordinator.switchToPoll(),
).resolves.toMatchObject({
ok: false,
error: { kind: "PROTOCOL_MISMATCH" },
});
liveEffect.resolve(realtimeSuccess(undefined));
await expect(pendingEffect).resolves.toMatchObject({
ok: false,
error: { kind: "SCOPE_FENCED" },
});
await flush();
expect(order).toEqual([
"apply:LIVE:in-flight",
"recover:LIVE->POLL",
]);
expect(harness.coordinator.currentWriter()).toBeNull();
checkpoint.resolve(realtimeSuccess(undefined));
const result = await transition;
expect(result).toMatchObject({
ok: true,
value: { writer: "POLL" },
});
if (!result.ok) throw new Error("expected poll writer");
await result.value.write("polled", 6);
expect(order.at(-1)).toBe("apply:POLL:polled");
expect(result.value.generation).toBeGreaterThan(live.generation);
expect(harness.coordinator.inspect().state).toBe("POLL_ACTIVE");
});
it("fails closed when the prior writer cannot quiesce before the bound", async () => {
const harness = createHarness({
apply: vi.fn(
async () =>
await new Promise<RealtimeResult<void>>(() => {}),
),
});
const live = harness.coordinator.currentWriter()!;
void live.write("hung", 4);
await flush();
const transition = harness.coordinator.switchToPoll();
await flush();
expect(harness.clock.sleepers).toHaveLength(1);
harness.clock.advance(100);
await expect(transition).resolves.toMatchObject({
ok: false,
error: { kind: "IDLE_TIMEOUT", operation: "RECOVER" },
});
expect(harness.recover).not.toHaveBeenCalled();
expect(harness.coordinator.inspect()).toMatchObject({
state: "CLOSED",
activeWriter: null,
});
});
it("keeps poll authoritative while probing, then recovers and drains live values serially", async () => {
const firstLive = deferred<RealtimeResult<void>>();
const order: string[] = [];
let activeEffects = 0;
let highWatermark = 0;
const harness = createHarness({
initial: "POLL",
apply: vi.fn(async ({ writer, value }) => {
activeEffects += 1;
highWatermark = Math.max(highWatermark, activeEffects);
order.push(`apply:${writer}:${value}`);
if (value === "live-1") await firstLive.promise;
activeEffects -= 1;
return realtimeSuccess(undefined);
}),
recover: vi.fn(async ({ from, to }) => {
order.push(`recover:${from}->${to}`);
return realtimeSuccess(undefined);
}),
});
const poll = harness.coordinator.currentWriter()!;
const opened = harness.coordinator.beginLiveProbe();
expect(opened.ok).toBe(true);
if (!opened.ok) throw new Error("expected live probe");
const live = opened.value;
await expect(live.write("live-1", 6)).resolves.toMatchObject({
ok: true,
value: { kind: "BUFFERED" },
});
await live.write("live-2", 6);
expect(live.isCurrent()).toBe(false);
expect(poll.isCurrent()).toBe(true);
await poll.write("poll-during-probe", 8);
expect(order).toEqual(["apply:POLL:poll-during-probe"]);
const activation = live.activate();
await vi.waitFor(() =>
expect(order).toEqual([
"apply:POLL:poll-during-probe",
"recover:POLL->LIVE",
"apply:LIVE:live-1",
]),
);
await live.write("live-3", 6);
expect(harness.coordinator.inspect()).toMatchObject({
state: "LIVE_PROBING",
bufferedEvents: 2,
transitioning: true,
});
firstLive.resolve(realtimeSuccess(undefined));
const activated = await activation;
expect(activated).toMatchObject({
ok: true,
value: { writer: "LIVE" },
});
expect(order).toEqual([
"apply:POLL:poll-during-probe",
"recover:POLL->LIVE",
"apply:LIVE:live-1",
"apply:LIVE:live-2",
"apply:LIVE:live-3",
]);
expect(highWatermark).toBe(1);
expect(live.isCurrent()).toBe(true);
expect(poll.isCurrent()).toBe(false);
await expect(poll.write("stale-poll", 5)).resolves.toMatchObject({
ok: false,
error: { kind: "SCOPE_FENCED" },
});
expect(harness.coordinator.inspect()).toMatchObject({
state: "LIVE_ACTIVE",
bufferedEvents: 0,
bufferedBytes: 0,
});
});
it("drops an overflowing probe without displacing poll and never reuses its generation", async () => {
const harness = createHarness({
initial: "POLL",
limits: {
...limits,
maxProbeBufferedEvents: 2,
},
});
const poll = harness.coordinator.currentWriter()!;
const first = expectProbe(harness.coordinator.beginLiveProbe());
await first.write("one", 3);
await first.write("two", 3);
await expect(first.write("overflow", 3)).resolves.toMatchObject({
ok: false,
error: { kind: "QUEUE_OVERFLOW" },
});
expect(harness.coordinator.inspect().state).toBe("POLL_ACTIVE");
expect(poll.isCurrent()).toBe(true);
await expect(first.write("stale", 999)).resolves.toMatchObject({
ok: false,
error: { kind: "SCOPE_FENCED" },
});
const second = expectProbe(harness.coordinator.beginLiveProbe());
expect(second.generation).toBeGreaterThan(first.generation);
const canceled = second.cancel();
expect(canceled).toMatchObject({
ok: true,
value: { writer: "POLL", generation: poll.generation },
});
expect(second.signal.aborted).toBe(true);
expect(harness.coordinator.inspect().state).toBe("POLL_ACTIVE");
});
it("closes if authoritative recovery fails and never activates the candidate", async () => {
const harness = createHarness({
recover: vi.fn(async () =>
realtimeFailure("CURSOR_EXPIRED", "RECOVER"),
),
});
const live = harness.coordinator.currentWriter()!;
await expect(
harness.coordinator.switchToPoll(),
).resolves.toMatchObject({
ok: false,
error: { kind: "CURSOR_EXPIRED", operation: "RECOVER" },
});
expect(live.signal.aborted).toBe(true);
expect(harness.coordinator.inspect()).toMatchObject({
state: "CLOSED",
activeWriter: null,
});
});
it("bounds a non-cooperative authoritative checkpoint", async () => {
let checkpointIsCurrent: (() => boolean) | undefined;
const harness = createHarness({
recover: vi.fn(async ({ isCurrent }) => {
checkpointIsCurrent = isCurrent;
return await new Promise<RealtimeResult<void>>(() => {});
}),
});
const transition = harness.coordinator.switchToPoll();
await flush();
expect(checkpointIsCurrent?.()).toBe(true);
expect(harness.clock.sleepers).toHaveLength(1);
harness.clock.advance(100);
await expect(transition).resolves.toMatchObject({
ok: false,
error: { kind: "IDLE_TIMEOUT", operation: "RECOVER" },
});
expect(checkpointIsCurrent?.()).toBe(false);
expect(harness.coordinator.inspect().state).toBe("CLOSED");
});
it("aborts and bounds close quiescence when an effect ignores cancellation", async () => {
let effectSignal: AbortSignal | undefined;
const harness = createHarness({
apply: vi.fn(
async ({ signal }) => {
effectSignal = signal;
return await new Promise<RealtimeResult<void>>(() => {});
},
),
});
const live = harness.coordinator.currentWriter()!;
void live.write("hung-close", 8);
await flush();
const closing = harness.coordinator.close();
expect(effectSignal?.aborted).toBe(true);
expect(harness.coordinator.inspect().state).toBe("CLOSED");
await flush();
harness.clock.advance(100);
await expect(closing).resolves.toMatchObject({
ok: false,
error: { kind: "IDLE_TIMEOUT", operation: "CLOSE" },
});
await expect(harness.coordinator.close()).resolves.toMatchObject({
ok: false,
error: { kind: "IDLE_TIMEOUT", operation: "CLOSE" },
});
});
it("rejects invalid initial authority and resource ceilings", () => {
expect(() =>
createLivePollHandoffCoordinator({
initial: {
writer: "LIVE",
authoritativeCheckpointEstablished: false,
} as never,
limits,
apply: async () => realtimeSuccess(undefined),
establishAuthoritativeCheckpoint: async () =>
realtimeSuccess(undefined),
}),
).toThrow(/initial checkpoint/u);
expect(() =>
createLivePollHandoffCoordinator({
initial: {
writer: "POLL",
authoritativeCheckpointEstablished: true,
},
limits: { ...limits, maxProbeBufferedEvents: 257 },
apply: async () => realtimeSuccess(undefined),
establishAuthoritativeCheckpoint: async () =>
realtimeSuccess(undefined),
}),
).toThrow(/limits/u);
expect(() =>
createLivePollHandoffCoordinator({
initial: {
writer: "POLL",
authoritativeCheckpointEstablished: true,
},
limits: { ...limits, maxActiveQueueCount: 257 },
apply: async () => realtimeSuccess(undefined),
establishAuthoritativeCheckpoint: async () =>
realtimeSuccess(undefined),
}),
).toThrow(/limits/u);
});
});
function expectProbe(
result: RealtimeResult<LiveProbeLease<string>>,
): LiveProbeLease<string> {
if (!result.ok) throw new Error("expected live probe");
return result.value;
}
function deferred<Value>() {
let resolve!: (value: Value) => void;
const promise = new Promise<Value>((selectedResolve) => {
resolve = selectedResolve;
});
return { promise, resolve };
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,160 @@
import { describe, expect, it } from "vitest";
import {
calculateReconnectDelay,
defineReconnectPolicy,
isReconnectAttemptResetEligible,
parseRetryAfterDelay,
REALTIME_RECONNECT_CEILINGS,
reconnectBudgetRemaining,
type ReconnectPolicy,
} from "../../../src/adapters/realtime/reconnect-policy.ts";
const policy = defineReconnectPolicy({
baseDelayMs: 1_000,
maxDelayMs: 60_000,
maxAttempts: 10,
maxElapsedMs: 300_000,
stableOpenMs: 30_000,
});
describe("realtime reconnect policy", () => {
it("uses full jitter and treats a server hint as a not-before floor", () => {
expect(
calculateReconnectDelay({
policy,
attemptIndex: 2,
remainingElapsedMs: 10_000,
random: () => 0.5,
}),
).toBe(2_000);
expect(
calculateReconnectDelay({
policy,
attemptIndex: 2,
remainingElapsedMs: 10_000,
random: () => 0.5,
serverNotBeforeMs: 3_000,
}),
).toBe(3_000);
});
it("stops instead of clamping a hint past a hard or remaining budget", () => {
expect(
calculateReconnectDelay({
policy,
attemptIndex: 0,
remainingElapsedMs: 100_000,
random: () => 0,
serverNotBeforeMs: 60_001,
}),
).toBeNull();
expect(
calculateReconnectDelay({
policy,
attemptIndex: 0,
remainingElapsedMs: 3_000,
random: () => 0,
serverNotBeforeMs: 3_000,
}),
).toBeNull();
expect(
calculateReconnectDelay({
policy,
attemptIndex: 10,
remainingElapsedMs: 100_000,
random: () => 0,
}),
).toBeNull();
});
it("parses only bounded-shape Retry-After syntax for caller validation", () => {
expect(parseRetryAfterDelay("12", 0)).toBe(12_000);
expect(
parseRetryAfterDelay(
"Thu, 01 Jan 1970 00:00:20 GMT",
5_000,
),
).toBe(15_000);
expect(parseRetryAfterDelay("1.5", 0)).toBeNull();
expect(parseRetryAfterDelay("-1", 0)).toBeNull();
});
it("resets attempts only after stable open or a valid signal", () => {
expect(
isReconnectAttemptResetEligible({
policy,
openedAtMs: 10,
nowMs: 29_000,
observedValidHeartbeatOrEvent: false,
}),
).toBe(false);
expect(
isReconnectAttemptResetEligible({
policy,
openedAtMs: 10,
nowMs: 30_010,
observedValidHeartbeatOrEvent: false,
}),
).toBe(true);
expect(
isReconnectAttemptResetEligible({
policy,
openedAtMs: 10,
nowMs: 11,
observedValidHeartbeatOrEvent: true,
}),
).toBe(true);
expect(reconnectBudgetRemaining(policy, 1_000, 2_000)).toBe(
299_000,
);
expect(reconnectBudgetRemaining(policy, 2_000, 1_000)).toBe(0);
});
it("rejects policies above the implementation ceiling", () => {
expect(() =>
defineReconnectPolicy({
...policy,
maxAttempts: 11,
}),
).toThrow(TypeError);
});
it("keeps aborted-task drain below the absolute implementation ceiling", () => {
expect(REALTIME_RECONNECT_CEILINGS.drainTimeoutMs).toBe(2_000);
expect(
REALTIME_RECONNECT_CEILINGS.drainTimeoutMs,
).toBeLessThanOrEqual(
REALTIME_RECONNECT_CEILINGS.maxDrainTimeoutMs,
);
expect(
REALTIME_RECONNECT_CEILINGS.maxDrainTimeoutMs,
).toBe(30_000);
});
it("snapshots only exact own data properties", () => {
const inherited = Object.create(policy) as ReconnectPolicy;
const accessor = Object.defineProperties(
{},
{
baseDelayMs: { enumerable: true, value: 1_000 },
maxDelayMs: {
enumerable: true,
get: () => 60_000,
},
maxAttempts: { enumerable: true, value: 10 },
maxElapsedMs: { enumerable: true, value: 300_000 },
stableOpenMs: { enumerable: true, value: 30_000 },
},
) as ReconnectPolicy;
expect(() => defineReconnectPolicy(inherited)).toThrow(TypeError);
expect(() => defineReconnectPolicy(accessor)).toThrow(TypeError);
expect(() =>
defineReconnectPolicy({
...policy,
extra: true,
} as ReconnectPolicy),
).toThrow(TypeError);
});
});
@@ -0,0 +1,222 @@
import { describe, expect, it } from "vitest";
import {
createRealtimePolicyRegistry,
defineEventTypeId,
defineStreamRegistrationId,
REALTIME_HARD_LIMITS,
type RealtimeLimits,
type RealtimeStreamRegistration,
} from "../../../src/contracts/realtime-streams.ts";
import {
EFFECT_PROFILE_ID,
ENDPOINT_ID,
EVENT_TYPE,
KILL_SWITCH_ID,
STREAM_ID,
TEST_API_OPERATIONS,
TEST_LIMITS,
TEST_MAPPERS,
TEST_SCHEMA_CODECS,
createTestRealtimeRegistry,
} from "./fixture.ts";
describe("realtime policy registry", () => {
it("deep-snapshots registrations and resolves only stream-owned event types", () => {
const baseline = createTestRealtimeRegistry();
const sourceEventIds = [EVENT_TYPE];
const sourceLimits = { ...TEST_LIMITS };
const sourceStream: RealtimeStreamRegistration = {
...baseline.listStreams()[0]!,
eventTypeIds: sourceEventIds,
limits: sourceLimits,
};
const sourceEventType = {
...baseline.listEventTypes()[0]!,
};
const registry = createRealtimePolicyRegistry({
streams: [sourceStream],
eventTypes: [sourceEventType],
bindings: bindings(),
});
sourceEventIds[0] = defineEventTypeId("MUTATED_EVENT");
sourceLimits.maxQueueEvents = 1;
sourceEventType.owner = "mutated-owner";
const installed = registry.findStream(STREAM_ID);
expect(installed).toMatchObject({
id: STREAM_ID,
eventTypeIds: [EVENT_TYPE],
limits: { maxQueueEvents: TEST_LIMITS.maxQueueEvents },
});
expect(registry.findEventType(EVENT_TYPE)?.owner).toBe(
"sample-owner",
);
expect(
registry.findStreamEventType(STREAM_ID, EVENT_TYPE)?.id,
).toBe(EVENT_TYPE);
expect(
registry.findStreamEventType(STREAM_ID, "MUTATED_EVENT"),
).toBeUndefined();
expect(Object.isFrozen(installed)).toBe(true);
expect(Object.isFrozen(installed?.eventTypeIds)).toBe(true);
expect(Object.isFrozen(installed?.limits)).toBe(true);
});
it("rejects duplicates, unknown references and extra keys", () => {
const baseline = createTestRealtimeRegistry();
const stream = baseline.listStreams()[0]!;
const eventType = baseline.listEventTypes()[0]!;
expect(() =>
createRealtimePolicyRegistry({
streams: [stream, stream],
eventTypes: [eventType],
bindings: bindings(),
}),
).toThrow("stream is duplicated");
expect(() =>
createRealtimePolicyRegistry({
streams: [
{
...stream,
eventTypeIds: [defineEventTypeId("UNKNOWN_EVENT")],
},
],
eventTypes: [eventType],
bindings: bindings(),
}),
).toThrow("stream registration is invalid");
expect(() =>
createRealtimePolicyRegistry({
streams: [
{
...stream,
unregisteredOverride: true,
} as RealtimeStreamRegistration,
],
eventTypes: [eventType],
bindings: bindings(),
}),
).toThrow("stream registration is invalid");
expect(() =>
createTestRealtimeRegistry({
eventTypeMutator: (candidate) => ({
...candidate,
mapperId: "MissingMapper",
}),
}),
).toThrow("event type registration is invalid");
});
it("closes state-bearing, ephemeral and recovery contradictions", () => {
expect(() =>
createTestRealtimeRegistry({
recovery: {
mode: "SNAPSHOT_ONLY",
snapshotOperationId: "GET_REFERENCE_REALTIME_SNAPSHOT",
checkpointCodecId: "ReferenceRealtimeCheckpoint",
barrier: "NONE",
},
delivery: "INVALIDATION_HINT",
stateBearing: true,
}),
).toThrow("recovery contract is contradictory");
expect(() =>
createTestRealtimeRegistry({
recovery: {
mode: "SESSION_REBUILD",
rebuildInputId: "referenceRealtimeRebuild",
},
delivery: "EPHEMERAL",
stateBearing: true,
}),
).toThrow("recovery contract is contradictory");
expect(() =>
createTestRealtimeRegistry({
recovery: {
mode: "SESSION_REBUILD",
rebuildInputId: "referenceRealtimeRebuild",
},
delivery: "INVALIDATION_HINT",
stateBearing: false,
}),
).toThrow("recovery contract is contradictory");
const registry = createTestRealtimeRegistry({
recovery: {
mode: "SESSION_REBUILD",
rebuildInputId: "referenceRealtimeRebuild",
},
delivery: "EPHEMERAL",
stateBearing: false,
});
expect(registry.findStream(STREAM_ID)?.recovery.mode).toBe(
"SESSION_REBUILD",
);
});
it("allows only reductions of implementation ceilings", () => {
expect(() =>
createTestRealtimeRegistry({
limits: {
...TEST_LIMITS,
maxQueueEvents: REALTIME_HARD_LIMITS.maxQueueEvents + 1,
},
}),
).toThrow("exceed implementation ceilings");
expect(() =>
createTestRealtimeRegistry({
limits: {
...TEST_LIMITS,
maxQueueBytes: TEST_LIMITS.maxEventBytes - 1,
},
}),
).toThrow("cannot hold one event");
const strictLimits: RealtimeLimits = {
...TEST_LIMITS,
maxQueueEvents: 1,
maxDedupeEntries: 1,
};
expect(
createTestRealtimeRegistry({ limits: strictLimits }).findStream(
STREAM_ID,
)?.limits,
).toMatchObject({
maxQueueEvents: 1,
maxDedupeEntries: 1,
});
});
it("issues only bounded closed registry IDs", () => {
expect(defineStreamRegistrationId("VALID_STREAM")).toBe(
"VALID_STREAM",
);
expect(() => defineStreamRegistrationId("arbitrary-channel")).toThrow(
"stream ID is invalid",
);
expect(() => defineEventTypeId("X")).toThrow(
"event type ID is invalid",
);
});
});
function bindings() {
return {
schemaCodecs: TEST_SCHEMA_CODECS,
mappers: TEST_MAPPERS,
apiOperations: TEST_API_OPERATIONS,
endpointIds: [ENDPOINT_ID],
effectProfileIds: [EFFECT_PROFILE_ID],
killSwitchIds: [KILL_SWITCH_ID],
rebuildInputIds: ["referenceRealtimeRebuild"],
} as const;
}
+168
View File
@@ -0,0 +1,168 @@
import { describe, expect, it } from "vitest";
import {
isRealtimeResult,
realtimeFailure,
realtimeSuccess,
snapshotRealtimeResult,
} from "../../../src/adapters/realtime/result.ts";
function isString(value: unknown): value is string {
return typeof value === "string";
}
describe("realtime result boundary", () => {
it("uses an immutable one-shot snapshot instead of rereading a mutable result", () => {
const source = { ok: true, value: "captured" };
const captured = snapshotRealtimeResult(source, (value): value is string => {
source.value = "changed-during-validation";
return value === "captured";
});
source.value = "changed-after-validation";
expect(captured).toEqual(
realtimeSuccess("captured"),
);
expect(Object.isFrozen(captured)).toBe(true);
expect(isRealtimeResult(source, isString)).toBe(false);
});
it("canonicalizes failure fields before the source can change", () => {
const source = {
ok: false,
error: {
kind: "FORBIDDEN",
operation: "RECOVER",
retryable: false,
},
};
const captured = snapshotRealtimeResult(
source,
(_value): _value is never => false,
);
source.error.kind = "PROVIDER_UNAVAILABLE";
source.error.operation = "CONNECT";
source.error.retryable = true;
expect(captured).toEqual(
realtimeFailure("FORBIDDEN", "RECOVER", false),
);
expect(
captured && !captured.ok
? Object.isFrozen(captured.error)
: false,
).toBe(true);
});
it("rejects accessors without invoking them", () => {
let outerReads = 0;
const outerAccessor = Object.defineProperties(
{},
{
ok: {
enumerable: true,
get() {
outerReads += 1;
return true;
},
},
value: {
enumerable: true,
value: "safe",
},
},
);
let nestedReads = 0;
const nestedAccessor = Object.defineProperties(
{},
{
kind: {
enumerable: true,
get() {
nestedReads += 1;
return "FORBIDDEN";
},
},
operation: {
enumerable: true,
value: "RECOVER",
},
retryable: {
enumerable: true,
value: false,
},
},
);
expect(
snapshotRealtimeResult(outerAccessor, isString),
).toBeNull();
expect(
snapshotRealtimeResult(
{ ok: false, error: nestedAccessor },
(_value): _value is never => false,
),
).toBeNull();
expect(outerReads).toBe(0);
expect(nestedReads).toBe(0);
});
it("consumes proxy fields only from one descriptor snapshot", () => {
const propertyReads: PropertyKey[] = [];
const descriptorReads = new Map<PropertyKey, number>();
const source = new Proxy(
{ ok: true, value: "descriptor-value" },
{
get(_target, key) {
propertyReads.push(key);
return key === "value" ? "get-trap-value" : false;
},
getOwnPropertyDescriptor(target, key) {
descriptorReads.set(
key,
(descriptorReads.get(key) ?? 0) + 1,
);
return Reflect.getOwnPropertyDescriptor(target, key);
},
},
);
expect(snapshotRealtimeResult(source, isString)).toEqual(
realtimeSuccess("descriptor-value"),
);
expect(propertyReads).toEqual([]);
expect(descriptorReads).toEqual(
new Map<PropertyKey, number>([
["ok", 1],
["value", 1],
]),
);
});
it("fails closed when a proxy is revoked", () => {
const revocable = Proxy.revocable(
{ ok: true, value: "safe" },
{},
);
revocable.revoke();
expect(
snapshotRealtimeResult(revocable.proxy, isString),
).toBeNull();
expect(isRealtimeResult(revocable.proxy, isString)).toBe(false);
});
it.each([
{ ok: true, value: "safe", extra: true },
Object.assign(
Object.create({ inherited: true }) as Record<string, unknown>,
{ ok: true, value: "safe" },
),
Object.assign(
{ ok: true, value: "safe" },
{ [Symbol("hidden")]: true },
),
])("rejects extra, inherited and symbol-key shapes", (source) => {
expect(snapshotRealtimeResult(source, isString)).toBeNull();
});
});
+188
View File
@@ -0,0 +1,188 @@
import { describe, expect, it } from "vitest";
import {
createIncrementalSseParser,
type SseParserItem,
} from "../../../src/adapters/realtime/sse/sse-parser.ts";
const encoder = new TextEncoder();
function pushText(
parser: ReturnType<typeof createIncrementalSseParser>,
text: string,
): readonly SseParserItem[] {
const result = parser.push(encoder.encode(text));
if (!result.ok) throw new Error(result.error.kind);
return result.value;
}
describe("incremental SSE parser", () => {
it("handles BOM, chunk boundaries, CR/LF/CRLF, comments and multi-line data", () => {
const parser = createIncrementalSseParser();
const chunks = [
"\uFEFF: ready\r",
"\nretry: 2500\revent: resource.updated\n",
"id: cursor-1\r\ndata: first\rdata:second\n\n",
];
const items = chunks.flatMap((chunk) => pushText(parser, chunk));
expect(items).toEqual([
{ kind: "COMMENT" },
{ kind: "RETRY", retryMs: 2_500 },
{
kind: "EVENT",
eventType: "resource.updated",
data: "first\nsecond",
id: "cursor-1",
hasExplicitId: true,
},
]);
expect(parser.finish()).toEqual({
ok: true,
value: {
items: [],
incompleteEventDiscarded: false,
},
});
});
it("preserves standard inherited ID state while marking direct IDs", () => {
const parser = createIncrementalSseParser();
const items = pushText(
parser,
"id: cursor-a\ndata: one\n\ndata: two\n\ndata:\n\n",
);
expect(items).toEqual([
{
kind: "EVENT",
eventType: "message",
data: "one",
id: "cursor-a",
hasExplicitId: true,
},
{
kind: "EVENT",
eventType: "message",
data: "two",
id: "cursor-a",
hasExplicitId: false,
},
{
kind: "EVENT",
eventType: "message",
data: "",
id: "cursor-a",
hasExplicitId: false,
},
]);
});
it("ignores invalid ID and retry fields without inventing a cursor", () => {
const parser = createIncrementalSseParser();
expect(
pushText(
parser,
"id: invalid\u0000cursor\nretry: 99999\ndata: value\n\n",
),
).toEqual([
{
kind: "EVENT",
eventType: "message",
data: "value",
id: null,
hasExplicitId: false,
},
]);
});
it("discards an event that was not terminated by a blank line", () => {
const parser = createIncrementalSseParser();
expect(pushText(parser, "data: incomplete\n")).toEqual([]);
expect(parser.finish()).toEqual({
ok: true,
value: {
items: [],
incompleteEventDiscarded: true,
},
});
expect(parser.push(encoder.encode("data: late\n\n"))).toEqual({
ok: false,
error: {
kind: "CLOSED",
operation: "DECODE",
retryable: false,
},
});
});
it("fails closed on malformed UTF-8 and parser ceilings", () => {
const malformed = createIncrementalSseParser();
expect(
malformed.push(new Uint8Array([0xc3, 0x28])),
).toEqual({
ok: false,
error: {
kind: "MALFORMED_EVENT",
operation: "DECODE",
retryable: false,
},
});
const longLine = createIncrementalSseParser({
maxLineBytes: 4,
maxEventBytes: 8,
maxIncompleteBufferBytes: 8,
maxRetryMs: 100,
});
expect(longLine.push(encoder.encode("data:"))).toEqual({
ok: false,
error: {
kind: "EVENT_TOO_LARGE",
operation: "DECODE",
retryable: false,
},
});
const largeEvent = createIncrementalSseParser({
maxLineBytes: 16,
maxEventBytes: 8,
maxIncompleteBufferBytes: 16,
maxRetryMs: 100,
});
expect(largeEvent.push(encoder.encode("data:abc\n"))).toEqual({
ok: false,
error: {
kind: "EVENT_TOO_LARGE",
operation: "DECODE",
retryable: false,
},
});
const excessiveBatch = createIncrementalSseParser({
maxItemsPerChunk: 2,
});
expect(excessiveBatch.push(encoder.encode(":\n:\n:\n"))).toEqual({
ok: false,
error: {
kind: "QUEUE_OVERFLOW",
operation: "DECODE",
retryable: false,
},
});
const oversizedChunk = createIncrementalSseParser({
maxChunkBytes: 65_536,
});
expect(
oversizedChunk.push(new Uint8Array(65_537)),
).toEqual({
ok: false,
error: {
kind: "EVENT_TOO_LARGE",
operation: "DECODE",
retryable: false,
},
});
});
});
@@ -0,0 +1,975 @@
import { describe, expect, it, vi } from "vitest";
import type {
ExternalRealtimeEventContext,
RealtimeEventAuthority,
RealtimeObservation,
RealtimeRecoveryCommit,
RealtimeRecoveryRequest,
} from "../../../src/application/ports/realtime/event-authority.ts";
import type { RealtimeResult } from "../../../src/application/ports/realtime/shared.ts";
import {
createRealtimeStreamCoordinator,
} from "../../../src/adapters/realtime/stream-coordinator.ts";
import {
realtimeFailure,
realtimeSuccess,
} from "../../../src/adapters/realtime/result.ts";
import type { ValidatedRealtimeEventDto } from "../../../src/adapters/realtime/event-codec.ts";
import type { RealtimePolicyRegistry } from "../../../src/contracts/realtime-streams.ts";
import {
STREAM_ID,
TEST_LIMITS,
TEST_MAPPER,
TEST_MAPPERS,
createTestRealtimeCodec,
createTestRealtimeRegistry,
realtimeEventJson,
type EventOverrides,
} from "./fixture.ts";
describe("transport-independent realtime stream coordinator", () => {
it("applies one stream sequentially and commits each cursor after its effect", async () => {
const first = deferred<RealtimeResult<void>>();
const applied: string[] = [];
const harness = createHarness({
async apply(_profile, value) {
const selected = (value as Readonly<{ value: string }>).value;
applied.push(selected);
return selected === "first"
? first.promise
: realtimeSuccess(undefined);
},
});
await harness.initialize();
const firstResult = harness.coordinator.accept(
harness.event({
eventId: "event-00000001",
sequence: "1",
resumeCursor: "cursor-00000001",
payload: { value: "first" },
}),
);
const secondResult = harness.coordinator.accept(
harness.event({
eventId: "event-00000002",
sequence: "2",
resumeCursor: "cursor-00000002",
payload: { value: "second" },
}),
);
await vi.waitFor(() => expect(applied).toEqual(["first"]));
expect(harness.coordinator.getResumeState(STREAM_ID)).toMatchObject({
lastAppliedSequence: "0",
resumeCursor: "cursor-snapshot-0",
});
first.resolve(realtimeSuccess(undefined));
await expect(firstResult).resolves.toMatchObject({
ok: true,
value: { outcome: "APPLIED" },
});
await expect(secondResult).resolves.toMatchObject({
ok: true,
value: { outcome: "APPLIED" },
});
expect(applied).toEqual(["first", "second"]);
expect(harness.coordinator.getResumeState(STREAM_ID)).toEqual({
recoveryMode: "CURSOR",
streamEpoch: "stream-epoch-0001",
lastAppliedSequence: "2",
resumeCursor: "cursor-00000002",
});
});
it("drops exact duplicates and stale events without replaying effects", async () => {
const harness = createHarness();
await harness.initialize();
const event = harness.event();
await harness.coordinator.accept(event);
await expect(harness.coordinator.accept(event)).resolves.toEqual({
ok: true,
value: {
outcome: "DROPPED",
reason: "DUPLICATE_EVENT",
},
});
await expect(
harness.coordinator.accept(
harness.event({
eventId: "event-stale-0001",
sequence: "0",
resumeCursor: "cursor-stale-0001",
}),
),
).resolves.toEqual({
ok: true,
value: {
outcome: "DROPPED",
reason: "STALE_EVENT",
},
});
expect(harness.effects).toHaveBeenCalledTimes(1);
expect(harness.coordinator.inspect(STREAM_ID).dedupeEntries).toBe(1);
});
it("recovers without applying a conflicting ID, sequence gap or epoch", async () => {
for (const [overrides, expectedReason] of [
[
{
eventId: "event-00000001",
sequence: "1",
payload: { value: "conflict" },
},
"EVENT_CONFLICT",
],
[
{
eventId: "event-gap-000001",
sequence: "3",
resumeCursor: "cursor-gap-000001",
},
"SEQUENCE_GAP",
],
[
{
eventId: "event-epoch-0001",
sequence: "2",
streamEpoch: "stream-epoch-0002",
resumeCursor: "cursor-epoch-0001",
},
"STREAM_EPOCH_CHANGED",
],
] as const) {
const harness = createHarness();
await harness.initialize();
await harness.coordinator.accept(harness.event());
await expect(
harness.coordinator.accept(harness.event(overrides)),
).resolves.toMatchObject({
ok: true,
value: {
outcome: "RECOVERED",
reason: expectedReason,
},
});
expect(harness.recoveryReasons).toEqual([
"INITIALIZE",
expectedReason,
]);
expect(harness.effects).toHaveBeenCalledTimes(1);
}
});
it("does not apply or advance when mapping fails", async () => {
const harness = createHarness({
mappers: {
ReferenceRealtimeMapper: {
...TEST_MAPPER,
map: () => ({
ok: false as const,
code: "MAPPING_INVARIANT_REJECTED" as const,
}),
},
},
});
await harness.initialize();
await expect(
harness.coordinator.accept(harness.event()),
).resolves.toMatchObject({
ok: true,
value: {
outcome: "RECOVERED",
reason: "MAPPING_CONTRACT_VIOLATION",
},
});
expect(harness.effects).not.toHaveBeenCalled();
expect(harness.recoveryReasons).toEqual([
"INITIALIZE",
"MAPPING_CONTRACT_VIOLATION",
]);
});
it("leaves the prior checkpoint when an effect and its recovery fail", async () => {
let recoveryCount = 0;
const harness = createHarness({
apply: async () => realtimeFailure("APPLY_FAILED", "APPLY"),
recover: async () => {
recoveryCount += 1;
return recoveryCount === 1
? realtimeSuccess(snapshotCommit("0"))
: realtimeFailure("PROVIDER_UNAVAILABLE", "RECOVER");
},
});
await harness.initialize();
await expect(
harness.coordinator.accept(harness.event()),
).resolves.toMatchObject({
ok: false,
error: {
kind: "PROVIDER_UNAVAILABLE",
operation: "RECOVER",
},
});
expect(harness.coordinator.getResumeState(STREAM_ID)).toMatchObject({
lastAppliedSequence: "0",
resumeCursor: "cursor-snapshot-0",
});
expect(harness.coordinator.inspect(STREAM_ID).freshness).toBe(
"UNKNOWN",
);
await harness.coordinator.accept(
harness.event({
eventId: "event-00000002",
sequence: "2",
resumeCursor: "cursor-00000002",
}),
);
expect(harness.effects).toHaveBeenCalledTimes(1);
});
it("rejects malformed authority results without advancing a checkpoint", async () => {
let recoveryCount = 0;
const harness = createHarness({
apply: async () =>
({
ok: true,
value: "not-void",
}) as unknown as RealtimeResult<void>,
recover: async () => {
recoveryCount += 1;
return recoveryCount === 1
? realtimeSuccess(snapshotCommit("0"))
: ({
ok: false,
error: {
kind: "FORBIDDEN",
operation: "APPLY",
retryable: false,
},
} as RealtimeResult<RealtimeRecoveryCommit>);
},
});
await harness.initialize();
await expect(
harness.coordinator.accept(harness.event()),
).resolves.toEqual(
realtimeFailure("PROTOCOL_MISMATCH", "RECOVER"),
);
expect(harness.coordinator.getResumeState(STREAM_ID)).toMatchObject({
lastAppliedSequence: "0",
});
expect(harness.coordinator.inspect(STREAM_ID).freshness).toBe(
"UNKNOWN",
);
});
it("rejects recovery accessors without invoking them", async () => {
let checkpointReads = 0;
const accessorCommit = Object.defineProperties(
{},
{
checkpoint: {
enumerable: true,
get() {
checkpointReads += 1;
return snapshotCommit("0");
},
},
kind: {
enumerable: true,
value: "SNAPSHOT_RESET",
},
},
) as RealtimeRecoveryCommit;
const harness = createHarness({
recover: async () => realtimeSuccess(accessorCommit),
});
await expect(
harness.coordinator.recover(STREAM_ID, "INITIALIZE"),
).resolves.toEqual(
realtimeFailure("PROTOCOL_MISMATCH", "RECOVER"),
);
expect(checkpointReads).toBe(0);
expect(harness.coordinator.getResumeState(STREAM_ID)).toBeNull();
});
it("commits only the one-shot descriptor snapshot of a recovery proxy", async () => {
const descriptorCommit = snapshotCommit("0");
const propertyReads: PropertyKey[] = [];
const proxyCommit = new Proxy(descriptorCommit, {
get(_target, key) {
propertyReads.push(key);
if (key === "kind") return "SESSION_REBUILD";
if (key === "checkpoint") return snapshotCommit("99");
return undefined;
},
});
const harness = createHarness({
recover: async () => realtimeSuccess(proxyCommit),
});
const recovered = await harness.coordinator.recover(
STREAM_ID,
"INITIALIZE",
);
expect(recovered).toMatchObject({
ok: true,
value: {
lastAppliedSequence: "0",
resumeCursor: "cursor-snapshot-0",
},
});
expect(propertyReads).toEqual([]);
});
it.each([
Object.freeze({
...snapshotCommit("0"),
unexpected: true,
}),
Object.assign(
Object.create({ inherited: true }) as Record<string, unknown>,
snapshotCommit("0"),
),
])(
"rejects extra and inherited recovery commit shapes",
async (commit) => {
const harness = createHarness({
recover: async () =>
realtimeSuccess(commit as RealtimeRecoveryCommit),
});
await expect(
harness.coordinator.recover(STREAM_ID, "INITIALIZE"),
).resolves.toEqual(
realtimeFailure("PROTOCOL_MISMATCH", "RECOVER"),
);
expect(harness.coordinator.getResumeState(STREAM_ID)).toBeNull();
},
);
it("expires effect and recovery commit leases when callbacks settle", async () => {
let effectContext: ExternalRealtimeEventContext | undefined;
let recoveryRequest: RealtimeRecoveryRequest | undefined;
const harness = createHarness({
async apply(_profile, _value, context) {
effectContext = context;
expect(context.isCurrent()).toBe(true);
return realtimeSuccess(undefined);
},
async recover(request) {
recoveryRequest = request;
expect(request.isCurrent()).toBe(true);
return realtimeSuccess(snapshotCommit("0"));
},
});
await harness.initialize();
expect(recoveryRequest?.isCurrent()).toBe(false);
await harness.coordinator.accept(harness.event());
expect(effectContext?.isCurrent()).toBe(false);
});
it("fences an in-flight successful effect before cursor commit", async () => {
const pending = deferred<RealtimeResult<void>>();
let effectContext: ExternalRealtimeEventContext | undefined;
const harness = createHarness({
apply: async (_profile, _value, context) => {
effectContext = context;
return pending.promise;
},
});
await harness.initialize();
const accepted = harness.coordinator.accept(harness.event());
await vi.waitFor(() =>
expect(harness.effects).toHaveBeenCalledOnce(),
);
harness.setCurrent(false);
expect(effectContext?.isCurrent()).toBe(false);
pending.resolve(realtimeSuccess(undefined));
await expect(accepted).resolves.toEqual({
ok: true,
value: {
outcome: "DROPPED",
reason: "SCOPE_FENCED",
},
});
expect(harness.coordinator.getResumeState(STREAM_ID)).toBeNull();
expect(harness.coordinator.inspect(STREAM_ID)).toMatchObject({
freshness: "UNKNOWN",
dedupeEntries: 0,
queuedEvents: 0,
awaitingTransportBarrier: false,
});
});
it("aborts and quiesces the active effect before queue-overflow recovery", async () => {
const pending = deferred<RealtimeResult<void>>();
let capturedSignal: AbortSignal | undefined;
const registry = createTestRealtimeRegistry({
limits: {
...TEST_LIMITS,
maxQueueEvents: 1,
},
});
const harness = createHarness({
registry,
async apply(_profile, _value, _context, signal) {
capturedSignal = signal;
return pending.promise;
},
});
await harness.initialize();
const first = harness.coordinator.accept(harness.event());
await vi.waitFor(() =>
expect(harness.effects).toHaveBeenCalledOnce(),
);
const overflow = harness.coordinator.accept(
harness.event({
eventId: "event-00000002",
sequence: "2",
resumeCursor: "cursor-00000002",
}),
);
expect(capturedSignal?.aborted).toBe(true);
expect(harness.recoveryReasons).toEqual(["INITIALIZE"]);
pending.resolve(realtimeSuccess(undefined));
await expect(first).resolves.toMatchObject({
ok: true,
value: { outcome: "DROPPED" },
});
await expect(overflow).resolves.toMatchObject({
ok: true,
value: {
outcome: "RECOVERED",
reason: "QUEUE_OVERFLOW",
},
});
expect(harness.recoveryReasons).toEqual([
"INITIALIZE",
"QUEUE_OVERFLOW",
]);
});
it("treats a current scope mismatch as a protocol violation, not a stale callback", async () => {
const harness = createHarness();
await harness.initialize();
await expect(
harness.coordinator.accept(
harness.event({ scopeBinding: "other-scope-binding" }),
),
).resolves.toMatchObject({
ok: true,
value: {
outcome: "RECOVERED",
reason: "SCOPE_PROTOCOL_VIOLATION",
},
});
expect(harness.effects).not.toHaveBeenCalled();
expect(harness.recoveryReasons).toEqual([
"INITIALIZE",
"SCOPE_PROTOCOL_VIOLATION",
]);
});
it("never claims CURRENT for a SNAPSHOT_ONLY stream without a barrier", async () => {
const registry = createTestRealtimeRegistry({
recovery: {
mode: "SNAPSHOT_ONLY",
snapshotOperationId: "GET_REFERENCE_REALTIME_SNAPSHOT",
checkpointCodecId: "ReferenceRealtimeCheckpoint",
barrier: "NONE",
},
delivery: "INVALIDATION_HINT",
stateBearing: false,
});
const harness = createHarness({
registry,
recover: async () =>
realtimeSuccess({
kind: "SNAPSHOT_RESET",
checkpoint: {
recoveryMode: "SNAPSHOT_ONLY",
streamEpoch: "stream-epoch-0001",
lastAppliedSequence: "0",
resumeCursor: null,
snapshotRevision: "snapshot-revision-0",
},
}),
});
await harness.initialize();
expect(harness.coordinator.inspect(STREAM_ID).freshness).toBe("STALE");
await expect(
harness.coordinator.accept(
harness.event({
recoveryMode: "SNAPSHOT_ONLY",
resumeCursor: null,
}),
),
).resolves.toMatchObject({
ok: true,
value: { outcome: "APPLIED" },
});
expect(harness.coordinator.inspect(STREAM_ID).freshness).toBe("STALE");
});
it("requires an exact transport barrier before promoting a recovered stream to CURRENT", async () => {
const harness = createHarness();
const recovered = await harness.coordinator.recover(
STREAM_ID,
"INITIALIZE",
);
expect(recovered.ok).toBe(true);
if (!recovered.ok) return;
await Promise.resolve();
expect(harness.coordinator.inspect(STREAM_ID)).toMatchObject({
freshness: "STALE",
awaitingTransportBarrier: true,
});
expect(
harness.coordinator.confirmTransportBarrier(
STREAM_ID,
Object.freeze({
...recovered.value,
}) as typeof recovered.value,
),
).toMatchObject({
ok: false,
error: { kind: "PROTOCOL_MISMATCH" },
});
const publicResumeState =
harness.coordinator.getResumeState(STREAM_ID);
expect(publicResumeState).not.toBe(recovered.value);
expect(
harness.coordinator.confirmTransportBarrier(
STREAM_ID,
publicResumeState as typeof recovered.value,
),
).toMatchObject({
ok: false,
error: { kind: "PROTOCOL_MISMATCH" },
});
expect(
harness.coordinator.confirmTransportBarrier(
STREAM_ID,
recovered.value,
),
).toEqual(realtimeSuccess(undefined));
expect(harness.coordinator.inspect(STREAM_ID)).toMatchObject({
freshness: "CURRENT",
awaitingTransportBarrier: false,
});
});
it("marks a successful invalidation hint stale until authoritative refresh", async () => {
const registry = createTestRealtimeRegistry({
recovery: {
mode: "SNAPSHOT_ONLY",
snapshotOperationId: "GET_REFERENCE_REALTIME_SNAPSHOT",
checkpointCodecId: "ReferenceRealtimeCheckpoint",
barrier: "CONNECT_BUFFER",
},
delivery: "INVALIDATION_HINT",
stateBearing: false,
});
const harness = createHarness({
registry,
recover: async () =>
realtimeSuccess({
kind: "SNAPSHOT_RESET",
checkpoint: {
recoveryMode: "SNAPSHOT_ONLY",
streamEpoch: "stream-epoch-0001",
lastAppliedSequence: "0",
resumeCursor: null,
snapshotRevision: "snapshot-revision-0",
},
}),
});
await harness.initialize();
expect(harness.coordinator.inspect(STREAM_ID).freshness).toBe(
"CURRENT",
);
await expect(
harness.coordinator.accept(
harness.event({
recoveryMode: "SNAPSHOT_ONLY",
resumeCursor: null,
}),
),
).resolves.toMatchObject({
ok: true,
value: { outcome: "APPLIED" },
});
expect(harness.coordinator.inspect(STREAM_ID).freshness).toBe("STALE");
});
it("recovers instead of evicting and continuing after dedupe capacity", async () => {
const harness = createHarness({
registry: createTestRealtimeRegistry({
limits: {
...TEST_LIMITS,
maxDedupeEntries: 1,
},
}),
});
await harness.initialize();
await harness.coordinator.accept(harness.event());
await expect(
harness.coordinator.accept(
harness.event({
eventId: "event-00000002",
sequence: "2",
resumeCursor: "cursor-00000002",
}),
),
).resolves.toMatchObject({
ok: true,
value: {
outcome: "RECOVERED",
reason: "DEDUPE_OVERFLOW",
},
});
expect(harness.effects).toHaveBeenCalledTimes(1);
expect(harness.coordinator.inspect(STREAM_ID).dedupeEntries).toBe(0);
});
it("rejects a regressing same-epoch recovery checkpoint atomically", async () => {
let checkpoint = "5";
const harness = createHarness({
recover: async () => realtimeSuccess(snapshotCommit(checkpoint)),
});
await harness.initialize();
checkpoint = "4";
await expect(
harness.coordinator.recover(STREAM_ID, "CURSOR_EXPIRED"),
).resolves.toMatchObject({
ok: false,
error: { kind: "PROTOCOL_MISMATCH" },
});
expect(harness.coordinator.getResumeState(STREAM_ID)).toMatchObject({
lastAppliedSequence: "5",
});
});
it("coalesces recovery, closes idempotently and rejects forged DTOs", async () => {
const pending = deferred<RealtimeResult<RealtimeRecoveryCommit>>();
const recover = vi.fn(async () => pending.promise);
const harness = createHarness({ recover });
const first = harness.coordinator.recover(STREAM_ID, "INITIALIZE");
const second = harness.coordinator.recover(STREAM_ID, "SEQUENCE_GAP");
await vi.waitFor(() => expect(recover).toHaveBeenCalledOnce());
pending.resolve(realtimeSuccess(snapshotCommit("0")));
await expect(first).resolves.toMatchObject({ ok: true });
await expect(second).resolves.toMatchObject({ ok: true });
harness.coordinator.close();
harness.coordinator.close();
expect(harness.coordinator.getResumeState(STREAM_ID)).toBeNull();
await expect(
harness.coordinator.accept(
Object.freeze({}) as ValidatedRealtimeEventDto,
),
).resolves.toMatchObject({
ok: false,
error: { kind: "MALFORMED_EVENT" },
});
await expect(
harness.coordinator.accept(harness.event()),
).resolves.toEqual({
ok: true,
value: { outcome: "DROPPED", reason: "CLOSED" },
});
});
it("returns the exact shared checkpoint to an event waiting on active recovery", async () => {
const pending = deferred<RealtimeResult<RealtimeRecoveryCommit>>();
const recover = vi.fn(async () => pending.promise);
const harness = createHarness({ recover });
const recovering = harness.coordinator.recover(
STREAM_ID,
"INITIALIZE",
);
await vi.waitFor(() => expect(recover).toHaveBeenCalledOnce());
const accepting = harness.coordinator.accept(harness.event());
pending.resolve(realtimeSuccess(snapshotCommit("0")));
const recovered = await recovering;
const accepted = await accepting;
expect(recovered.ok).toBe(true);
expect(accepted.ok).toBe(true);
if (!recovered.ok || !accepted.ok) return;
expect(accepted.value).toMatchObject({
outcome: "RECOVERED",
reason: "INITIALIZE",
});
if (accepted.value.outcome !== "RECOVERED") return;
expect(accepted.value.resumeState).toBe(recovered.value);
});
it("aborts only an event waiter without cancelling shared recovery", async () => {
const pending = deferred<RealtimeResult<RealtimeRecoveryCommit>>();
let recoverySignal: AbortSignal | undefined;
const harness = createHarness({
recover: async (request) => {
recoverySignal = request.signal;
return pending.promise;
},
});
const recovering = harness.coordinator.recover(
STREAM_ID,
"INITIALIZE",
);
await vi.waitFor(() => expect(recoverySignal).toBeDefined());
const controller = new AbortController();
const accepting = harness.coordinator.accept(
harness.event(),
controller.signal,
);
controller.abort();
await expect(accepting).resolves.toEqual(
realtimeFailure("ABORTED", "RECEIVE"),
);
expect(recoverySignal?.aborted).toBe(false);
pending.resolve(realtimeSuccess(snapshotCommit("0")));
await expect(recovering).resolves.toMatchObject({ ok: true });
});
it("aborts the active recovery authority when closed", async () => {
let recoverySignal: AbortSignal | undefined;
const harness = createHarness({
recover: async (request) => {
recoverySignal = request.signal;
return new Promise((resolve) => {
request.signal.addEventListener(
"abort",
() => resolve(realtimeFailure("ABORTED", "RECOVER")),
{ once: true },
);
});
},
});
const recovering = harness.coordinator.recover(
STREAM_ID,
"INITIALIZE",
);
await vi.waitFor(() => expect(recoverySignal).toBeDefined());
harness.coordinator.close();
expect(recoverySignal?.aborted).toBe(true);
await expect(recovering).resolves.toMatchObject({
ok: false,
error: { kind: "CLOSED", operation: "RECOVER" },
});
});
it("does not commit a non-cooperative recovery after caller cancellation", async () => {
const pending = deferred<RealtimeResult<RealtimeRecoveryCommit>>();
let recoveryRequest: RealtimeRecoveryRequest | undefined;
const harness = createHarness({
recover: async (request) => {
recoveryRequest = request;
return pending.promise;
},
});
const controller = new AbortController();
const recovering = harness.coordinator.recover(
STREAM_ID,
"INITIALIZE",
controller.signal,
);
await vi.waitFor(() => expect(recoveryRequest).toBeDefined());
controller.abort();
expect(recoveryRequest?.isCurrent()).toBe(false);
pending.resolve(realtimeSuccess(snapshotCommit("0")));
await expect(recovering).resolves.toEqual(
realtimeFailure("ABORTED", "RECOVER"),
);
expect(recoveryRequest?.signal.aborted).toBe(true);
expect(recoveryRequest?.isCurrent()).toBe(false);
expect(harness.coordinator.getResumeState(STREAM_ID)).toBeNull();
expect(harness.coordinator.inspect(STREAM_ID).freshness).toBe(
"UNKNOWN",
);
});
it("emits only closed redacted observations and ignores sink failure", async () => {
const observations: RealtimeObservation[] = [];
const harness = createHarness({
observe(observation) {
observations.push(observation);
throw new Error("diagnostic sink unavailable");
},
});
await harness.initialize();
await harness.coordinator.accept(
harness.event({
eventId: "sensitive-event-id",
resumeCursor: "sensitive-cursor",
payload: { value: "sensitive-payload" },
}),
);
const serialized = JSON.stringify(observations);
expect(serialized).not.toContain("sensitive-event-id");
expect(serialized).not.toContain("sensitive-cursor");
expect(serialized).not.toContain("sensitive-payload");
expect(serialized).not.toContain("scope-binding-0001");
expect(observations).toEqual(
expect.arrayContaining([
expect.objectContaining({
operation: "RECOVER",
outcome: "RECOVERED",
reason: "INITIALIZE",
}),
expect.objectContaining({
operation: "APPLY",
outcome: "APPLIED",
}),
]),
);
});
});
type HarnessOptions = Readonly<{
registry?: RealtimePolicyRegistry;
mappers?: typeof TEST_MAPPERS | Readonly<Record<string, typeof TEST_MAPPER>>;
apply?: RealtimeEventAuthority["effects"]["apply"];
recover?: (
request: RealtimeRecoveryRequest,
) => Promise<RealtimeResult<RealtimeRecoveryCommit>>;
observe?: (observation: RealtimeObservation) => void;
}>;
function createHarness(options: HarnessOptions = {}) {
const registry = options.registry ?? createTestRealtimeRegistry();
const codec = createTestRealtimeCodec(registry);
let current = true;
const recoveryReasons: string[] = [];
let defaultRecoveryCount = 0;
const effects = vi.fn(
options.apply ??
(async () => realtimeSuccess(undefined)),
);
const recover = vi.fn(
options.recover ??
(async (request: RealtimeRecoveryRequest) => {
recoveryReasons.push(request.reason);
defaultRecoveryCount += 1;
return realtimeSuccess(
snapshotCommit(
"0",
`stream-epoch-${String(defaultRecoveryCount).padStart(4, "0")}`,
),
);
}),
);
const authority: RealtimeEventAuthority = {
effects: { apply: effects },
recovery: {
async recover(request) {
if (options.recover) recoveryReasons.push(request.reason);
return recover(request);
},
},
};
const coordinator = createRealtimeStreamCoordinator({
registry,
mappers: options.mappers ?? TEST_MAPPERS,
authority,
scope: {
generation: 7,
scopeBinding: "scope-binding-0001",
isCurrent: () => current,
},
now: () => 10_000,
observe: options.observe,
});
return {
coordinator,
effects,
recoveryReasons,
event(overrides: EventOverrides = {}) {
const decoded = codec.decode(realtimeEventJson(overrides));
if (!decoded.ok) {
throw new Error(`test event failed: ${decoded.error.kind}`);
}
return decoded.value;
},
async initialize() {
const result = await coordinator.recover(
STREAM_ID,
"INITIALIZE",
);
await Promise.resolve();
if (
result.ok &&
coordinator.inspect(STREAM_ID).awaitingTransportBarrier
) {
const confirmed = coordinator.confirmTransportBarrier(
STREAM_ID,
result.value,
);
if (!confirmed.ok) {
throw new Error("test transport barrier failed");
}
}
return result;
},
setCurrent(value: boolean) {
current = value;
},
};
}
function snapshotCommit(
sequence: string,
streamEpoch = "stream-epoch-0001",
): RealtimeRecoveryCommit {
return Object.freeze({
kind: "SNAPSHOT_RESET",
checkpoint: Object.freeze({
recoveryMode: "CURSOR",
streamEpoch,
lastAppliedSequence: sequence,
resumeCursor: `cursor-snapshot-${sequence}`,
snapshotRevision: `snapshot-revision-${sequence}`,
}),
});
}
function deferred<Value>() {
let resolve!: (value: Value) => void;
const promise = new Promise<Value>((next) => {
resolve = next;
});
return { promise, resolve };
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,266 @@
import { describe, expect, it } from "vitest";
import {
REALTIME_WEBSOCKET_PROTOCOL,
decodeWebSocketServerFrame,
encodeWebSocketClientFrame,
nextUnsignedSequence,
type WebSocketAdvertisedLimits,
type WebSocketSubscribeFrame,
} from "../../../src/adapters/realtime/websocket/websocket-protocol.ts";
const LIMITS: WebSocketAdvertisedLimits = Object.freeze({
maxFrameBytes: 65_536,
maxSubscriptions: 32,
maxInboundQueueCount: 256,
maxInboundQueueBytes: 4 * 1_024 * 1_024,
maxOutboundQueueCount: 128,
maxOutboundQueueBytes: 256 * 1_024,
maxBufferedAmountBytes: 256 * 1_024,
maxEventsPerSecond: 128,
});
function encode(value: unknown): string {
return JSON.stringify(value);
}
describe("realtime WebSocket protocol", () => {
it("decodes and freezes an exact WELCOME frame", () => {
const result = decodeWebSocketServerFrame(
encode({
type: "WELCOME",
protocol: REALTIME_WEBSOCKET_PROTOCOL,
connectionId: "connection.0001",
heartbeatMs: 15_000,
heartbeatAckTimeoutMs: 5_000,
limits: LIMITS,
}),
65_536,
);
expect(result).toMatchObject({
ok: true,
value: {
type: "WELCOME",
limits: { maxSubscriptions: 32 },
},
});
if (!result.ok) throw new Error("Expected WELCOME to decode.");
if (result.value.type !== "WELCOME") {
throw new Error("Expected the WELCOME discriminant.");
}
expect(Object.isFrozen(result.value)).toBe(true);
expect(Object.isFrozen(result.value.limits)).toBe(true);
});
it("rejects extra keys, unknown frames, wrong versions and binary data", () => {
const welcome = {
type: "WELCOME",
protocol: REALTIME_WEBSOCKET_PROTOCOL,
connectionId: "connection.0001",
heartbeatMs: 15_000,
heartbeatAckTimeoutMs: 5_000,
limits: LIMITS,
};
expect(
decodeWebSocketServerFrame(
encode({ ...welcome, credential: "must-not-cross" }),
65_536,
),
).toEqual({
ok: false,
error: { code: "MALFORMED_FRAME" },
});
expect(
decodeWebSocketServerFrame(
encode({ ...welcome, protocol: "realtime.v2" }),
65_536,
),
).toEqual({
ok: false,
error: { code: "PROTOCOL_MISMATCH" },
});
expect(
decodeWebSocketServerFrame(
encode({
type: "COMMAND",
protocol: REALTIME_WEBSOCKET_PROTOCOL,
}),
65_536,
),
).toEqual({
ok: false,
error: { code: "UNKNOWN_FRAME" },
});
expect(
decodeWebSocketServerFrame(new Uint8Array([1, 2, 3]), 65_536),
).toEqual({
ok: false,
error: { code: "BINARY_FRAME" },
});
const duplicateTopLevel = encode(welcome).replace(
'{"type":"WELCOME",',
'{"\\u0074ype":"WELCOME","type":"WELCOME",',
);
expect(
decodeWebSocketServerFrame(duplicateTopLevel, 65_536),
).toEqual({
ok: false,
error: { code: "MALFORMED_FRAME" },
});
const duplicateNested = encode({
type: "EVENT",
protocol: REALTIME_WEBSOCKET_PROTOCOL,
subscriptionId: "subscription.0001",
envelope: { streamId: "orders.v1" },
}).replace(
'"streamId":"orders.v1"',
'"streamId":"orders.v1","\\u0073treamId":"shadowed"',
);
expect(
decodeWebSocketServerFrame(duplicateNested, 65_536),
).toEqual({
ok: false,
error: { code: "MALFORMED_FRAME" },
});
});
it("enforces frame bytes and canonical uint64 sequences", () => {
expect(
decodeWebSocketServerFrame(
encode({
type: "SUBSCRIBED",
protocol: REALTIME_WEBSOCKET_PROTOCOL,
subscriptionId: "subscription.0001",
streamEpoch: "stream-epoch.0001",
acceptedCursor: "cursor.0001",
nextExpectedSequence: "01",
}),
65_536,
),
).toEqual({
ok: false,
error: { code: "MALFORMED_FRAME" },
});
expect(
decodeWebSocketServerFrame(
encode({
type: "HEARTBEAT_ACK",
protocol: REALTIME_WEBSOCKET_PROTOCOL,
nonce: "nonce.0001",
}),
8,
),
).toEqual({
ok: false,
error: { code: "FRAME_TOO_LARGE" },
});
expect(nextUnsignedSequence("0")).toBe("1");
expect(nextUnsignedSequence("18446744073709551614")).toBe(
"18446744073709551615",
);
expect(nextUnsignedSequence("18446744073709551615")).toBeNull();
expect(nextUnsignedSequence("01")).toBeNull();
});
it("decodes only an exact UNSUBSCRIBED acknowledgement", () => {
const acknowledgement = {
type: "UNSUBSCRIBED",
protocol: REALTIME_WEBSOCKET_PROTOCOL,
subscriptionId: "subscription.0001",
};
const decoded = decodeWebSocketServerFrame(
encode(acknowledgement),
65_536,
);
expect(decoded).toMatchObject({
ok: true,
value: acknowledgement,
});
if (!decoded.ok) {
throw new Error("Expected UNSUBSCRIBED to decode.");
}
expect(Object.isFrozen(decoded.value)).toBe(true);
expect(
decodeWebSocketServerFrame(
encode({ ...acknowledgement, released: true }),
65_536,
),
).toEqual({
ok: false,
error: { code: "MALFORMED_FRAME" },
});
expect(
decodeWebSocketServerFrame(
encode({ ...acknowledgement, subscriptionId: "" }),
65_536,
),
).toEqual({
ok: false,
error: { code: "MALFORMED_FRAME" },
});
});
it("rejects deeply nested or structurally excessive event envelopes without recursion", () => {
let nested: unknown = "leaf";
for (let depth = 0; depth < 40; depth += 1) {
nested = [nested];
}
const event = (envelope: unknown) =>
encode({
type: "EVENT",
protocol: REALTIME_WEBSOCKET_PROTOCOL,
subscriptionId: "subscription.0001",
envelope,
});
expect(
decodeWebSocketServerFrame(
event({ payload: nested }),
65_536,
),
).toEqual({
ok: false,
error: { code: "MALFORMED_FRAME" },
});
expect(
decodeWebSocketServerFrame(
event({
payload: Array.from({ length: 4_097 }, () => ({})),
}),
65_536,
),
).toEqual({
ok: false,
error: { code: "MALFORMED_FRAME" },
});
});
it("encodes only closed client frames without leaking arbitrary commands", () => {
const frame: WebSocketSubscribeFrame = {
type: "SUBSCRIBE",
protocol: REALTIME_WEBSOCKET_PROTOCOL,
subscriptionId: "subscription.0001",
streamId: "orders.v1",
cursor: "cursor.0001",
scopeBinding: "scope-binding.0001",
};
const result = encodeWebSocketClientFrame(frame, 65_536);
expect(result.ok).toBe(true);
if (!result.ok) throw new Error("Expected SUBSCRIBE to encode.");
expect(JSON.parse(result.value)).toEqual(frame);
expect(
encodeWebSocketClientFrame(
{ ...frame, payload: "arbitrary" } as WebSocketSubscribeFrame,
65_536,
),
).toEqual({
ok: false,
error: { code: "MALFORMED_FRAME" },
});
});
});