WFDASH-WEBAPP/scripts/perf/dashboard-live-timing.ts

94 lines
4.1 KiB
TypeScript
Raw Normal View History

// Quick live timing of the dashboard's PocketBase calls.
import { performance } from "node:perf_hooks";
import PocketBase from "pocketbase";
async function main() {
const url = process.env.NEXT_PUBLIC_POCKETBASE_URL || "http://127.0.0.1:8090";
const email = process.env.PB_ADMIN_EMAIL;
const password = process.env.PB_ADMIN_PASSWORD;
if (!email || !password) {
console.error("Missing PB_ADMIN_EMAIL / PB_ADMIN_PASSWORD");
process.exit(1);
}
const pb = new PocketBase(url);
await pb.collection("_superusers").authWithPassword(email, password);
console.log("PB:", url);
const twelveWeeksAgo = new Date(Date.now() - 84 * 24 * 60 * 60 * 1000).toISOString();
const startOfMonth = new Date(new Date().getFullYear(), new Date().getMonth(), 1).toISOString();
type Timed = { label: string; ms: number; count?: number };
const results: Timed[] = [];
const measure = async (label: string, fn: () => Promise<{ items?: unknown[]; totalItems?: number } | unknown[]>) => {
const a = performance.now();
try {
const r = (await fn()) as { items?: unknown[]; totalItems?: number } | unknown[];
const b = performance.now();
const count = Array.isArray(r)
? r.length
: Array.isArray(r?.items)
? (r.items as unknown[]).length
: r?.totalItems;
results.push({ label, ms: b - a, count });
} catch (e) {
const b = performance.now();
console.log(`!! ${label} ERR ${(e as { message?: string })?.message ?? ""}`);
results.push({ label, ms: b - a, count: -1 });
}
};
console.log("\n--- Sequential timing of each dashboard call ---");
await measure("customers total count", () => pb.collection("customers").getList(1, 1));
await measure("quotes active count", () =>
pb.collection("quotes").getList(1, 1, {
filter: '(status = "new" || status = "claimed" || status = "processed" || status = "emailed" || status = "approval_pending") && is_template != true',
})
);
await measure("orders this month count", () =>
pb.collection("orders").getList(1, 1, { filter: `created >= "${startOfMonth}"` })
);
await measure("follow-ups getFullList", () =>
pb.collection("quotes").getFullList({
filter: `follow_up_due != "" && follow_up_due <= "${new Date().toISOString()}" && status != "complete" && status != "cancelled" && status != "rejected" && is_template != true`,
sort: "follow_up_due",
expand: "customer",
})
);
await measure("quotes 500 + customer expand", () =>
pb.collection("quotes").getList(1, 500, { filter: "is_template != true", expand: "customer" })
);
await measure("orders 12w 500", () =>
pb.collection("orders").getList(1, 500, { sort: "-created", filter: `created >= "${twelveWeeksAgo}"` })
);
await measure("customers 12w 500", () =>
pb.collection("customers").getList(1, 500, { sort: "-created", filter: `created >= "${twelveWeeksAgo}"` })
);
await measure("order_items month 500", () =>
pb.collection("order_items").getList(1, 500, { filter: `created >= "${startOfMonth}"` })
);
await measure("order_items 12w 500", () =>
pb.collection("order_items").getList(1, 500, { filter: `created >= "${twelveWeeksAgo}"` })
);
await measure("quotes 12w 500", () =>
pb.collection("quotes").getList(1, 500, { filter: `created >= "${twelveWeeksAgo}" && is_template != true` })
);
await measure("stock_items FULL LIST", () => pb.collection("stock_items").getFullList());
console.log("\nlabel ms rows/total");
console.log("------------------------------------------------------ -------");
let totalMs = 0;
for (const r of results) {
totalMs += r.ms;
console.log(`${r.label.padEnd(45)} ${r.ms.toFixed(0).padStart(6)} ${String(r.count ?? "-").padStart(8)}`);
}
console.log("------------------------------------------------------ -------");
console.log(`TOTAL sequential: ${totalMs.toFixed(0).padStart(6)} ms`);
console.log("(In the page, Promise.all parallelises these; real wall-clock ≈ slowest single call.)");
}
main().catch((e) => {
console.error(e);
process.exit(1);
});