Perf/scan and font cache#100
Conversation
Two hot-path optimisations backported from the v2 rewrite:
1. getConnectedNodes (page-wide): replace manual JS recursion +
per-node getPluginData() with findAllWithCriteria({ pluginData })
so the Figma runtime does the filtering natively — O(all nodes)
→ O(connected nodes), zero bridge crossings for unrelated nodes.
2. formatText: hoist the availableFonts cache to module scope so
listAvailableFontsAsync() is called at most once per plugin
session rather than once per node during a multi-node pull.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
After any setNodesData call (connect, disconnect, pull), the mutation's onSuccess patched only the stale marker, causing a full-page findAll scan every time the user returned to Index. On large Figma files this was the source of the ~20-second connect operation delay. Fix with three coordinated changes: - useSetNodesDataMutation: replace invalidateQueries with a direct cache patch (setQueryData) that adds, updates, or removes only the affected nodes — no bridge round-trip needed. - useConnectedNodes: set staleTime:30s so the freshly-patched cache is still considered valid when the Index route-change effect fires. - Index: guard allNodes.refetch() behind allNodes.isStale, so it only rescans when the cache is genuinely outdated (e.g. after Push/Pull which use explicit invalidation, or on first mount). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nent Updated the translation assignment in the Connect component to use nullish coalescing (??) instead of logical OR (||) for better handling of undefined values. This change ensures that the fallback to node.characters only occurs when resolvedTranslation is null or undefined.
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughThe PR optimizes query caching and data fetching across the Figma plugin. It introduces session-level font caching, refactors connected-nodes queries to handle selection vs. page-wide paths separately, and improves the UI layer's React Query strategy with cache expiration, direct patching, and conditional refetch guards. A minor translation fallback operator fix is included. ChangesCache Optimization and Connected Nodes Refactoring
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/main/endpoints/formatText.ts`:
- Around line 73-76: formatText's font-loading logic races because multiple
concurrent callers can see availableFontsCache null and each call
figma.listAvailableFontsAsync(); introduce an in-flight promise (e.g.,
availableFontsPromise) alongside availableFontsCache, set availableFontsPromise
= figma.listAvailableFontsAsync() before awaiting, await that promise to
populate availableFontsCache, return cached value for subsequent callers, and on
rejection clear availableFontsPromise (and leave availableFontsCache null) so
future attempts retry; update any references in formatText to use the promise
cache to dedupe concurrent requests.
In `@src/ui/hooks/useSetNodesDataMutation.ts`:
- Around line 27-31: The multiline ternary inside the Array.prototype.map
callback (the block that checks patch.has(item.id) and uses patch.get(item.id))
violates Prettier; replace it with a single-line ternary or an explicit block
return to satisfy formatting—for example, change the map callback to either:
map((item) => patch.has(item.id) ? { ...item, ...patch.get(item.id)! } : item)
or convert to a block: map((item) => { if (patch.has(item.id)) return { ...item,
...patch.get(item.id)! }; return item; }) so that the expressions using
patch.has and patch.get in useSetNodesDataMutation are flattened and
Prettier-friendly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3da73715-6335-453d-a8bb-8e564a2c4312
📒 Files selected for processing (6)
src/main/endpoints/formatText.tssrc/main/endpoints/getConnectedNodes.tssrc/ui/hooks/useConnectedNodes.tssrc/ui/hooks/useSetNodesDataMutation.tssrc/ui/views/Connect/Connect.tsxsrc/ui/views/Index/Index.tsx
Enhanced the font retrieval logic in formatText by introducing an in-flight promise to prevent concurrent requests for available fonts. This change ensures that the listAvailableFontsAsync function is called only once while the promise is pending, improving performance and reducing unnecessary API calls.
… characters When Index remounts after navigating back from Pull, mountedRef resets to false and the route-change effect treats the mount as the first render, skipping selectionLoadable.refetch(). Marking the selectedNodes query stale in onSuccess ensures useQuery triggers a background refetch on remount so the updated node characters are visible. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Updated the getGlobalSettings function to return a Promise with a Partial<GlobalSettings> type. Improved error handling for clientStorage data retrieval by checking for both string and already-parsed object formats, ensuring robust data parsing and reducing potential errors.
Summary by CodeRabbit
Bug Fixes
Performance
UX / Reliability