Describe the bug
In apps/dashboard-api/src/controllers/analytics.controller.js, getGlobalStats counts users across all projects using a sequential for loop that opens a separate MongoDB connection per project:
const projects = await Project.find({ owner: user_id }).select('_id').lean();
let totalUsers = 0;
for (const project of projects) {
try {
const conn = await getConnection(project._id.toString());
const userCount = await conn.collection('users').countDocuments();
totalUsers += userCount;
} catch (err) { ... }
}
For a developer with 50 projects, this makes 50 sequential network round-trips to potentially 50 different MongoDB instances. The response time scales linearly with project count, and the connection pool is exhausted for the duration of each request.
To Reproduce
- Create a developer account with 20+ projects.
- Navigate to the analytics dashboard.
- Observe that
GET /api/dashboard/stats takes several seconds to respond, proportional to the number of projects.
Expected behavior
For internal databases (not external), user counts should be aggregated in a single batch operation rather than N sequential calls. At minimum, the loop should use Promise.all for concurrent execution:
const userCounts = await Promise.all(
projects.map(async (project) => {
try {
const conn = await getConnection(project._id.toString());
return conn.collection('users').countDocuments();
} catch { return 0; }
})
);
totalUsers = userCounts.reduce((sum, c) => sum + c, 0);
Additional context
File: apps/dashboard-api/src/controllers/analytics.controller.js, function: getGlobalStats
Labels: bug, nsoc26, level2
Describe the bug
In
apps/dashboard-api/src/controllers/analytics.controller.js,getGlobalStatscounts users across all projects using a sequentialforloop that opens a separate MongoDB connection per project:For a developer with 50 projects, this makes 50 sequential network round-trips to potentially 50 different MongoDB instances. The response time scales linearly with project count, and the connection pool is exhausted for the duration of each request.
To Reproduce
GET /api/dashboard/statstakes several seconds to respond, proportional to the number of projects.Expected behavior
For internal databases (not external), user counts should be aggregated in a single batch operation rather than N sequential calls. At minimum, the loop should use
Promise.allfor concurrent execution:Additional context
File:
apps/dashboard-api/src/controllers/analytics.controller.js, function:getGlobalStatsLabels:
bug,nsoc26,level2