Skip to content

fix(models-dev): prevent OOM crash on first launch#26781

Merged
raycastbot merged 3 commits intoraycast:mainfrom
carlesandres:ext/models-dev
Mar 31, 2026
Merged

fix(models-dev): prevent OOM crash on first launch#26781
raycastbot merged 3 commits intoraycast:mainfrom
carlesandres:ext/models-dev

Conversation

@carlesandres
Copy link
Copy Markdown
Contributor

@carlesandres carlesandres commented Mar 30, 2026

Summary

Fixes JS heap out of memory crash that occurs when opening the extension for the first time (empty cache).

Problem

useCachedPromise uses ~4x more memory than direct fetch when populating an empty cache. For our dataset (~1.6 MB JSON, ~4,100 models), this caused the worker to exceed its memory limit and crash before rendering.

This only affected first-time users or users who cleared their cache—subsequent launches worked fine.

Solution

Replaced useCachedPromise with direct fetch + Raycast's Cache API. This:

  • Reduces peak memory from ~82 MB to ~22 MB during initial load
  • Maintains the same stale-while-revalidate behavior
  • Removes the @raycast/utils dependency (no longer needed)

Related issue filed: raycast/utils#67

Checklist

- chore: ignore local debug files
- fix: replace useCachedPromise with direct fetch to prevent OOM on first launch
- Pull contributions
@raycastbot raycastbot added extension fix / improvement Label for PRs with extension's fix improvements extension: models-dev Issues related to the models-dev extension platform: macOS OP is author The OP of the PR is the author of the extension labels Mar 30, 2026
@raycastbot
Copy link
Copy Markdown
Collaborator

Thank you for the update! 🎉

We're currently experiencing a high volume of incoming requests. As a result, the initial review may take up to 10-15 business days.

@carlesandres carlesandres changed the title Update models-dev extension fix(models-dev): prevent OOM crash on first launch Mar 30, 2026
@carlesandres carlesandres marked this pull request as ready for review March 30, 2026 20:21
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 30, 2026

Greptile Summary

This PR fixes a JS heap out-of-memory crash on first launch by replacing useCachedPromise (from @raycast/utils) with a hand-rolled stale-while-revalidate pattern using React's useState/useEffect and Raycast's built-in Cache API. The change reduces peak memory during initial data load from ~82 MB to ~22 MB, addressing a real crash for first-time users.

Key changes:

  • useModelsData.ts: New implementation reads from Cache synchronously on mount, renders immediately with stale data, then fetches fresh data in the background — mirroring the original keepPreviousData behavior with far lower memory overhead.
  • package.json / package-lock.json: @raycast/utils and its dequal transitive dependency removed.
  • CHANGELOG.md: New entry added at the top with correct {PR_MERGE_DATE} placeholder.
  • .gitignore: Local development artifacts (.claude/, GITHUB_ISSUE.md) excluded from version control.

The implementation is logically sound. Two minor style nits: a placeholder issues/XXX URL in a comment should be updated to the real issue number (65), and a setIsLoading(true) call inside the effect is redundant since isLoading is already initialized to true in that code path.

Confidence Score: 5/5

Safe to merge — all remaining findings are P2 style nits with no impact on correctness or behavior.

The core logic is correct: the stale-while-revalidate semantics are preserved, error handling is appropriate, the fetchedRef guard correctly prevents double-fetching in React StrictMode, and the cache write is deliberately deferred after state update to minimize peak heap. Only two minor style issues remain (a stale placeholder URL and a redundant state setter), neither of which affects runtime behavior.

No files require special attention.

Important Files Changed

Filename Overview
extensions/models-dev/src/hooks/useModelsData.ts Replaces useCachedPromise with manual useState/useEffect + Raycast Cache API to fix OOM crash; logic is sound with two minor style nits (placeholder URL, redundant state setter).
extensions/models-dev/package.json Removes @raycast/utils dependency since it is no longer needed after replacing useCachedPromise.
extensions/models-dev/CHANGELOG.md New entry added at the top with correct {PR_MERGE_DATE} placeholder and descending version order.
extensions/models-dev/.gitignore Adds .claude/ and GITHUB_ISSUE.md to prevent local development artifacts from being committed.
extensions/models-dev/package-lock.json Lockfile updated to remove @raycast/utils and its dequal transitive dependency.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/models-dev/src/hooks/useModelsData.ts
Line: 13-14

Comment:
**Placeholder issue URL not updated**

The comment references `issues/XXX` which is a placeholder. Based on the PR description, the actual filed issue is `https://github.com/raycast/utils/issues/65`. This should be updated to point to the real issue for future maintainers.

```suggestion
 * Uses direct fetch + Cache API instead of useCachedPromise to avoid
 * memory spikes during fresh cache population. See:
 * https://github.com/raycast/utils/issues/65
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: extensions/models-dev/src/hooks/useModelsData.ts
Line: 29-42

Comment:
**Redundant `setIsLoading(true)` call**

`isLoading` is already initialized to `!data` on line 29, so when `shouldRevalidate` is `false` (i.e. `data` is `null`), `isLoading` is already `true`. The `setIsLoading(true)` call inside the `if (!shouldRevalidate)` block is a no-op on first render and triggers an unnecessary re-render in React StrictMode (where the effect body runs twice).

```suggestion
  const [isLoading, setIsLoading] = useState(!data);
  const fetchedRef = useRef(false);

  useEffect(() => {
    // Already have cached data or already fetching
    if (fetchedRef.current) return;
    fetchedRef.current = true;

    // If we have cached data, still revalidate in background
    const shouldRevalidate = !!data;
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "Update models-dev extension" | Re-trigger Greptile

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
@carlesandres
Copy link
Copy Markdown
Contributor Author

@0xdhrv @pernielsentikaer This one should be relatively straightforward.

@pernielsentikaer pernielsentikaer self-assigned this Mar 31, 2026
Copy link
Copy Markdown
Collaborator

@pernielsentikaer pernielsentikaer left a comment

Choose a reason for hiding this comment

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

Looks good to me, approved 🔥

@raycastbot raycastbot merged commit 896bed9 into raycast:main Mar 31, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Published to the Raycast Store:
https://raycast.com/carlesandres/models-dev

@raycastbot
Copy link
Copy Markdown
Collaborator

🎉 🎉 🎉

We've rewarded your Raycast account with some credits. You will soon be able to exchange them for some swag.

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

Labels

extension fix / improvement Label for PRs with extension's fix improvements extension: models-dev Issues related to the models-dev extension OP is author The OP of the PR is the author of the extension platform: macOS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants