123 lines
3.7 KiB
TypeScript
123 lines
3.7 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import type { GrowEventRow } from "../src/db/schema.js";
|
|
import { recordGatewayEvent } from "../src/routes/services.js";
|
|
|
|
for (const service of [
|
|
{
|
|
source: "interview-service",
|
|
type: "interview.session.configured",
|
|
serviceId: "interview",
|
|
},
|
|
{
|
|
source: "roleplay-service",
|
|
type: "roleplay.scenario.configured",
|
|
serviceId: "roleplay",
|
|
},
|
|
] as const) {
|
|
const event = {
|
|
id: `event-${service.serviceId}`,
|
|
userId: "user-1",
|
|
orgId: null,
|
|
source: service.source,
|
|
type: service.type,
|
|
category: "service",
|
|
occurredAt: new Date("2026-07-14T00:00:00.000Z"),
|
|
receivedAt: new Date("2026-07-14T00:00:00.000Z"),
|
|
mission: null,
|
|
subject: { serviceId: service.serviceId, externalId: "session-1" },
|
|
correlation: { sessionId: "session-1" },
|
|
payload: {},
|
|
raw: null,
|
|
dedupeKey: `dedupe-${service.serviceId}`,
|
|
processingStatus: "pending",
|
|
processingError: null,
|
|
processedAt: null,
|
|
} as GrowEventRow;
|
|
|
|
const order: string[] = [];
|
|
const returned = await recordGatewayEvent(
|
|
{
|
|
userId: "user-1",
|
|
source: service.source,
|
|
type: service.type,
|
|
payload: { session_id: "session-1" },
|
|
},
|
|
{
|
|
recordLegacyEvent: async () => {
|
|
order.push("legacy");
|
|
},
|
|
recordGrowEvent: async () => {
|
|
order.push("record");
|
|
return event;
|
|
},
|
|
applyServiceSessionProjection: async (projectedEvent) => {
|
|
assert.strictEqual(projectedEvent, event);
|
|
order.push("project");
|
|
return null;
|
|
},
|
|
routeGrowEventToUserActor: async (routedEvent) => {
|
|
assert.strictEqual(routedEvent, event);
|
|
order.push("route");
|
|
},
|
|
},
|
|
);
|
|
|
|
assert.strictEqual(returned, event);
|
|
assert.deepEqual(order, ["legacy", "record", "project", "route"], `${service.serviceId} must project ownership before actor routing`);
|
|
}
|
|
|
|
const configureDedupeKeys: string[] = [];
|
|
for (const sessionId of ["streak-session-1", "streak-session-2"]) {
|
|
await recordGatewayEvent(
|
|
{
|
|
userId: "user-1",
|
|
source: "interview-service",
|
|
type: "interview.session.configured",
|
|
payload: {
|
|
request: { curatorTaskId: "curator-task-1", taskId: "curator-task-1" },
|
|
result: { session_id: sessionId },
|
|
},
|
|
correlation: {
|
|
sessionId,
|
|
curatorTaskId: "curator-task-1",
|
|
taskId: "curator-task-1",
|
|
},
|
|
},
|
|
{
|
|
recordLegacyEvent: async () => undefined,
|
|
recordGrowEvent: async (input) => {
|
|
configureDedupeKeys.push(input.dedupeKey ?? "");
|
|
return {
|
|
id: `event-${sessionId}`,
|
|
userId: "user-1",
|
|
orgId: null,
|
|
source: "interview-service",
|
|
type: "interview.session.configured",
|
|
category: "service",
|
|
occurredAt: new Date("2026-07-14T00:00:00.000Z"),
|
|
receivedAt: new Date("2026-07-14T00:00:00.000Z"),
|
|
mission: null,
|
|
subject: { serviceId: "interview", externalId: sessionId },
|
|
correlation: { sessionId, curatorTaskId: "curator-task-1" },
|
|
payload: {},
|
|
raw: null,
|
|
dedupeKey: input.dedupeKey ?? null,
|
|
processingStatus: "pending",
|
|
processingError: null,
|
|
processedAt: null,
|
|
} as GrowEventRow;
|
|
},
|
|
applyServiceSessionProjection: async () => null,
|
|
routeGrowEventToUserActor: async () => undefined,
|
|
},
|
|
);
|
|
}
|
|
|
|
assert.notEqual(
|
|
configureDedupeKeys[0],
|
|
configureDedupeKeys[1],
|
|
"reconfiguring the same curator streak task must record ownership for each generated interview session",
|
|
);
|
|
|
|
console.log("interview and roleplay service session projection ordering tests passed");
|