Optimize frontend data fetching with parallelization#274
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
Optimizes frontend perceived performance and resilience by parallelizing multiple independent data fetches and tolerating partial failures (via Promise.allSettled) across scheduling, runner, AI planning, and settings flows.
Changes:
- Parallelizes multi-source task loading (per-project + quick tasks) and continues on partial failures with structured logging.
- Preloads AI Planning data when an API key is already validated, using partial-failure tolerant loading.
- Reuses React Query cache for goal/project lookups in Runner session context, and parallelizes Supabase auth context reads in Settings.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| apps/web/src/hooks/use-runner.ts | Reuses React Query cache for goal/project details before falling back to API calls. |
| apps/web/src/hooks/use-project-page-state.ts | Enables project progress query based on projectId directly. |
| apps/web/src/components/runner/manual-task-select-dialog.tsx | Fetches tasks across all projects using Promise.allSettled and logs per-project failures. |
| apps/web/src/app/settings/page.tsx | Adds shared getAuthContext() to fetch user+session in parallel and reuses it across handlers. |
| apps/web/src/app/scheduling/page.tsx | Parallelizes all-project tasks and quick tasks loading; continues with partial results when some fetches fail. |
| apps/web/src/app/ai-planning/page.tsx | Adds preloadAiPlanningData to prefetch schedules + recurring tasks after API key validation using allSettled. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| projectTaskResults.forEach((result, index) => { | ||
| if (result.status === 'fulfilled') { | ||
| allTasks.push(...(result.value as TaskInfo[])); | ||
| } else { | ||
| logger.error( | ||
| `Failed to load tasks for project ${projects[index]?.id}`, | ||
| result.reason instanceof Error ? result.reason : new Error(String(result.reason)) | ||
| ); |
There was a problem hiding this comment.
The per-project failure log uses projects[index]?.id, which can become inaccurate if the projects state changes between starting the requests and handling the settled results. Capture the project id alongside each promise (or close over project.id) and use that captured id for error logs to ensure correct attribution.
| const taskPromises = projects.map((project) => | ||
| tasksApi.getByProject(project.id, 0, 100) | ||
| ); | ||
| const taskResults = await Promise.all(taskPromises); | ||
| return taskResults.flat(); | ||
| const taskResults = await Promise.allSettled(taskPromises); | ||
| return taskResults.flatMap((result, index) => { | ||
| if (result.status === 'fulfilled') { | ||
| return result.value; | ||
| } | ||
|
|
||
| log.error( | ||
| `Failed to load tasks for project ${projects[index]?.id}`, | ||
| result.reason instanceof Error ? result.reason : new Error(String(result.reason)), | ||
| { component: 'ManualTaskSelectDialog' } | ||
| ); |
There was a problem hiding this comment.
In the all projects fetch, the error log uses projects[index]?.id. If the projects list changes while the query is in-flight, this can log the wrong project id. Consider capturing { projectId, promise } (or closing over project.id) so the log always references the project tied to that request.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 68a97f0c27
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
apps/web/src/app/settings/page.tsx
Outdated
| const [{ data: { user } }, { data: { session } }] = await Promise.all([ | ||
| supabase.auth.getUser(), | ||
| supabase.auth.getSession(), |
There was a problem hiding this comment.
Avoid parallel auth calls in getAuthContext
Running supabase.auth.getUser() and supabase.auth.getSession() concurrently can produce an inconsistent auth snapshot when a token refresh is in flight (common after access-token expiry): getSession() may return a stale/empty session while getUser() succeeds, causing the repeated !session?.access_token checks in this page to redirect valid users to /login. Keeping these reads ordered prevents this race.
Useful? React with 👍 / 👎.
PR Title
Optimize frontend data fetching with parallelization
Summary
Improve frontend UX/performance by parallelizing multiple independent data fetches and reducing sequential bottlenecks in UI workflows.
Background
The user asked to continue frontend UX optimization for data retrieval and overall perceived responsiveness.
Changes
apps/web/src/app/scheduling/page.tsxPromise.allSettled.apps/web/src/app/ai-planning/page.tsxpreloadAiPlanningDataand preload weekly schedules + recurring tasks when API key is already validated.Promise.allSettledto allow partial success and avoid blocking UI.apps/web/src/app/settings/page.tsxgetAuthContext()helper usingPromise.allforsupabase.auth.getUser()+supabase.auth.getSession().apps/web/src/components/runner/manual-task-select-dialog.tsxPromise.allSettled.apps/web/src/hooks/use-runner.tsapps/web/src/hooks/use-project-page-state.tsprojectIddirectly (enabled whenprojectIdexists).Technical Notes
Testing
pnpm --filter web type-check(pass)feat/frontend-parallel-fetch-optimizationCommit
68a97f0 Optimize frontend data fetching with parallelizationPR Checklist
type-checkpassed)Notes
pre-commithooks may need local env write permissions.git push/gh pr createcurrently failed in this environment due to GitHub network/DNS restrictions.