Description
In backend/src/db/repositories/campaigns.ts, the getStats() function uses Promise.all() with three Prisma queries, but has no error handling for partial failures:
export async function getStats() {
const [total, active, agg] = await Promise.all([
prisma.campaign.count(),
prisma.campaign.count({ where: { status: 'Active' } }),
prisma.campaign.aggregate({
_sum: { impressions: true, clicks: true, spentStroops: true },
}),
]);
// ...
}
Problem
If any one of the three queries fails (e.g., temporary connection issue, table lock), Promise.all() rejects immediately and discards results from successful queries. The route handler catches this, but the user gets a generic 500 error when partial data could have been returned.
Impact
- Transient database issues cause the entire stats endpoint to fail
- No degraded/partial response — it's all or nothing
- The aggregate query is the most expensive and likely to timeout under load
Suggested Fix
Use Promise.allSettled() with fallback values:
export async function getStats() {
const [totalResult, activeResult, aggResult] = await Promise.allSettled([
prisma.campaign.count(),
prisma.campaign.count({ where: { status: 'Active' } }),
prisma.campaign.aggregate({
_sum: { impressions: true, clicks: true, spentStroops: true },
}),
]);
return {
total_campaigns: totalResult.status === 'fulfilled' ? totalResult.value : null,
active_campaigns: activeResult.status === 'fulfilled' ? activeResult.value : null,
total_impressions: aggResult.status === 'fulfilled' ? aggResult.value._sum.impressions ?? 0 : null,
// ...
};
}
File
backend/src/db/repositories/campaigns.ts — Lines 17-23
Description
In
backend/src/db/repositories/campaigns.ts, thegetStats()function usesPromise.all()with three Prisma queries, but has no error handling for partial failures:Problem
If any one of the three queries fails (e.g., temporary connection issue, table lock),
Promise.all()rejects immediately and discards results from successful queries. The route handler catches this, but the user gets a generic 500 error when partial data could have been returned.Impact
Suggested Fix
Use
Promise.allSettled()with fallback values:File
backend/src/db/repositories/campaigns.ts— Lines 17-23