Skip to content

feat: workspace fetch optimization + parent tasks fetching#1207

Open
priosshrsth wants to merge 3 commits intofeature/c1-optimizationfrom
workspace-fetch-optimization
Open

feat: workspace fetch optimization + parent tasks fetching#1207
priosshrsth wants to merge 3 commits intofeature/c1-optimizationfrom
workspace-fetch-optimization

Conversation

@priosshrsth
Copy link
Copy Markdown
Collaborator

@priosshrsth priosshrsth commented May 6, 2026

Summary

resolves OUT-3705 OUT-3705: Optimize workspace to be fetched once per session

  • Fetch workspace on client side and once per session
  • Update rest of the codebase to use portalUrl from store rather than props.
  • For subtasks we get the details of both tasks with single query instead of multiple
  • resolves OUT-3695 OUT-3695: Remove customFields from clients response

Test plan

  • App boots, workspace data appears in redux after first paint
  • Detail page: sidebar + header breadcrumbs render correctly with portalUrl-dependent CTAs
  • Home / client board: app bridges (CTAs, breadcrumbs) work
  • Manage templates list + detail: app bridges work
  • First-paint flash on portalUrl-dependent UI is not visually disruptive
  • Subtask detail page: ancestor breadcrumbs render in correct root → leaf order (parent tasks ordering fix)
2026-05-07.15-11-44.mov

🤖 Generated with Claude Code

priosshrsth and others added 2 commits May 6, 2026 15:02
Add a layout-level WorkspaceFetcher that uses SWR to populate
authDetails.workspace from /api/workspace on the client. SSR pages
((home), detail, client, manage-templates, manage-templates/[id]) no
longer block on copilot.getWorkspace() per request — they let the
Redux store hydrate from the cached client fetch (60s deduping).

Server-side route uses React cache() via getMemoizedWorkspace for
per-request memoization. Workspace consumers (Sidebar, AppBridges,
HeaderBreadcrumbs, TaskBoard) now read portalUrl from the store via
selectAuthDetails instead of taking it as a prop.

Add tsc script (tsc --noEmit) to package.json for type-only checks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 6, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
tasks-app Ready Ready Preview, Comment May 7, 2026 5:57am

Request Review

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 6, 2026

Greptile Summary

This PR delivers two optimizations targeting the feature/c1-optimization branch: it replaces the per-parent findFirstOrThrow fan-out in getTraversalPath with a single findMany + client-side reordering, and it moves workspace fetching from per-page SSR calls into a single SWR-backed client component (WorkspaceFetcher) mounted in the root layout that writes to the redux store.

  • Parent-task fetch: N serial DB queries → 1 findMany; order is preserved via a Map indexed by the original parentIds array; missing IDs throw EXPECTATION_FAILED with the offending ID surfaced.
  • Workspace fetch: Five SSR pages drop their getWorkspace calls and workspace prop drilling; all AppBridge hooks and layout components now read portalUrl from selectAuthDetails; first-paint undefined is tolerated because every AppBridge hook already guards on portalUrl in its effect deps.
  • customFields in ClientResponseSchema: field is commented out rather than removed, silently dropping it from the inferred TypeScript type with no type-checker warning at callsites.

Confidence Score: 5/5

Safe to merge — all changed paths are well-guarded and the optimizations are straightforward.

The parent-task query consolidation is logically correct: order is explicitly re-applied from parentIds after the findMany, and missing entries throw with a clear error. The workspace SWR lift is a well-scoped refactor with no broken contracts — every AppBridge hook already handles an undefined portalUrl for one tick. The only new code concern is a dead parentTasksStartedAt variable that will generate a lint warning but has no runtime impact.

No files require special attention beyond the unused variable in tasks.service.ts and the pre-existing customFields comment-out in types/common.ts.

Important Files Changed

Filename Overview
src/app/api/tasks/tasks.service.ts Replaces N serial findFirstOrThrow calls with a single findMany + client-side reordering; parentTasksStartedAt is declared but never used (dead variable).
src/app/_fetchers/WorkspaceFetcher.tsx New client component that fetches workspace once via SWR (60s dedup) when token is present and redux store has no workspace yet, then dispatches to redux.
src/app/api/workspace/route.ts New authenticated GET handler wrapping getMemoizedWorkspace; correctly uses withErrorHandler and authenticate.
src/utils/copilotMemo.ts Wraps copilot.getWorkspace() in React cache() — effective within RSC render trees but not across API route invocations (already flagged in prior review).
src/types/common.ts customFields field commented out of ClientResponseSchema, silently dropping it from the inferred ClientResponse type (already flagged in prior review).
src/app/layout.tsx Mounts WorkspaceFetcher once in the root layout inside a Suspense boundary — correct usage of useSearchParams in layout context.

Reviews (2): Last reviewed commit: "fix traversal" | Re-trigger Greptile

@priosshrsth priosshrsth self-assigned this May 7, 2026
@priosshrsth priosshrsth marked this pull request as draft May 7, 2026 05:15
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 7, 2026

Deployment failed with the following error:

Deploying Serverless Functions to multiple regions is restricted to the Pro and Enterprise plans.

Learn More: https://vercel.link/multiple-function-regions

@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 7, 2026

) as Promise<AncestorTaskResponse>[],
)
const parentIds = getIdsFromLtreePath(taskWithPath.path)
const parentTasksStartedAt = performance.now()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this necessary to be in prod?

Comment thread src/types/common.ts
.nullable(),
// customFields: z
// .record(z.string(), z.union([z.string().nullable(), z.array(z.string()).nullable(), z.object({}).nullable()]))
// .nullable(),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets remove the commented code or add an extra comment on why we commented this out.

@arpandhakal
Copy link
Copy Markdown
Collaborator

Lets consider testing in the platform itself in a custom app. That way we can ensure everything works including the app bridge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants