perf(parcel-sync): make GisFeature groupBy opt-in on /api/eterra/uats

The groupBy query scanning the entire GisFeature table (~30k+ rows)
was blocking the UAT list API for 25+ seconds on every page load.
Feature counts are now opt-in via ?features=true query param.
Default response is instant (just GisUat table, no joins).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
AI Assistant
2026-03-23 12:44:09 +02:00
parent 2886703d0f
commit ad4c72f527
+20 -18
View File
@@ -119,31 +119,33 @@ function unwrapArray(data: any): any[] {
/* No eTerra credentials needed — instant response. */
/* ------------------------------------------------------------------ */
export async function GET() {
export async function GET(req: Request) {
try {
// Fetch UATs and local feature counts in parallel
const [rows, featureCounts] = await Promise.all([
prisma.gisUat.findMany({ orderBy: { name: "asc" } }),
prisma.gisFeature
.groupBy({
by: ["siruta"],
_count: { id: true },
})
.then((groups) => {
const map = new Map<string, number>();
for (const g of groups) {
map.set(g.siruta, g._count.id);
}
return map;
}),
]);
const url = new URL(req.url);
const withFeatures = url.searchParams.get("features") === "true";
const rows = await prisma.gisUat.findMany({ orderBy: { name: "asc" } });
// Feature counts are expensive (scans entire GisFeature table)
// Only include when explicitly requested
let featureCounts: Map<string, number> | null = null;
if (withFeatures) {
const groups = await prisma.gisFeature.groupBy({
by: ["siruta"],
_count: { id: true },
});
featureCounts = new Map<string, number>();
for (const g of groups) {
featureCounts.set(g.siruta, g._count.id);
}
}
const uats: UatResponse[] = rows.map((r) => ({
siruta: r.siruta,
name: r.name,
county: r.county ?? "",
workspacePk: r.workspacePk ?? 0,
localFeatures: featureCounts.get(r.siruta) ?? 0,
localFeatures: featureCounts?.get(r.siruta) ?? 0,
}));
// Populate in-memory workspace cache for search route