Skip to content
Source
Sign inSign up

ThreadTransportPerformance.test.ts

99 lines3.2 KB

1import {
2 EventId,
3 OrchestrationV2RpcSchemas,
4 ThreadId,
5 TurnItemId,
6 type OrchestrationV2DomainEvent,
7 type OrchestrationV2ThreadStreamItem,
8 type OrchestrationV2TurnItem,
9} from "@t3tools/contracts";
10import * as DateTime from "effect/DateTime";
11import * as Schema from "effect/Schema";
12import type * as RpcMessage from "effect/rpc/RpcMessage";
13import { describe, expect, it } from "vite-plus/test";
14​
15import { projectDomainEventForWire } from "./WireProjection.ts";
16​
17const OUTPUT_BYTES_PER_ROW = 8_192;
18const NOW = DateTime.makeUnsafe("2026-06-20T00:00:00.000Z");
19const THREAD_ID = ThreadId.make("thread-perf");
20​
21const PRE_OMISSION_COMMAND_EVENT_RPC_JSON_BYTES = 8_790;
22const MAX_PROJECTED_COMMAND_EVENT_RPC_JSON_BYTES = 1_024;
23​
24const encodeThreadStreamItem = Schema.encodeSync(
25 Schema.toCodecJson(OrchestrationV2RpcSchemas.subscribeThread.output),
26);
27​
28function encodedBytes(value: unknown): number {
29 return Buffer.byteLength(JSON.stringify(value), "utf8");
31​
32function encodedThreadStreamChunkBytes(value: OrchestrationV2ThreadStreamItem): number {
33 const response = {
34 _tag: "Chunk",
35 requestId: 0,
36 values: [encodeThreadStreamItem(value)],
37 } satisfies RpcMessage.ResponseChunkEncoded;
38 return encodedBytes(response);
40​
41function makeCommandItem(index: number): OrchestrationV2TurnItem {
42 return {
43 id: TurnItemId.make(`item-${index}`),
44 type: "command_execution",
45 threadId: THREAD_ID,
46 runId: null,
47 nodeId: null,
48 providerThreadId: null,
49 providerTurnId: null,
50 nativeItemRef: null,
51 parentItemId: null,
52 ordinal: index + 1,
53 status: "completed",
54 title: `Command ${index}`,
55 input: `cmd-${index}`,
56 output: "x".repeat(OUTPUT_BYTES_PER_ROW),
57 exitCode: 0,
58 startedAt: NOW,
59 completedAt: NOW,
60 updatedAt: NOW,
61 };
63​
64function makeTurnItemEvent(item: OrchestrationV2TurnItem): OrchestrationV2DomainEvent {
65 return {
66 id: EventId.make(`event-${item.id}`),
67 type: "turn-item.updated",
68 threadId: THREAD_ID,
69 occurredAt: NOW,
70 payload: item,
71 };
73​
74describe("thread transport payload budget", () => {
75 it("omits command output from a live event without changing persisted source data", () => {
76 const sourceItem = makeCommandItem(0);
77 const sourceEvent = makeTurnItemEvent(sourceItem);
78 const projectedEvent = projectDomainEventForWire(sourceEvent);
79 const preOmissionStreamItem: OrchestrationV2ThreadStreamItem = {
80 kind: "event",
81 sequence: 1,
82 event: sourceEvent,
83 };
84 const projectedStreamItem: OrchestrationV2ThreadStreamItem = {
85 kind: "event",
86 sequence: 1,
87 event: projectedEvent,
88 };
89​
90 const preOmissionRpcJsonBytes = encodedThreadStreamChunkBytes(preOmissionStreamItem);
91 const projectedRpcJsonBytes = encodedThreadStreamChunkBytes(projectedStreamItem);
92​
93 expect(preOmissionRpcJsonBytes).toBe(PRE_OMISSION_COMMAND_EVENT_RPC_JSON_BYTES);
94 expect(projectedRpcJsonBytes).toBeLessThanOrEqual(MAX_PROJECTED_COMMAND_EVENT_RPC_JSON_BYTES);
95 expect(projectedRpcJsonBytes / preOmissionRpcJsonBytes).toBeLessThanOrEqual(0.1);
96 expect(sourceItem).toHaveProperty("output", "x".repeat(OUTPUT_BYTES_PER_ROW));
97 expect(projectedEvent.payload).not.toHaveProperty("output");
98 });
99});