Description
In analytics.controller.js, getGlobalStats iterates over every project in a for...of loop and sequentially calls await getConnection(project._id) + conn.collection('users').countDocuments(). For a developer with many projects, this opens N sequential per-project MongoDB connections synchronously before returning — reported in issue #259 but the existing fix is a different bug. The issue is that even after awaiting each connection, there is no concurrency: each connection+count waits for the previous one, making the dashboard homepage extremely slow under real load.
Steps to Reproduce
- Create 10+ projects with user data.
- Load the dashboard homepage (triggers GET /api/analytics/global).
- Observe the response time scales linearly with project count.
Expected Behaviour
All getConnection + countDocuments calls should run in parallel using Promise.all(projects.map(...)), reducing response time from O(N×latency) to O(1×max_latency).
Actual Behaviour
Each project's user count is fetched sequentially. With 10 projects and 50ms latency per DB call, the endpoint takes 500ms+ to respond.
Description
In analytics.controller.js, getGlobalStats iterates over every project in a for...of loop and sequentially calls await getConnection(project._id) + conn.collection('users').countDocuments(). For a developer with many projects, this opens N sequential per-project MongoDB connections synchronously before returning — reported in issue #259 but the existing fix is a different bug. The issue is that even after awaiting each connection, there is no concurrency: each connection+count waits for the previous one, making the dashboard homepage extremely slow under real load.
Steps to Reproduce
Expected Behaviour
All getConnection + countDocuments calls should run in parallel using Promise.all(projects.map(...)), reducing response time from O(N×latency) to O(1×max_latency).
Actual Behaviour
Each project's user count is fetched sequentially. With 10 projects and 50ms latency per DB call, the endpoint takes 500ms+ to respond.