@turingfocus/chat-testing 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/contract-core.d.ts +12 -0
- package/dist/contract-core.d.ts.map +1 -0
- package/dist/contract-core.js +34 -0
- package/dist/contract-core.js.map +1 -0
- package/dist/contracts.d.ts +4 -0
- package/dist/contracts.d.ts.map +1 -0
- package/dist/contracts.js +4 -0
- package/dist/contracts.js.map +1 -0
- package/dist/fixtures.d.ts +37 -0
- package/dist/fixtures.d.ts.map +1 -0
- package/dist/fixtures.js +365 -0
- package/dist/fixtures.js.map +1 -0
- package/dist/gateway-contracts.d.ts +58 -0
- package/dist/gateway-contracts.d.ts.map +1 -0
- package/dist/gateway-contracts.js +524 -0
- package/dist/gateway-contracts.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/memory-gateway-clock.d.ts +13 -0
- package/dist/memory-gateway-clock.d.ts.map +1 -0
- package/dist/memory-gateway-clock.js +52 -0
- package/dist/memory-gateway-clock.js.map +1 -0
- package/dist/memory-gateway-holds.d.ts +26 -0
- package/dist/memory-gateway-holds.d.ts.map +1 -0
- package/dist/memory-gateway-holds.js +67 -0
- package/dist/memory-gateway-holds.js.map +1 -0
- package/dist/memory-gateway.d.ts +55 -0
- package/dist/memory-gateway.d.ts.map +1 -0
- package/dist/memory-gateway.js +461 -0
- package/dist/memory-gateway.js.map +1 -0
- package/dist/runtime-contracts.d.ts +26 -0
- package/dist/runtime-contracts.d.ts.map +1 -0
- package/dist/runtime-contracts.js +425 -0
- package/dist/runtime-contracts.js.map +1 -0
- package/package.json +37 -0
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
import { createGatewayDeadlineExceededError } from "@turingfocus/chat-protocol";
|
|
2
|
+
import { assert, assertEqual, deadlineFrom, } from "./contract-core.js";
|
|
3
|
+
import { createChatContractFixtures, } from "./fixtures.js";
|
|
4
|
+
const disposeGatewayHarness = async (harness) => {
|
|
5
|
+
try {
|
|
6
|
+
await harness.gateway.dispose({
|
|
7
|
+
deadlineAt: deadlineFrom(harness.controller.now()),
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
finally {
|
|
11
|
+
await harness.dispose?.();
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
const gatewayCase = (name, factory, execute, options = {}) => Object.freeze({
|
|
15
|
+
name,
|
|
16
|
+
async run() {
|
|
17
|
+
const fixtures = createChatContractFixtures(options);
|
|
18
|
+
const harness = await factory(fixtures);
|
|
19
|
+
try {
|
|
20
|
+
await execute(harness, fixtures);
|
|
21
|
+
}
|
|
22
|
+
finally {
|
|
23
|
+
await disposeGatewayHarness(harness);
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
const gatewayIsolationCase = (factory, options = {}) => Object.freeze({
|
|
28
|
+
name: "isolates concurrent Gateway instances",
|
|
29
|
+
async run() {
|
|
30
|
+
const baseTimestamp = 1_773_705_600_000;
|
|
31
|
+
const firstFixtures = createChatContractFixtures({
|
|
32
|
+
answerInteraction: options.answerInteraction,
|
|
33
|
+
baseTimestamp,
|
|
34
|
+
conversationId: "conversation-contract-first",
|
|
35
|
+
});
|
|
36
|
+
const secondFixtures = createChatContractFixtures({
|
|
37
|
+
answerInteraction: options.answerInteraction,
|
|
38
|
+
baseTimestamp: baseTimestamp + 10_000,
|
|
39
|
+
conversationId: "conversation-contract-second",
|
|
40
|
+
});
|
|
41
|
+
const harnesses = [];
|
|
42
|
+
let executionFailure;
|
|
43
|
+
try {
|
|
44
|
+
const first = await factory(firstFixtures);
|
|
45
|
+
harnesses.push(first);
|
|
46
|
+
const second = await factory(secondFixtures);
|
|
47
|
+
harnesses.push(second);
|
|
48
|
+
const firstUpdates = [];
|
|
49
|
+
const secondUpdates = [];
|
|
50
|
+
const firstSubscribed = await first.gateway.subscribe({
|
|
51
|
+
conversationId: firstFixtures.conversation.id,
|
|
52
|
+
deadlineAt: deadlineFrom(first.controller.now()),
|
|
53
|
+
}, { next: (update) => firstUpdates.push(update) });
|
|
54
|
+
const secondSubscribed = await second.gateway.subscribe({
|
|
55
|
+
conversationId: secondFixtures.conversation.id,
|
|
56
|
+
deadlineAt: deadlineFrom(second.controller.now()),
|
|
57
|
+
}, { next: (update) => secondUpdates.push(update) });
|
|
58
|
+
assert(firstSubscribed.ok, "the first instance must subscribe");
|
|
59
|
+
assert(secondSubscribed.ok, "the second instance must subscribe");
|
|
60
|
+
if (options.answerInteraction === true) {
|
|
61
|
+
assert(first.gateway.answerInteraction !== undefined &&
|
|
62
|
+
second.gateway.answerInteraction !== undefined, "each capable instance must expose answerInteraction");
|
|
63
|
+
const answered = await first.gateway.answerInteraction({
|
|
64
|
+
conversationId: firstFixtures.conversation.id,
|
|
65
|
+
answer: {
|
|
66
|
+
requestId: firstFixtures.askUserRequest.requestId,
|
|
67
|
+
revision: firstFixtures.askUserRequest.revision,
|
|
68
|
+
action: "cancel",
|
|
69
|
+
answers: {},
|
|
70
|
+
},
|
|
71
|
+
deadlineAt: deadlineFrom(first.controller.now()),
|
|
72
|
+
});
|
|
73
|
+
assert(answered.ok, "the first instance must answer its own pending interaction");
|
|
74
|
+
assert(second.controller.calls.every(({ operation }) => operation !== "answerInteraction"), "answering through one instance must not reach another");
|
|
75
|
+
}
|
|
76
|
+
await first.controller.emitUpdate(firstFixtures.realtimeMessageUpdate);
|
|
77
|
+
assertEqual(firstUpdates, [firstFixtures.realtimeMessageUpdate], "the first instance must receive its own update");
|
|
78
|
+
assertEqual(secondUpdates, [], "the second instance must not receive the first instance update");
|
|
79
|
+
await first.controller.disconnect(firstFixtures.disconnectError);
|
|
80
|
+
const secondLoaded = await second.gateway.loadConversation({
|
|
81
|
+
conversationId: secondFixtures.conversation.id,
|
|
82
|
+
deadlineAt: deadlineFrom(second.controller.now()),
|
|
83
|
+
});
|
|
84
|
+
assertEqual(secondLoaded, { ok: true, value: secondFixtures.initialSnapshot }, "disconnecting one instance must not disconnect another");
|
|
85
|
+
await first.gateway.dispose({
|
|
86
|
+
deadlineAt: deadlineFrom(first.controller.now()),
|
|
87
|
+
});
|
|
88
|
+
await second.controller.emitUpdate(secondFixtures.realtimeMessageUpdate);
|
|
89
|
+
assertEqual(secondUpdates, [secondFixtures.realtimeMessageUpdate], "disposing one instance must not silence another");
|
|
90
|
+
assertEqual(first.controller.calls.filter(({ operation }) => operation === "loadConversation"), [], "one instance must not record another instance's operations");
|
|
91
|
+
await firstSubscribed.value.dispose({
|
|
92
|
+
deadlineAt: deadlineFrom(first.controller.now()),
|
|
93
|
+
});
|
|
94
|
+
await secondSubscribed.value.dispose({
|
|
95
|
+
deadlineAt: deadlineFrom(second.controller.now()),
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
catch (reason) {
|
|
99
|
+
executionFailure = { reason };
|
|
100
|
+
}
|
|
101
|
+
const cleanupResults = await Promise.allSettled(harnesses.reverse().map(disposeGatewayHarness));
|
|
102
|
+
if (executionFailure !== undefined) {
|
|
103
|
+
throw executionFailure.reason;
|
|
104
|
+
}
|
|
105
|
+
const failedCleanup = cleanupResults.find((result) => result.status === "rejected");
|
|
106
|
+
if (failedCleanup !== undefined) {
|
|
107
|
+
throw failedCleanup.reason;
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
/** Framework-neutral Gateway cases consumable from Vitest, Jest, or Node tests. */
|
|
112
|
+
export const createGatewayContractCases = (factory, options = {}) => Object.freeze([
|
|
113
|
+
gatewayIsolationCase(factory, options),
|
|
114
|
+
gatewayCase("aligns the optional answerInteraction command with capabilities", factory, async ({ controller, gateway }, fixtures) => {
|
|
115
|
+
const loaded = await gateway.loadConversation({
|
|
116
|
+
conversationId: fixtures.conversation.id,
|
|
117
|
+
deadlineAt: deadlineFrom(controller.now()),
|
|
118
|
+
});
|
|
119
|
+
assert(loaded.ok, "the capability probe must load a snapshot");
|
|
120
|
+
const supported = loaded.value.capabilities.answerInteraction === true;
|
|
121
|
+
if (supported) {
|
|
122
|
+
assert(gateway.answerInteraction !== undefined, "an advertised answerInteraction capability requires the command");
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (gateway.answerInteraction === undefined)
|
|
126
|
+
return;
|
|
127
|
+
const answered = await gateway.answerInteraction({
|
|
128
|
+
conversationId: fixtures.conversation.id,
|
|
129
|
+
answer: {
|
|
130
|
+
requestId: fixtures.askUserRequest.requestId,
|
|
131
|
+
revision: fixtures.askUserRequest.revision,
|
|
132
|
+
action: "cancel",
|
|
133
|
+
answers: {},
|
|
134
|
+
},
|
|
135
|
+
deadlineAt: deadlineFrom(controller.now()),
|
|
136
|
+
});
|
|
137
|
+
assert(!answered.ok && answered.error.code === "unsupported", "an unavailable answerInteraction command must return unsupported");
|
|
138
|
+
}, options),
|
|
139
|
+
...(options.answerInteraction === true
|
|
140
|
+
? [
|
|
141
|
+
gatewayCase("executes answerInteraction commands", factory, async ({ controller, gateway }, fixtures) => {
|
|
142
|
+
assert(gateway.answerInteraction !== undefined, "answerInteraction capability requires a Gateway command");
|
|
143
|
+
const input = {
|
|
144
|
+
conversationId: fixtures.conversation.id,
|
|
145
|
+
answer: {
|
|
146
|
+
requestId: fixtures.askUserRequest.requestId,
|
|
147
|
+
revision: fixtures.askUserRequest.revision,
|
|
148
|
+
action: "submit",
|
|
149
|
+
answers: { "0": "first" },
|
|
150
|
+
},
|
|
151
|
+
deadlineAt: deadlineFrom(controller.now()),
|
|
152
|
+
};
|
|
153
|
+
const answered = await gateway.answerInteraction(input);
|
|
154
|
+
assertEqual(answered, { ok: true, value: fixtures.answerInteractionSuccess }, "answerInteraction must preserve its acknowledgement ID");
|
|
155
|
+
assertEqual(controller.calls, [{ operation: "answerInteraction", input }], "answerInteraction must dispatch the complete request payload");
|
|
156
|
+
}, options),
|
|
157
|
+
gatewayCase("rejects invalid answerInteraction input before dispatch", factory, async ({ controller, gateway }, fixtures) => {
|
|
158
|
+
assert(gateway.answerInteraction !== undefined, "answerInteraction capability requires a Gateway command");
|
|
159
|
+
const answered = await gateway.answerInteraction({
|
|
160
|
+
conversationId: fixtures.conversation.id,
|
|
161
|
+
answer: {
|
|
162
|
+
requestId: "r".repeat(1_000),
|
|
163
|
+
revision: fixtures.askUserRequest.revision,
|
|
164
|
+
action: "cancel",
|
|
165
|
+
answers: {},
|
|
166
|
+
},
|
|
167
|
+
deadlineAt: deadlineFrom(controller.now()),
|
|
168
|
+
});
|
|
169
|
+
assert(!answered.ok && answered.error.code === "validation", "invalid answerInteraction input must return validation");
|
|
170
|
+
assertEqual(controller.calls, [], "invalid answerInteraction input must not reach the transport");
|
|
171
|
+
}, options),
|
|
172
|
+
gatewayCase("isolates replacement revisions that reuse a request ID", factory, async ({ controller, gateway }, fixtures) => {
|
|
173
|
+
assert(gateway.answerInteraction !== undefined, "answerInteraction capability requires a Gateway command");
|
|
174
|
+
assert(controller.setSnapshot !== undefined &&
|
|
175
|
+
controller.setAnswerInteractionResult !== undefined, "answerInteraction revision contracts require mutable fake-server state");
|
|
176
|
+
const hold = controller.holdNext("answerInteraction");
|
|
177
|
+
const originalAnswer = {
|
|
178
|
+
conversationId: fixtures.conversation.id,
|
|
179
|
+
answer: {
|
|
180
|
+
requestId: fixtures.askUserRequest.requestId,
|
|
181
|
+
revision: fixtures.askUserRequest.revision,
|
|
182
|
+
action: "cancel",
|
|
183
|
+
answers: {},
|
|
184
|
+
},
|
|
185
|
+
deadlineAt: deadlineFrom(controller.now()),
|
|
186
|
+
};
|
|
187
|
+
const original = gateway.answerInteraction(originalAnswer);
|
|
188
|
+
await hold.started;
|
|
189
|
+
const replacement = {
|
|
190
|
+
...fixtures.askUserRequest,
|
|
191
|
+
revision: "replacement-revision",
|
|
192
|
+
title: "Replacement interaction",
|
|
193
|
+
};
|
|
194
|
+
await controller.setSnapshot({
|
|
195
|
+
...fixtures.initialSnapshot,
|
|
196
|
+
pendingInteraction: replacement,
|
|
197
|
+
});
|
|
198
|
+
await controller.setAnswerInteractionResult({
|
|
199
|
+
ok: true,
|
|
200
|
+
value: {
|
|
201
|
+
requestId: replacement.requestId,
|
|
202
|
+
revision: replacement.revision,
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
const replacementAnswer = {
|
|
206
|
+
conversationId: fixtures.conversation.id,
|
|
207
|
+
answer: {
|
|
208
|
+
requestId: replacement.requestId,
|
|
209
|
+
revision: replacement.revision,
|
|
210
|
+
action: "cancel",
|
|
211
|
+
answers: {},
|
|
212
|
+
},
|
|
213
|
+
deadlineAt: deadlineFrom(controller.now()),
|
|
214
|
+
};
|
|
215
|
+
const replacementResult = await gateway.answerInteraction(replacementAnswer);
|
|
216
|
+
assert(replacementResult.ok, "the replacement revision must be independently answerable");
|
|
217
|
+
hold.release();
|
|
218
|
+
const stale = await original;
|
|
219
|
+
assert(!stale.ok && stale.error.code === "conflict", "the old revision must not affect its replacement");
|
|
220
|
+
assertEqual(controller.calls, [
|
|
221
|
+
{ operation: "answerInteraction", input: originalAnswer },
|
|
222
|
+
{ operation: "answerInteraction", input: replacementAnswer },
|
|
223
|
+
], "each interaction revision must keep its complete payload");
|
|
224
|
+
}, options),
|
|
225
|
+
gatewayCase("rejects stale answerInteraction requests", factory, async ({ controller, gateway }, fixtures) => {
|
|
226
|
+
assert(gateway.answerInteraction !== undefined, "answerInteraction capability requires a Gateway command");
|
|
227
|
+
const answered = await gateway.answerInteraction({
|
|
228
|
+
conversationId: fixtures.conversation.id,
|
|
229
|
+
answer: {
|
|
230
|
+
requestId: "stale-request",
|
|
231
|
+
revision: "stale-revision",
|
|
232
|
+
action: "cancel",
|
|
233
|
+
answers: {},
|
|
234
|
+
},
|
|
235
|
+
deadlineAt: deadlineFrom(controller.now()),
|
|
236
|
+
});
|
|
237
|
+
assert(!answered.ok && answered.error.code === "conflict", "answerInteraction must reject stale request IDs");
|
|
238
|
+
}, options),
|
|
239
|
+
gatewayCase("returns structured answerInteraction failures", factory, async ({ controller, gateway }, fixtures) => {
|
|
240
|
+
assert(gateway.answerInteraction !== undefined, "answerInteraction capability requires a Gateway command");
|
|
241
|
+
await controller.failNext("answerInteraction", fixtures.authenticationError);
|
|
242
|
+
const answered = await gateway.answerInteraction({
|
|
243
|
+
conversationId: fixtures.conversation.id,
|
|
244
|
+
answer: {
|
|
245
|
+
requestId: fixtures.askUserRequest.requestId,
|
|
246
|
+
revision: fixtures.askUserRequest.revision,
|
|
247
|
+
action: "cancel",
|
|
248
|
+
answers: {},
|
|
249
|
+
},
|
|
250
|
+
deadlineAt: deadlineFrom(controller.now()),
|
|
251
|
+
});
|
|
252
|
+
assertEqual(answered, { ok: false, error: fixtures.authenticationError }, "answerInteraction failures must remain structured");
|
|
253
|
+
}, options),
|
|
254
|
+
gatewayCase("bounds answerInteraction by its deadline", factory, async ({ controller, gateway }, fixtures) => {
|
|
255
|
+
assert(gateway.answerInteraction !== undefined, "answerInteraction capability requires a Gateway command");
|
|
256
|
+
const hold = controller.holdNext("answerInteraction");
|
|
257
|
+
const deadlineAt = controller.now() + 1_000;
|
|
258
|
+
const answering = gateway.answerInteraction({
|
|
259
|
+
conversationId: fixtures.conversation.id,
|
|
260
|
+
answer: {
|
|
261
|
+
requestId: fixtures.askUserRequest.requestId,
|
|
262
|
+
revision: fixtures.askUserRequest.revision,
|
|
263
|
+
action: "cancel",
|
|
264
|
+
answers: {},
|
|
265
|
+
},
|
|
266
|
+
deadlineAt,
|
|
267
|
+
});
|
|
268
|
+
await hold.started;
|
|
269
|
+
await controller.advanceTimeTo(deadlineAt);
|
|
270
|
+
const answered = await answering;
|
|
271
|
+
assert(!answered.ok && answered.error.code === "timeout", "answerInteraction must return a structured deadline failure");
|
|
272
|
+
hold.release();
|
|
273
|
+
}, options),
|
|
274
|
+
]
|
|
275
|
+
: []),
|
|
276
|
+
gatewayCase("loads normalized conversations and snapshots", factory, async ({ controller, gateway }, fixtures) => {
|
|
277
|
+
const listed = await gateway.listConversations({
|
|
278
|
+
deadlineAt: deadlineFrom(controller.now()),
|
|
279
|
+
});
|
|
280
|
+
assert(listed.ok, "listConversations must succeed");
|
|
281
|
+
assertEqual(listed.value.conversations, [fixtures.conversation], "listConversations must return the configured conversation");
|
|
282
|
+
const loaded = await gateway.loadConversation({
|
|
283
|
+
conversationId: fixtures.conversation.id,
|
|
284
|
+
deadlineAt: deadlineFrom(controller.now()),
|
|
285
|
+
});
|
|
286
|
+
assert(loaded.ok, "loadConversation must succeed");
|
|
287
|
+
assertEqual(loaded.value, fixtures.initialSnapshot, "loadConversation must return the normalized snapshot");
|
|
288
|
+
}),
|
|
289
|
+
gatewayCase("delivers duplicate, out-of-order, and unknown updates safely", factory, async ({ controller, gateway }, fixtures) => {
|
|
290
|
+
const received = [];
|
|
291
|
+
const subscribed = await gateway.subscribe({
|
|
292
|
+
conversationId: fixtures.conversation.id,
|
|
293
|
+
deadlineAt: deadlineFrom(controller.now()),
|
|
294
|
+
}, { next: (update) => received.push(update) });
|
|
295
|
+
assert(subscribed.ok, "subscribe must succeed");
|
|
296
|
+
for (const update of [
|
|
297
|
+
...fixtures.duplicateMessageUpdates,
|
|
298
|
+
...fixtures.outOfOrderEventUpdates,
|
|
299
|
+
fixtures.unknownEventUpdate,
|
|
300
|
+
]) {
|
|
301
|
+
await controller.emitUpdate(update);
|
|
302
|
+
}
|
|
303
|
+
assertEqual(received, [
|
|
304
|
+
...fixtures.duplicateMessageUpdates,
|
|
305
|
+
...fixtures.outOfOrderEventUpdates,
|
|
306
|
+
fixtures.unknownEventUpdate,
|
|
307
|
+
], "Gateway must preserve normalized delivery semantics");
|
|
308
|
+
await subscribed.value.dispose({
|
|
309
|
+
deadlineAt: deadlineFrom(controller.now()),
|
|
310
|
+
});
|
|
311
|
+
await controller.emitUpdate(fixtures.realtimeMessageUpdate);
|
|
312
|
+
assert(received.length === 5, "disposed subscriptions must stay silent");
|
|
313
|
+
}),
|
|
314
|
+
gatewayCase("executes send and interrupt commands", factory, async ({ controller, gateway }, fixtures) => {
|
|
315
|
+
const sendInput = {
|
|
316
|
+
conversationId: fixtures.conversation.id,
|
|
317
|
+
text: "Contract message",
|
|
318
|
+
clientMessageId: "client-contract",
|
|
319
|
+
deadlineAt: deadlineFrom(controller.now()),
|
|
320
|
+
};
|
|
321
|
+
const sent = await gateway.sendText(sendInput);
|
|
322
|
+
assertEqual(sent, { ok: true, value: fixtures.sendTextSuccess }, "sendText must return the configured command result");
|
|
323
|
+
const interruptInput = {
|
|
324
|
+
conversationId: fixtures.conversation.id,
|
|
325
|
+
runId: fixtures.initialSnapshot.run?.id,
|
|
326
|
+
deadlineAt: deadlineFrom(controller.now()),
|
|
327
|
+
};
|
|
328
|
+
const interrupted = await gateway.interrupt(interruptInput);
|
|
329
|
+
assertEqual(interrupted, { ok: true, value: fixtures.interruptSuccess }, "interrupt must return the configured command result");
|
|
330
|
+
assertEqual(controller.calls, [
|
|
331
|
+
{ operation: "sendText", input: sendInput },
|
|
332
|
+
{ operation: "interrupt", input: interruptInput },
|
|
333
|
+
], "Gateway commands must dispatch their complete request payloads");
|
|
334
|
+
}),
|
|
335
|
+
gatewayCase("rejects stale interrupt targets", factory, async ({ controller, gateway }, fixtures) => {
|
|
336
|
+
const input = {
|
|
337
|
+
conversationId: fixtures.conversation.id,
|
|
338
|
+
runId: "run-stale",
|
|
339
|
+
deadlineAt: deadlineFrom(controller.now()),
|
|
340
|
+
};
|
|
341
|
+
const interrupted = await gateway.interrupt(input);
|
|
342
|
+
assert(!interrupted.ok && interrupted.error.code === "conflict", "interrupt must reject a stale runId with a structured conflict");
|
|
343
|
+
assertEqual(controller.calls, [{ operation: "interrupt", input }], "stale interrupt validation must retain the complete request record");
|
|
344
|
+
}),
|
|
345
|
+
gatewayCase("returns structured authentication failures", factory, async ({ controller, gateway }, fixtures) => {
|
|
346
|
+
await controller.failNext("loadConversation", fixtures.authenticationError);
|
|
347
|
+
const loaded = await gateway.loadConversation({
|
|
348
|
+
conversationId: fixtures.conversation.id,
|
|
349
|
+
deadlineAt: deadlineFrom(controller.now()),
|
|
350
|
+
});
|
|
351
|
+
assertEqual(loaded, { ok: false, error: fixtures.authenticationError }, "authentication failures must remain structured");
|
|
352
|
+
}),
|
|
353
|
+
gatewayCase("reports disconnection and recovers without replacing the port", factory, async ({ controller, gateway }, fixtures) => {
|
|
354
|
+
const errors = [];
|
|
355
|
+
const updates = [];
|
|
356
|
+
const subscribed = await gateway.subscribe({
|
|
357
|
+
conversationId: fixtures.conversation.id,
|
|
358
|
+
deadlineAt: deadlineFrom(controller.now()),
|
|
359
|
+
}, {
|
|
360
|
+
next: (update) => updates.push(update),
|
|
361
|
+
error: (error) => errors.push(error),
|
|
362
|
+
});
|
|
363
|
+
assert(subscribed.ok, "subscribe must succeed before disconnection");
|
|
364
|
+
await controller.disconnect(fixtures.disconnectError);
|
|
365
|
+
assertEqual(errors, [fixtures.disconnectError], "active observers must receive the structured disconnect error");
|
|
366
|
+
const disconnectedLoad = await gateway.loadConversation({
|
|
367
|
+
conversationId: fixtures.conversation.id,
|
|
368
|
+
deadlineAt: deadlineFrom(controller.now()),
|
|
369
|
+
});
|
|
370
|
+
assert(!disconnectedLoad.ok && disconnectedLoad.error.code === "network", "operations must report a network error while disconnected");
|
|
371
|
+
await controller.emitUpdate(fixtures.realtimeMessageUpdate);
|
|
372
|
+
assert(updates.length === 0, "live subscriptions must stay silent while disconnected");
|
|
373
|
+
await controller.reconnect();
|
|
374
|
+
const recoveredLoad = await gateway.loadConversation({
|
|
375
|
+
conversationId: fixtures.conversation.id,
|
|
376
|
+
deadlineAt: deadlineFrom(controller.now()),
|
|
377
|
+
});
|
|
378
|
+
assert(recoveredLoad.ok, "the same Gateway must recover after reconnect");
|
|
379
|
+
await controller.emitUpdate(fixtures.realtimeMessageUpdate);
|
|
380
|
+
const recoveredRealtimeUpdates = updates.filter((update) => update.kind === "timeline.upsert");
|
|
381
|
+
assertEqual(recoveredRealtimeUpdates, [fixtures.realtimeMessageUpdate], "the original live subscription must resume after reconnect");
|
|
382
|
+
assert(updates.every((update) => update.kind === "timeline.upsert" ||
|
|
383
|
+
(update.kind === "run.replace" &&
|
|
384
|
+
update.conversationId === fixtures.conversation.id)), "reconnect may additionally converge only the subscribed run state");
|
|
385
|
+
await subscribed.value.dispose({
|
|
386
|
+
deadlineAt: deadlineFrom(controller.now()),
|
|
387
|
+
});
|
|
388
|
+
}),
|
|
389
|
+
gatewayCase("honors expired deadlines", factory, async ({ gateway }) => {
|
|
390
|
+
const result = await gateway.listConversations({ deadlineAt: 0 });
|
|
391
|
+
assert(!result.ok && result.error.code === "timeout", "expired operations must return a timeout error");
|
|
392
|
+
}),
|
|
393
|
+
gatewayCase("times out in-flight operations and discards late results", factory, async ({ controller, gateway }, fixtures) => {
|
|
394
|
+
const operationHold = controller.holdNext("loadConversation");
|
|
395
|
+
const operationDeadline = controller.now() + 1_000;
|
|
396
|
+
const pendingLoad = gateway.loadConversation({
|
|
397
|
+
conversationId: fixtures.conversation.id,
|
|
398
|
+
deadlineAt: operationDeadline,
|
|
399
|
+
});
|
|
400
|
+
await operationHold.started;
|
|
401
|
+
await controller.advanceTimeTo(operationDeadline);
|
|
402
|
+
assertEqual(await pendingLoad, {
|
|
403
|
+
ok: false,
|
|
404
|
+
error: createGatewayDeadlineExceededError(fixtures.conversation.id),
|
|
405
|
+
}, "an in-flight operation must settle with the standard timeout");
|
|
406
|
+
operationHold.release();
|
|
407
|
+
await operationHold.completed;
|
|
408
|
+
assertEqual(await pendingLoad, {
|
|
409
|
+
ok: false,
|
|
410
|
+
error: createGatewayDeadlineExceededError(fixtures.conversation.id),
|
|
411
|
+
}, "a late transport result must not replace the timeout");
|
|
412
|
+
const timelySubscriptionHold = controller.holdNext("subscribe");
|
|
413
|
+
const timelySubscription = gateway.subscribe({
|
|
414
|
+
conversationId: fixtures.conversation.id,
|
|
415
|
+
deadlineAt: controller.now() + 1_000,
|
|
416
|
+
}, { next: () => undefined });
|
|
417
|
+
await timelySubscriptionHold.started;
|
|
418
|
+
timelySubscriptionHold.release();
|
|
419
|
+
await timelySubscriptionHold.completed;
|
|
420
|
+
const timelySubscribed = await timelySubscription;
|
|
421
|
+
assert(timelySubscribed.ok, "a transport subscription completed before deadline must be exposed");
|
|
422
|
+
assert(Number(timelySubscriptionHold.resourceDisposeCount) === 0, "a timely transport subscription must remain live until public disposal");
|
|
423
|
+
await timelySubscribed.value.dispose({
|
|
424
|
+
deadlineAt: controller.now() + 1_000,
|
|
425
|
+
});
|
|
426
|
+
assert(timelySubscriptionHold.resourceDisposeCount === 1, "public subscription disposal must dispose its transport resource");
|
|
427
|
+
const subscriptionHold = controller.holdNext("subscribe");
|
|
428
|
+
const subscriptionDeadline = controller.now() + 1_000;
|
|
429
|
+
const received = [];
|
|
430
|
+
const pendingSubscription = gateway.subscribe({
|
|
431
|
+
conversationId: fixtures.conversation.id,
|
|
432
|
+
deadlineAt: subscriptionDeadline,
|
|
433
|
+
}, { next: (update) => received.push(update) });
|
|
434
|
+
await subscriptionHold.started;
|
|
435
|
+
await controller.advanceTimeTo(subscriptionDeadline);
|
|
436
|
+
assertEqual(await pendingSubscription, {
|
|
437
|
+
ok: false,
|
|
438
|
+
error: createGatewayDeadlineExceededError(fixtures.conversation.id),
|
|
439
|
+
}, "late subscription establishment must settle with the standard timeout");
|
|
440
|
+
assert(Number(subscriptionHold.resourceDisposeCount) === 0, "a timed-out subscription has no transport resource before completion");
|
|
441
|
+
subscriptionHold.release();
|
|
442
|
+
assert(Number(subscriptionHold.resourceDisposeCount) === 0, "releasing the fake transport must not itself dispose its resource");
|
|
443
|
+
await subscriptionHold.completed;
|
|
444
|
+
await Promise.resolve();
|
|
445
|
+
assert(subscriptionHold.resourceDisposeCount === 1, "Gateway logic must dispose the transport subscription created after timeout");
|
|
446
|
+
await controller.emitUpdate(fixtures.realtimeMessageUpdate);
|
|
447
|
+
assert(received.length === 0, "a late subscription must never notify its observer");
|
|
448
|
+
}),
|
|
449
|
+
gatewayCase("bounds subscription and Gateway cleanup by deadline", factory, async ({ controller, gateway }, fixtures) => {
|
|
450
|
+
const subscribed = await gateway.subscribe({
|
|
451
|
+
conversationId: fixtures.conversation.id,
|
|
452
|
+
deadlineAt: controller.now() + 1_000,
|
|
453
|
+
}, { next: () => undefined });
|
|
454
|
+
assert(subscribed.ok, "subscribe must succeed before cleanup probes");
|
|
455
|
+
const subscriptionCleanup = controller.holdNext("subscription.dispose");
|
|
456
|
+
const subscriptionDeadline = controller.now() + 1_000;
|
|
457
|
+
const disposingSubscription = subscribed.value.dispose({
|
|
458
|
+
deadlineAt: subscriptionDeadline,
|
|
459
|
+
});
|
|
460
|
+
await subscriptionCleanup.started;
|
|
461
|
+
await controller.advanceTimeTo(subscriptionDeadline);
|
|
462
|
+
await disposingSubscription;
|
|
463
|
+
subscriptionCleanup.release();
|
|
464
|
+
const gatewayCleanup = controller.holdNext("gateway.dispose");
|
|
465
|
+
const gatewayDeadline = controller.now() + 1_000;
|
|
466
|
+
const disposingGateway = gateway.dispose({
|
|
467
|
+
deadlineAt: gatewayDeadline,
|
|
468
|
+
});
|
|
469
|
+
await gatewayCleanup.started;
|
|
470
|
+
await controller.advanceTimeTo(gatewayDeadline);
|
|
471
|
+
await disposingGateway;
|
|
472
|
+
gatewayCleanup.release();
|
|
473
|
+
}),
|
|
474
|
+
gatewayCase("owns transport subscription resources across rejection and disposal", factory, async ({ controller, gateway }, fixtures) => {
|
|
475
|
+
const rejectedHold = controller.holdNext("subscribe");
|
|
476
|
+
const rejectedSubscription = gateway.subscribe({
|
|
477
|
+
conversationId: "conversation-foreign",
|
|
478
|
+
deadlineAt: controller.now() + 1_000,
|
|
479
|
+
}, { next: () => undefined });
|
|
480
|
+
await rejectedHold.started;
|
|
481
|
+
rejectedHold.release();
|
|
482
|
+
const rejected = await rejectedSubscription;
|
|
483
|
+
assert(!rejected.ok && rejected.error.code === "not-found", "a transport subscription for an unknown conversation must be rejected");
|
|
484
|
+
assert(rejectedHold.resourceDisposeCount === 1, "a transport subscription rejected after establishment must be disposed");
|
|
485
|
+
const activeHold = controller.holdNext("subscribe");
|
|
486
|
+
const activeSubscription = gateway.subscribe({
|
|
487
|
+
conversationId: fixtures.conversation.id,
|
|
488
|
+
deadlineAt: controller.now() + 1_000,
|
|
489
|
+
}, { next: () => undefined });
|
|
490
|
+
await activeHold.started;
|
|
491
|
+
activeHold.release();
|
|
492
|
+
const active = await activeSubscription;
|
|
493
|
+
assert(active.ok, "the held transport subscription must become active");
|
|
494
|
+
assert(Number(activeHold.resourceDisposeCount) === 0, "an active transport subscription must remain live");
|
|
495
|
+
await gateway.dispose({ deadlineAt: controller.now() + 1_000 });
|
|
496
|
+
assert(activeHold.resourceDisposeCount === 1, "Gateway disposal must dispose every active transport subscription");
|
|
497
|
+
}),
|
|
498
|
+
gatewayCase("rejects a subscription that completes after Gateway disposal", factory, async ({ controller, gateway }, fixtures) => {
|
|
499
|
+
const establishingHold = controller.holdNext("subscribe");
|
|
500
|
+
const establishing = gateway.subscribe({
|
|
501
|
+
conversationId: fixtures.conversation.id,
|
|
502
|
+
deadlineAt: controller.now() + 1_000,
|
|
503
|
+
}, { next: () => undefined });
|
|
504
|
+
await establishingHold.started;
|
|
505
|
+
await gateway.dispose({ deadlineAt: controller.now() + 1_000 });
|
|
506
|
+
establishingHold.release();
|
|
507
|
+
const result = await establishing;
|
|
508
|
+
assert(!result.ok && result.error.code === "conflict", "subscription establishment must not outlive Gateway disposal");
|
|
509
|
+
assert(establishingHold.resourceDisposeCount === 1, "a transport subscription completing after Gateway disposal must be disposed");
|
|
510
|
+
}),
|
|
511
|
+
gatewayCase("becomes silent and remains idempotently disposable", factory, async ({ controller, gateway }, fixtures) => {
|
|
512
|
+
const received = [];
|
|
513
|
+
const subscribed = await gateway.subscribe({
|
|
514
|
+
conversationId: fixtures.conversation.id,
|
|
515
|
+
deadlineAt: deadlineFrom(controller.now()),
|
|
516
|
+
}, { next: (update) => received.push(update) });
|
|
517
|
+
assert(subscribed.ok, "subscribe must succeed before Gateway disposal");
|
|
518
|
+
await gateway.dispose({ deadlineAt: deadlineFrom(controller.now()) });
|
|
519
|
+
await gateway.dispose({ deadlineAt: deadlineFrom(controller.now()) });
|
|
520
|
+
await controller.emitUpdate(fixtures.realtimeMessageUpdate);
|
|
521
|
+
assert(received.length === 0, "disposed Gateways must stay silent");
|
|
522
|
+
}),
|
|
523
|
+
]);
|
|
524
|
+
//# sourceMappingURL=gateway-contracts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway-contracts.js","sourceRoot":"","sources":["../src/gateway-contracts.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface DeadlineSignal {
|
|
2
|
+
cancel(): void;
|
|
3
|
+
readonly promise: Promise<void>;
|
|
4
|
+
}
|
|
5
|
+
/** Deterministic clock used to drive Memory Gateway deadlines without timers. */
|
|
6
|
+
export declare class MemoryGatewayClock {
|
|
7
|
+
#private;
|
|
8
|
+
constructor(now: number);
|
|
9
|
+
now(): number;
|
|
10
|
+
signal(deadlineAt: number): DeadlineSignal;
|
|
11
|
+
advanceTo(timestamp: number): void;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=memory-gateway-clock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-gateway-clock.d.ts","sourceRoot":"","sources":["../src/memory-gateway-clock.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC7B,MAAM,IAAI,IAAI,CAAC;IACf,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CACjC;AAED,iFAAiF;AACjF,qBAAa,kBAAkB;;gBAIjB,GAAG,EAAE,MAAM;IAIvB,GAAG,IAAI,MAAM;IAIb,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc;IA8B1C,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;CASnC"}
|