Repository navigation
perf(server): index slow projection lookups #22354
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| import { assert, it } from "@effect/vitest"; | ||
| import * as NodeSqliteClient from "@t3tools/shared/nodeSqliteClient"; | ||
| import * as Effect from "effect/Effect"; | ||
| import * as SqlClient from "effect/sql/SqlClient"; | ||
|
|
||
| import { runMigrations } from "../Migrations.ts"; | ||
|
|
||
| const layer = it.layer(NodeSqliteClient.layer({ filename: ":memory:" })); | ||
|
|
||
| layer("067_OrchestrationSlowQueryIndexes", (it) => { | ||
| it.effect("creates the indexes and the planner uses them for the slow queries", () => | ||
| Effect.gen(function* () { | ||
| const sql = yield* SqlClient.SqlClient; | ||
| yield* runMigrations({ toMigrationInclusive: 66 }); | ||
| yield* sql` | ||
| INSERT INTO orchestration_v2_projection_turn_items ( | ||
| turn_item_id, thread_id, run_id, ordinal, type, status, payload_json, updated_at | ||
| ) VALUES ( | ||
| 'item-1', 'thread-1', NULL, 1, 'user_message', 'completed', | ||
| '{"messageId":"message-1"}', '2026-01-01' | ||
| ) | ||
| `; | ||
| const beforeMessages = yield* sql` | ||
| SELECT json_extract(payload_json, '$.messageId') AS message_id, MIN(ordinal) AS ordinal | ||
| FROM orchestration_v2_projection_turn_items | ||
| WHERE thread_id = 'thread-1' AND type IN ('user_message', 'assistant_message') | ||
| GROUP BY json_extract(payload_json, '$.messageId') | ||
| `; | ||
| const beforeRunning = yield* sql<{ readonly detail: string }>` | ||
| EXPLAIN QUERY PLAN | ||
| SELECT thread_id FROM orchestration_v2_projection_runs WHERE status = 'running' | ||
| `; | ||
| assert.isFalse( | ||
| beforeRunning.some((row) => row.detail.includes("runs_recovery_idx")), | ||
| beforeRunning.map((row) => row.detail).join("\n"), | ||
| ); | ||
| yield* runMigrations({ toMigrationInclusive: 67 }); | ||
| assert.deepEqual(yield* runMigrations(), []); | ||
|
|
||
| const afterRunning = yield* sql<{ readonly detail: string }>` | ||
| EXPLAIN QUERY PLAN | ||
| SELECT thread_id FROM orchestration_v2_projection_runs WHERE status = 'running' | ||
| `; | ||
| assert.isTrue( | ||
| afterRunning.some((row) => row.detail.includes("runs_running_idx")), | ||
| afterRunning.map((row) => row.detail).join("\n"), | ||
| ); | ||
| const recoveryPlan = yield* sql<{ readonly detail: string }>` | ||
| EXPLAIN QUERY PLAN | ||
| SELECT thread_id FROM orchestration_v2_projection_runs | ||
| WHERE thread_id = 'thread-1' | ||
| AND status IN ('queued', 'preparing', 'starting', 'running', 'waiting') | ||
| `; | ||
| assert.isTrue( | ||
| recoveryPlan.some((row) => row.detail.includes("runs_recovery_idx")), | ||
| recoveryPlan.map((row) => row.detail).join("\n"), | ||
| ); | ||
|
|
||
| const rows = yield* sql<{ readonly name: string }>` | ||
| SELECT name FROM sqlite_master WHERE type = 'index' | ||
| `; | ||
| const indexes = new Set(rows.map((row) => row.name)); | ||
| for (const name of [ | ||
| "orchestration_v2_projection_turn_items_thread_type_idx", | ||
| "orchestration_v2_projection_turn_items_thread_message_idx", | ||
| "orchestration_v2_projection_turn_items_run_status_idx", | ||
| "orchestration_v2_projection_runs_running_idx", | ||
| "orchestration_v2_projection_runs_user_message_idx", | ||
| "orchestration_v2_projection_provider_turns_thread_completed_idx", | ||
| "idx_orchestration_events_aggregate_version_sequence", | ||
| ]) { | ||
| assert.isTrue(indexes.has(name), name); | ||
| } | ||
|
|
||
| const afterMessages = yield* sql` | ||
| SELECT json_extract(payload_json, '$.messageId') AS message_id, MIN(ordinal) AS ordinal | ||
| FROM orchestration_v2_projection_turn_items | ||
| WHERE thread_id = 'thread-1' AND type IN ('user_message', 'assistant_message') | ||
| GROUP BY json_extract(payload_json, '$.messageId') | ||
| `; | ||
| assert.deepEqual(afterMessages, beforeMessages); | ||
| const messagePlan = yield* sql<{ readonly detail: string }>` | ||
| EXPLAIN QUERY PLAN | ||
| SELECT json_extract(payload_json, '$.messageId'), MIN(ordinal) | ||
| FROM orchestration_v2_projection_turn_items | ||
| WHERE thread_id = 'thread-1' AND type IN ('user_message', 'assistant_message') | ||
| GROUP BY json_extract(payload_json, '$.messageId') | ||
| `; | ||
| assert.isTrue( | ||
| messagePlan.some((row) => | ||
| row.detail.includes("orchestration_v2_projection_turn_items_thread_message_idx"), | ||
| ), | ||
| messagePlan.map((row) => row.detail).join("\n"), | ||
| ); | ||
|
|
||
| const runPlan = yield* sql<{ readonly detail: string }>` | ||
| EXPLAIN QUERY PLAN | ||
| SELECT thread_id FROM orchestration_v2_projection_runs | ||
| WHERE json_extract(payload_json, '$.userMessageId') = 'message-1' | ||
| `; | ||
| assert.isTrue( | ||
| runPlan.some((row) => | ||
| row.detail.includes("orchestration_v2_projection_runs_user_message_idx"), | ||
| ), | ||
| runPlan.map((row) => row.detail).join("\n"), | ||
| ); | ||
| }), | ||
| ); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| import * as Effect from "effect/Effect"; | ||
| import * as SqlClient from "effect/sql/SqlClient"; | ||
|
|
||
| // Each expression index repeats the json_extract text of the query it serves. | ||
| // SQLite only uses an expression index when the query expression matches it. | ||
| export default Effect.gen(function* () { | ||
| const sql = yield* SqlClient.SqlClient; | ||
|
|
||
| yield* sql` | ||
| CREATE INDEX IF NOT EXISTS orchestration_v2_projection_turn_items_thread_type_idx | ||
| ON orchestration_v2_projection_turn_items(thread_id, type) | ||
| `; | ||
| yield* sql` | ||
| CREATE INDEX IF NOT EXISTS orchestration_v2_projection_turn_items_thread_message_idx | ||
| ON orchestration_v2_projection_turn_items(thread_id, json_extract(payload_json, '$.messageId')) | ||
| WHERE type IN ('user_message', 'assistant_message') | ||
| `; | ||
| yield* sql` | ||
| CREATE INDEX IF NOT EXISTS orchestration_v2_projection_turn_items_run_status_idx | ||
| ON orchestration_v2_projection_turn_items(run_id, status) | ||
| `; | ||
| yield* sql` | ||
| CREATE INDEX IF NOT EXISTS orchestration_v2_projection_runs_running_idx | ||
| ON orchestration_v2_projection_runs(thread_id) | ||
| WHERE status = 'running' | ||
| `; | ||
| yield* sql` | ||
| CREATE INDEX IF NOT EXISTS orchestration_v2_projection_runs_user_message_idx | ||
| ON orchestration_v2_projection_runs(json_extract(payload_json, '$.userMessageId')) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When upgrading a database that contains a malformed run projection, this statement evaluates Useful? React with 👍 / 👎. |
||
| `; | ||
| yield* sql` | ||
| CREATE INDEX IF NOT EXISTS orchestration_v2_projection_provider_turns_thread_completed_idx | ||
| ON orchestration_v2_projection_provider_turns(thread_id, completed_at DESC) | ||
|
Comment on lines
+32
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
For normal provider-turn updates, this adds a second B-tree with the same useful prefix as the existing AGENTS.md reference: AGENTS.md:L15-L17 Useful? React with 👍 / 👎. |
||
| `; | ||
| yield* sql` | ||
| CREATE INDEX IF NOT EXISTS idx_orchestration_events_aggregate_version_sequence | ||
| ON orchestration_events(aggregate_kind, application_event_version, sequence) | ||
| `; | ||
| }); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This planner query does not occur in production: a repo-wide search finds the only two
$.userMessageIdSQL reads atProjectionStore.ts:4234-4235and5140-5144, and both restrict the run byrun_idbefore extracting the field, so the primary-key lookup wins. Consequently this test blesses an expression index that everyrun.created/run.updatedupsert must maintain without accelerating a real read; exercise an actual lookup and drop or reshape the index.AGENTS.md reference: AGENTS.md:L98-L101
Useful? React with 👍 / 👎.