Skip to content

improvement(react-query): codebase-wide audit — server-state hooks, webhook coherence, resume migration#5024

Merged
waleedlatif1 merged 2 commits into
stagingfrom
rq-audit-sweep
Jun 13, 2026
Merged

improvement(react-query): codebase-wide audit — server-state hooks, webhook coherence, resume migration#5024
waleedlatif1 merged 2 commits into
stagingfrom
rq-audit-sweep

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Codebase-wide React Query audit (multi-agent sweep) + fixes across ~37 server-state hooks: added explicit staleTime, forwarded { signal } into queryFn, reshaped key factories to the hierarchical all/lists()/details() form, narrowed broad invalidations to targeted prefixes, and made onSettled return the invalidateQueries promise so mutations stay pending through refetch
  • Fixed a HIGH webhook cache-coherence bug: reactivateWebhook PATCHed without invalidating the shared webhookKeys cache, so useWebhookManagement served stale isActive for up to 60s. Added useReactivateWebhook mutation and refactored use-webhook-info.ts off its duplicate fetch-into-useState onto the shared useWebhookQuery
  • Migrated resume-page-client.tsx off raw fetch + useState onto React Query: new getPauseContextDetailContract, new resume-execution.ts hooks (2 useQuery + 1 useMutation), collapsed two byte-identical GET paths into one query + effect-on-data, optimistic updates via setQueryData, invalidation-driven reconciliation
  • Confirmed false-positives (no change needed): 8 of 9 raw-fetch candidates were already on React Query or are legitimate boundary exceptions (SSE streaming, one-time socket token, static-asset seed)

Type of Change

  • Bug fix / improvement

Testing

  • bunx tsc --noEmit clean (only a pre-existing unrelated tailwind.config.ts error)
  • bun run check:api-validation passed
  • Adversarial multi-agent review of the full diff; all 6 confirmed findings fixed (subscription-upgrade invoice invalidation, falsy resume-input parity, webhook reset-when-unconfigured gating, refresh auto-select parity, lint placement)
  • Resume flow is behavior-preserving vs origin/staging; recommend a manual pause/resume smoke test before merge

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel

vercel Bot commented Jun 13, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview, Comment Jun 13, 2026 5:08pm

Request Review

@cursor

cursor Bot commented Jun 13, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Wide hook and cache-invalidation changes plus a refactored pause/resume UI; webhook and resume paths are execution-adjacent though intended behavior-preserving.

Overview
Introduces check:react-query (new script + CI step + docs) to enforce staleTime, signal in queryFn, colocated key factories, and all root keys in hooks/queries/**.

Runs a broad React Query cleanup: hierarchical *Keys factories, AbortSignal forwarding (e.g. admin users), and mutations that return invalidations from onSettled so pending state tracks refetches. Subscription/schedule invalidations are narrowed or expanded where lists were stale.

Resume UI moves off local fetch/useState to resume-execution hooks; adds getPauseContextDetailContract and wires the GET route to it. Resume submit still uses annotated raw POST fetch; cache updates use setQueryData plus invalidation.

Webhook coherence: use-webhook-info uses shared useWebhookQuery; useReactivateWebhook invalidates webhookKeys after PATCH so disabled state does not linger for staleTime.

Smaller touches: demo modal uses getErrorMessage, workflow sidebar save invalidates on onSettled, table detail invalidation uses exact: true to avoid refetching all row queries.

Reviewed by Cursor Bugbot for commit f7e87df. Configure here.

Comment thread apps/sim/hooks/queries/resume-execution.ts Outdated
@greptile-apps

greptile-apps Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR performs a codebase-wide React Query audit across ~46 files, applying consistent patterns (explicit staleTime, signal forwarding, hierarchical key factories, onSettled returning invalidateQueries promises) along with three substantive fixes: a webhook cache-coherence bug where reactivateWebhook bypassed the shared query cache, a full migration of resume-page-client.tsx from raw fetch+useState to React Query (with optimistic updates), and the addition of a getPauseContextDetailContract for the GET handler that previously shared the POST contract.

  • Webhook fix: use-webhook-info.ts replaced its own fetch+useState loop with useWebhookQuery + new useReactivateWebhook mutation that properly invalidates webhookKeys.byBlock(...), eliminating the up-to-60s stale isActive window that useWebhookManagement was exposed to.
  • Resume migration: resume-page-client.tsx was restructured around useResumeExecutionDetail, usePauseContextDetail, and useResumeContext, collapsing two duplicate GET paths into a single query + useEffect-on-data, with optimistic setQueryData on submit followed by invalidation-driven reconciliation.
  • onSettled Promise propagation: All onSettled callbacks now return the Promise.all([invalidateQueries...]) so mutateAsync stays pending through the refetch cycle before resolving to callers.

Confidence Score: 5/5

Safe to merge after a manual pause/resume smoke test on the resume page, which underwent the largest single-component rewrite in the PR.

The webhook and resume changes are behavior-preserving migrations with clear correctness: isDisabled/webhookId derivations in use-webhook-info.ts produce identical outputs to the old setState logic, onSettled returns the Promise.all so mutateAsync correctly stays pending through refetch, and the optimistic setQueryData in handleResume is followed by invalidation-driven reconciliation. No cache keys are left dangling — useReactivateWebhook invalidates the exact byBlock key that useWebhookQuery subscribes to. The schedules, subscription, workflow, and other bulk-updated hooks are mechanical onSuccess→onSettled conversions with no logic changes. The new check-react-query-patterns.ts CI script locks in the conventions going forward.

apps/sim/app/resume/[workflowId]/[executionId]/resume-page-client.tsx — largest change (~350 lines net), worth a manual pause/resume smoke test before merge.

Important Files Changed

Filename Overview
apps/sim/hooks/queries/resume-execution.ts New file: three hooks (useResumeExecutionDetail, usePauseContextDetail, useResumeContext) with proper staleTime, signal forwarding, hierarchical key factory, and a boundary-annotated raw fetch for the POST that has no body schema.
apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/workflow-block/hooks/use-webhook-info.ts Replaced local fetch+useState with useWebhookQuery + useReactivateWebhook; isDisabled/webhookId derivation is correct parity with old logic; reactivateMutation is correctly omitted from useCallback deps per project rules.
apps/sim/hooks/queries/webhooks.ts Added useReactivateWebhook mutation with onSettled invalidation; webhookKeys updated to hierarchical form (added 'detail' segment); byBlock params made optional for invalidation use cases.
apps/sim/app/resume/[workflowId]/[executionId]/resume-page-client.tsx Large migration (~350 lines removed) from raw fetch/useState to React Query; optimistic setQueryData on resume submit followed by invalidation; handleRefreshExecution auto-select parity preserved; recommend a manual pause/resume smoke test.
apps/sim/hooks/queries/subscription.ts onSuccess → onSettled with returned Promise.all; useUpgradeSubscription now also invalidates invoicesAll() which was missing before; useUpdateUsageLimit narrowed from subscriptionKeys.all to users() + usage().
apps/sim/hooks/queries/schedules.ts All five mutations consistently migrated from onSuccess to onSettled with returned Promise.all; useReactivateSchedule still logs in onSuccess (non-blocking) before async invalidations in onSettled.
apps/sim/lib/api/contracts/workflows.ts New getPauseContextDetailContract with passthrough z.object schema; GET route handler now parses against this contract instead of the POST resumeWorkflowExecutionContextContract.
apps/sim/app/api/resume/[workflowId]/[executionId]/[contextId]/route.ts Correct swap from resumeWorkflowExecutionContextContract to getPauseContextDetailContract for GET parseRequest; both share the same params schema so request validation is unchanged.
apps/sim/hooks/queries/workflow-mcp-servers.ts All six mutations consistently moved to onSettled returning Promise.all; no logic changes.
scripts/check-react-query-patterns.ts New CI enforcement script: statically checks staleTime presence, signal destructuring, key factory usage, and all root keys in hooks/queries/**; baseline JSON ratchet for the rest of the app.

Sequence Diagram

sequenceDiagram
    participant UI as ResumeExecutionPage
    participant RQ as React Query Cache
    participant API as /api/resume/...
    participant WH as use-webhook-info
    participant WHAPI as /api/webhooks/...

    Note over UI,RQ: Resume Page - React Query migration
    UI->>RQ: useResumeExecutionDetail(workflowId, executionId, initialData)
    RQ-->>UI: data (from initialData or background refetch)
    UI->>RQ: usePauseContextDetail(workflowId, executionId, contextId)
    RQ->>API: GET /api/resume/[wId]/[eId]/[cId]
    API-->>RQ: PauseContextDetail
    RQ-->>UI: selectedDetail
    UI->>RQ: "useResumeContext().mutateAsync({...})"
    RQ->>API: POST /api/resume/[wId]/[eId]/[cId]
    API-->>RQ: "{ok, payload}"
    Note over UI,RQ: Optimistic update via setQueryData
    RQ-->>UI: "resumeStatus=resuming (optimistic)"
    Note over RQ: onSettled: invalidate execution + context keys
    RQ->>API: GET refetch (execution + context)
    API-->>RQ: Fresh server state
    RQ-->>UI: Reconciled data

    Note over WH,WHAPI: Webhook Cache-Coherence Fix
    WH->>RQ: useWebhookQuery(workflowId, blockId, isConfigured)
    RQ->>WHAPI: GET listWebhooksByBlock
    WHAPI-->>RQ: "{isActive, id}"
    RQ-->>WH: "webhook (shared cache, staleTime=60s)"
    WH->>RQ: "useReactivateWebhook().mutateAsync({webhookId, workflowId, blockId})"
    RQ->>WHAPI: PATCH /api/webhooks/[id]
    WHAPI-->>RQ: updated webhook
    Note over RQ: onSettled: invalidate webhookKeys.byBlock(wId, bId)
    RQ->>WHAPI: GET refetch (all consumers see fresh isActive)
    RQ-->>WH: "{isActive: true} (cache coherent)"
Loading

Reviews (2): Last reviewed commit: "chore(react-query): add static pattern l..." | Re-trigger Greptile

Comment thread apps/sim/hooks/queries/resume-execution.ts Outdated
- add scripts/check-react-query-patterns.ts (staleTime/signal/key-factory/inline-key
  enforcement) wired into CI as check:react-query; strict zone hooks/queries/**, ratchet elsewhere
- fix(resume): use same-origin relative path for resume POST (getBaseUrl could cross origin
  on whitelabel/preview hosts and drop session cookies) — Cursor Bugbot
- remove explanatory inline comments in favor of TSDoc per repo convention
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile review

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit f7e87df. Configure here.

@waleedlatif1 waleedlatif1 merged commit eb1009d into staging Jun 13, 2026
15 checks passed
@waleedlatif1 waleedlatif1 deleted the rq-audit-sweep branch June 13, 2026 17:14
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.

1 participant