authorgravatar for me@t3.ggTheo Browne <me@t3.gg> 2026-09-04 12:12:49-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-04 12:12:49-07:00
log6365919f2e5bcfb4fa4020b95e19af26ae40979f
treea0a61525de2cc0b0aa99ae9a091ee2ff20479133
parent77b655c47b82c9b2aad09e447117b7618a16e21d
signature Signed by PGP key B5690EEEBB952194

perf(server): skip history reads for metadata commands (#9758)


2 files changed, 69 insertions(+), 43 deletions(-)

apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts+46-26
......@@ -29,6 +29,7 @@ import * as Deferred from "effect/Deferred";
2929import * as Exit from "effect/Exit";
3030import * as Layer from "effect/Layer";
3131import * as ManagedRuntime from "effect/ManagedRuntime";
32import * as Option from "effect/Option";
3233import * as PubSub from "effect/PubSub";
3334import * as Scope from "effect/Scope";
3435import * as Stream from "effect/Stream";
......@@ -170,6 +171,7 @@ describe("ProviderCommandReactor", () => {
170171 readonly threadModelSelection?: ModelSelection;
171172 readonly sessionModelSwitch?: "unsupported" | "in-session";
172173 readonly requiresNewThreadForModelChange?: boolean;
174 readonly unreadableHistory?: boolean;
173175 readonly titleRegenerationCompletionDispatchFailures?: number;
174176 readonly titleRegenerationBeforeStart?: "one" | "two";
175177 readonly serverActivation?: Effect.Effect<void>;
......@@ -512,6 +514,23 @@ describe("ProviderCommandReactor", () => {
512514 createdAt: now,
513515 }),
514516 );
517 if (input?.unreadableHistory === true) {
518 // Metadata commands must not decode this unrelated message body.
519 await runtime.runPromise(
520 Effect.gen(function* () {
521 const sql = yield* SqlClient.SqlClient;
522 yield* sql`
523 INSERT INTO projection_thread_messages (
524 message_id, thread_id, turn_id, role, text, attachments_json,
525 is_streaming, created_at, updated_at
526 ) VALUES (
527 'old-unreadable-message', 'thread-1', NULL, 'assistant',
528 'Old assistant output', 'invalid json', 0, ${now}, ${now}
529 )
530 `;
531 }),
532 );
533 }
515534 if (input?.titleRegenerationBeforeStart === "two") {
516535 await Effect.runPromise(
517536 engine.dispatch({
......@@ -561,6 +580,7 @@ describe("ProviderCommandReactor", () => {
561580
562581 return {
563582 engine,
583 snapshotQuery,
564584 readModel: () => Effect.runPromise(snapshotQuery.getSnapshot()),
565585 readPendingTurnStarts: () =>
566586 runtime!.runPromise(
......@@ -3533,8 +3553,8 @@ describe("ProviderCommandReactor", () => {
35333553 });
35343554 });
35353555
3536 it("reacts to thread.approval.respond by forwarding provider approval response", async () => {
3537 const harness = await createHarness();
3556 it("forwards approval responses without reading unrelated message bodies", async () => {
3557 const harness = await createHarness({ unreadableHistory: true });
35383558 const now = "2026-01-01T00:00:00.000Z";
35393559
35403560 await Effect.runPromise(
......@@ -3566,7 +3586,7 @@ describe("ProviderCommandReactor", () => {
35663586 }),
35673587 );
35683588
3569 await waitFor(() => harness.respondToRequest.mock.calls.length === 1);
3589 await harness.drain();
35703590 expect(harness.respondToRequest.mock.calls[0]?.[0]).toEqual({
35713591 threadId: "thread-1",
35723592 requestId: "approval-request-1",
......@@ -3574,8 +3594,8 @@ describe("ProviderCommandReactor", () => {
35743594 });
35753595 });
35763596
3577 it("reacts to thread.user-input.respond by forwarding structured user input answers", async () => {
3578 const harness = await createHarness();
3597 it("forwards user input answers without reading unrelated message bodies", async () => {
3598 const harness = await createHarness({ unreadableHistory: true });
35793599 const now = "2026-01-01T00:00:00.000Z";
35803600
35813601 await Effect.runPromise(
......@@ -3609,7 +3629,7 @@ describe("ProviderCommandReactor", () => {
36093629 }),
36103630 );
36113631
3612 await waitFor(() => harness.respondToUserInput.mock.calls.length === 1);
3632 await harness.drain();
36133633 expect(harness.respondToUserInput.mock.calls[0]?.[0]).toEqual({
36143634 threadId: "thread-1",
36153635 requestId: "user-input-request-1",
......@@ -3823,12 +3843,12 @@ describe("ProviderCommandReactor", () => {
38233843 expect(resolvedActivity).toBeUndefined();
38243844 });
38253845
3826 it("reacts to thread.session.stop by stopping provider session and clearing thread session state", async () => {
3827 const harness = await createHarness();
3828 const now = "2026-01-01T00:00:00.000Z";
3846 effectIt.effect("stops a provider session without reading unrelated message bodies", () =>
3847 Effect.gen(function* () {
3848 const harness = yield* Effect.promise(() => createHarness({ unreadableHistory: true }));
3849 const now = "2026-01-01T00:00:00.000Z";
38293850
3830 await harness.runEffect(
3831 harness.engine.dispatch({
3851 yield* harness.engine.dispatch({
38323852 type: "thread.session.set",
38333853 commandId: CommandId.make("cmd-session-set-for-stop"),
38343854 threadId: ThreadId.make("thread-1"),
......@@ -3843,27 +3863,27 @@ describe("ProviderCommandReactor", () => {
38433863 updatedAt: now,
38443864 },
38453865 createdAt: now,
3846 }),
3847 );
3866 });
38483867
3849 await harness.runEffect(
3850 harness.engine.dispatch({
3868 yield* harness.engine.dispatch({
38513869 type: "thread.session.stop",
38523870 commandId: CommandId.make("cmd-session-stop"),
38533871 threadId: ThreadId.make("thread-1"),
38543872 createdAt: now,
3855 }),
3856 );
3873 });
38573874
3858 await waitFor(() => harness.stopSession.mock.calls.length === 1);
3859 const readModel = await harness.readModel();
3860 const thread = readModel.threads.find((entry) => entry.id === ThreadId.make("thread-1"));
3861 expect(thread?.session).not.toBeNull();
3862 expect(thread?.session?.status).toBe("stopped");
3863 expect(thread?.session?.threadId).toBe("thread-1");
3864 expect(thread?.session?.providerInstanceId).toBe(ProviderInstanceId.make("codex_work"));
3865 expect(thread?.session?.activeTurnId).toBeNull();
3866 });
3875 yield* Effect.promise(() => harness.drain());
3876 expect(harness.stopSession).toHaveBeenCalledWith({ threadId: ThreadId.make("thread-1") });
3877 const thread = yield* harness.snapshotQuery
3878 .getThreadShellById(ThreadId.make("thread-1"))
3879 .pipe(Effect.map(Option.getOrThrow));
3880 expect(thread.session).not.toBeNull();
3881 expect(thread.session?.status).toBe("stopped");
3882 expect(thread.session?.threadId).toBe("thread-1");
3883 expect(thread.session?.providerInstanceId).toBe(ProviderInstanceId.make("codex_work"));
3884 expect(thread.session?.activeTurnId).toBeNull();
3885 }),
3886 );
38673887
38683888 effectIt.effect("stops a ready provider session after automatic settlement", () =>
38693889 Effect.gen(function* () {
apps/server/src/orchestration/Layers/ProviderCommandReactor.ts+23-17
......@@ -419,7 +419,7 @@ const make = Effect.gen(function* () {
419419 readonly detail: string;
420420 readonly createdAt: string;
421421 }) {
422 const thread = yield* resolveThread(input.threadId);
422 const thread = yield* resolveThreadShell(input.threadId);
423423 if (!thread) {
424424 return;
425425 }
......@@ -447,7 +447,7 @@ const make = Effect.gen(function* () {
447447 compactingThreadIds.delete(threadId);
448448 return;
449449 }
450 const thread = yield* resolveThread(threadId);
450 const thread = yield* resolveThreadShell(threadId);
451451 if (!thread?.session) return;
452452 if (
453453 thread.session.status !== "starting" &&
......@@ -525,7 +525,13 @@ const make = Effect.gen(function* () {
525525 );
526526 });
527527
528 const resolveThread = Effect.fnUntraced(function* (threadId: ThreadId) {
528 const resolveThreadShell = Effect.fnUntraced(function* (threadId: ThreadId) {
529 return yield* projectionSnapshotQuery
530 .getThreadShellById(threadId)
531 .pipe(Effect.map(Option.getOrUndefined));
532 });
533
534 const resolveThreadDetail = Effect.fnUntraced(function* (threadId: ThreadId) {
529535 return yield* projectionSnapshotQuery
530536 .getThreadDetailById(threadId, { activityKinds: [] })
531537 .pipe(Effect.map(Option.getOrUndefined));
......@@ -571,7 +577,7 @@ const make = Effect.gen(function* () {
571577 readonly pendingTurnStart?: boolean;
572578 },
573579 ) {
574 const thread = yield* resolveThread(threadId);
580 const thread = yield* resolveThreadShell(threadId);
575581 if (!thread) {
576582 return yield* Effect.die(new Error(`Thread '${threadId}' was not found in read model.`));
577583 }
......@@ -834,7 +840,7 @@ const make = Effect.gen(function* () {
834840 readonly interactionMode?: "default" | "plan";
835841 readonly createdAt: string;
836842 }) {
837 const thread = yield* resolveThread(input.threadId);
843 const thread = yield* resolveThreadShell(input.threadId);
838844 if (!thread) {
839845 return yield* Effect.die(
840846 new Error(`Thread '${input.threadId}' was not found in read model.`),
......@@ -975,7 +981,7 @@ const make = Effect.gen(function* () {
975981 );
976982 if (!generated) return;
977983
978 const thread = yield* resolveThread(input.threadId);
984 const thread = yield* resolveThreadShell(input.threadId);
979985 if (!thread) return;
980986 if (!canReplaceThreadTitle(thread.title, input.titleSeed)) {
981987 return;
......@@ -1007,7 +1013,7 @@ const make = Effect.gen(function* () {
10071013 return { _tag: "Superseded" } as const;
10081014 }
10091015
1010 const thread = yield* resolveThread(event.payload.threadId);
1016 const thread = yield* resolveThreadDetail(event.payload.threadId);
10111017 if (!thread || thread.titleRegeneration?.requestId !== requestId) {
10121018 return { _tag: "Superseded" } as const;
10131019 }
......@@ -1040,7 +1046,7 @@ const make = Effect.gen(function* () {
10401046 return { _tag: "Completed", title: undefined } as const;
10411047 }
10421048
1043 const latestThread = yield* resolveThread(event.payload.threadId);
1049 const latestThread = yield* resolveThreadShell(event.payload.threadId);
10441050 if (
10451051 !latestThread ||
10461052 latestThread.titleRegeneration?.requestId !== requestId ||
......@@ -1177,7 +1183,7 @@ const make = Effect.gen(function* () {
11771183 return;
11781184 }
11791185
1180 const thread = yield* resolveThread(event.payload.threadId);
1186 const thread = yield* resolveThreadDetail(event.payload.threadId);
11811187 if (!thread) {
11821188 return;
11831189 }
......@@ -1366,7 +1372,7 @@ const make = Effect.gen(function* () {
13661372 "Context compaction requires an existing conversation.",
13671373 );
13681374 }
1369 const latestThread = yield* resolveThread(event.payload.threadId);
1375 const latestThread = yield* resolveThreadShell(event.payload.threadId);
13701376 if (
13711377 compactingThreadIds.has(event.payload.threadId) ||
13721378 latestThread?.session?.status === "starting" ||
......@@ -1436,7 +1442,7 @@ const make = Effect.gen(function* () {
14361442 const processTurnInterruptRequested = Effect.fn("processTurnInterruptRequested")(function* (
14371443 event: Extract<ProviderIntentEvent, { type: "thread.turn-interrupt-requested" }>,
14381444 ) {
1439 const thread = yield* resolveThread(event.payload.threadId);
1445 const thread = yield* resolveThreadShell(event.payload.threadId);
14401446 if (!thread) {
14411447 return;
14421448 }
......@@ -1459,7 +1465,7 @@ const make = Effect.gen(function* () {
14591465
14601466 const detail = formatFailureDetail(cause);
14611467 return Effect.gen(function* () {
1462 const latestThread = yield* resolveThread(event.payload.threadId);
1468 const latestThread = yield* resolveThreadShell(event.payload.threadId);
14631469 const latestSession = latestThread?.session;
14641470 if (
14651471 !latestSession ||
......@@ -1487,7 +1493,7 @@ const make = Effect.gen(function* () {
14871493 );
14881494 }),
14891495 );
1490 const stoppedThread = yield* resolveThread(event.payload.threadId);
1496 const stoppedThread = yield* resolveThreadShell(event.payload.threadId);
14911497 const stoppedSession = stoppedThread?.session;
14921498 if (
14931499 !stoppedSession ||
......@@ -1531,7 +1537,7 @@ const make = Effect.gen(function* () {
15311537 const processApprovalResponseRequested = Effect.fn("processApprovalResponseRequested")(function* (
15321538 event: Extract<ProviderIntentEvent, { type: "thread.approval-response-requested" }>,
15331539 ) {
1534 const thread = yield* resolveThread(event.payload.threadId);
1540 const thread = yield* resolveThreadShell(event.payload.threadId);
15351541 if (!thread) {
15361542 return;
15371543 }
......@@ -1575,7 +1581,7 @@ const make = Effect.gen(function* () {
15751581 function* (
15761582 event: Extract<ProviderIntentEvent, { type: "thread.user-input-response-requested" }>,
15771583 ) {
1578 const thread = yield* resolveThread(event.payload.threadId);
1584 const thread = yield* resolveThreadShell(event.payload.threadId);
15791585 if (!thread) {
15801586 return;
15811587 }
......@@ -1619,7 +1625,7 @@ const make = Effect.gen(function* () {
16191625 const processSessionStopRequested = Effect.fn("processSessionStopRequested")(function* (
16201626 event: Extract<ProviderIntentEvent, { type: "thread.session-stop-requested" }>,
16211627 ) {
1622 const thread = yield* resolveThread(event.payload.threadId);
1628 const thread = yield* resolveThreadShell(event.payload.threadId);
16231629 if (!thread) {
16241630 return;
16251631 }
......@@ -1696,7 +1702,7 @@ const make = Effect.gen(function* () {
16961702 yield* threadTitleRegenerationWorker.enqueue(event);
16971703 return;
16981704 case "thread.runtime-mode-set": {
1699 const thread = yield* resolveThread(event.payload.threadId);
1705 const thread = yield* resolveThreadShell(event.payload.threadId);
17001706 if (!thread?.session || thread.session.status === "stopped") {
17011707 return;
17021708 }