mirror of
https://github.com/willchen96/mike.git
synced 2026-07-24 23:41:04 +02:00
fix: batch directory-modal project fetch instead of N+1 getProject burst
Every directory picker (AddDocumentsModal, UseWorkflowModal, the assistant
project selector) loads its "Projects" tab through useDirectoryData, which
fired one GET /projects/:id for EVERY existing project the moment the modal
opened. Each of those requests costs an auth verification against GoTrue
plus ~6 PostgREST queries, so an account with N projects produced an
~8xN-request burst on the Supabase gateway per modal open.
Under that burst the gateway genuinely falls over: measured locally against
the Supabase CLI stack, overlapping modal-open storms drove GoTrue into
Postgres connection exhaustion ("failed to connect ... context deadline
exceeded") and produced 467x 500 + 641x 504 on /auth/v1/user in a single
run — surfacing to users as failed project creates/loads, and to the e2e
suite as the intermittent Kong 502s its specs currently retry around.
Fix: GET /projects now accepts ?include=documents and returns each
project's documents from one batched query (same attach helpers as
GET /projects/:id, run once across all documents), and useDirectoryData
uses it. A modal open is now 1 API request and a fixed number of DB
queries regardless of project count. After the change the same storm
harness produced zero 5xx and zero auth failures.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
0843e2909a
commit
36cddb2566
3 changed files with 58 additions and 17 deletions
|
|
@ -152,9 +152,16 @@ async function attachChatCreatorLabels(
|
|||
}
|
||||
|
||||
// GET /projects
|
||||
// Pass ?include=documents to also receive each project's documents in the
|
||||
// same response. The directory pickers (useDirectoryData) previously fanned
|
||||
// out one GET /projects/:id per project to obtain those documents; with N
|
||||
// projects that burst — auth check plus several DB queries per request —
|
||||
// could overwhelm the Supabase gateway. Batching keeps it at one request
|
||||
// and a fixed number of queries regardless of project count.
|
||||
projectsRouter.get("/", requireAuth, async (req, res) => {
|
||||
const userId = res.locals.userId as string;
|
||||
const userEmail = res.locals.userEmail as string | undefined;
|
||||
const includeDocuments = req.query.include === "documents";
|
||||
const db = createServerSupabase();
|
||||
|
||||
const { data, error } = await db.rpc("get_projects_overview", {
|
||||
|
|
@ -163,7 +170,45 @@ projectsRouter.get("/", requireAuth, async (req, res) => {
|
|||
});
|
||||
if (error) return void res.status(500).json({ detail: error.message });
|
||||
|
||||
res.json(data ?? []);
|
||||
const projects = (data ?? []) as { id: string }[];
|
||||
if (!includeDocuments || projects.length === 0) {
|
||||
return void res.json(projects);
|
||||
}
|
||||
|
||||
const { data: docs, error: docsError } = await db
|
||||
.from("documents")
|
||||
.select("*")
|
||||
.in(
|
||||
"project_id",
|
||||
projects.map((p) => p.id),
|
||||
)
|
||||
.order("created_at", { ascending: true });
|
||||
if (docsError)
|
||||
return void res.status(500).json({ detail: docsError.message });
|
||||
|
||||
const docsTyped = (docs ?? []) as unknown as {
|
||||
id: string;
|
||||
project_id?: string | null;
|
||||
user_id?: string | null;
|
||||
current_version_id?: string | null;
|
||||
}[];
|
||||
await attachLatestVersionNumbers(db, docsTyped);
|
||||
await attachActiveVersionPaths(db, docsTyped);
|
||||
await attachDocumentOwnerLabels(db, docsTyped);
|
||||
|
||||
const docsByProject = new Map<string, typeof docsTyped>();
|
||||
for (const doc of docsTyped) {
|
||||
if (!doc.project_id) continue;
|
||||
const bucket = docsByProject.get(doc.project_id);
|
||||
if (bucket) bucket.push(doc);
|
||||
else docsByProject.set(doc.project_id, [doc]);
|
||||
}
|
||||
res.json(
|
||||
projects.map((p) => ({
|
||||
...p,
|
||||
documents: docsByProject.get(p.id) ?? [],
|
||||
})),
|
||||
);
|
||||
});
|
||||
|
||||
// POST /projects
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue