perf(db): index a workspace's live files in upload order

Merged
WA
1d ago
+31515-4

Summary

  • Adds workspace_files_workspace_active_uploaded_idx (workspace_id, uploaded_at, id) with the predicate the other live workspace-file indexes share (deleted_at IS NULL AND context = 'workspace' AND workspace_id IS NOT NULL), built concurrently with the replay-safe recovery pattern
  • No index served the file list's filter in upload order, so the planner combined the context and search-keyset indexes, matching every workspace's live files, filtered to one workspace on the heap and sorted, even for a bounded read; the full list and the SSR seed now read the workspace's rows in index order with no sort (the uploadedAt keyset pages still order on date_trunc('milliseconds', uploaded_at) and move to this order in the pagination PR, which aligns their keyset with the plain column)
  • listWorkspaceFiles orders by uploaded_at, id, so ties come back in a stable order across reads
  • The key stays narrow (no name/key columns) so an entry can never approach the btree size limit and fail a write
  • Marks workspace_files_workspace_active_keyset_idx for retirement once its scans stop after deploy
  • Adds @sim/db/testing/explain (explainCaptured), a test helper that EXPLAINs the SQL a call actually sends, with its bound parameters

Type of Change

  • Other: performance

Testing

  • New file-list.integration.ts: active, archived and all scopes list exactly their rows in (uploaded_at, id) order (archived and all fail without the tiebreak); the full list and the SSR seed's bounded read plan on the new index with no Sort (fails with the index dropped)
  • Plans verified on a production-shaped local copy under stale statistics: the SSR seed drops from a whole-workspace scan and sort to an ordered index scan; name-sorted pages, key/name/id lookups and the archived list keep their plans
  • Push- and migrate-provisioned databases build the identical index; replay rebuilds an invalid index and keeps a valid one
  • bun run check:migrations origin/staging, drizzle-kit generate (no changes), bun run lint, bun run check:audits, bun run type-check

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing (new tests pass the test-audit authoring gate)
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)