Comfy-Org / Comfy-Org/Comfy-Desktop
Snapshot install: reuse modal-resolved release/variant (fix >1min freeze + drift) and memoize detectGPU
- Dominant language
- TypeScript
- Stars
- 458
- Forks
- 59
- Avg merge
- 22h 18m
- Merged PRs (30d)
- 45
Description
## Context
Follow-up work split out of #998 (frozen-comfy Load Snapshot / Track Existing fixes). Two related "snapshot install is slow / janky" problems that are out of scope for that PR but should be fixed together in one follow-up PR.
---
## 1. `createFromSnapshot` re-resolves R2 on Install — causes a >1 min freeze and a consistency bug
**Symptom:** Clicking **Install** in Restore-from-Snapshot flips the button to "Installing…" but no progress modal appears for a long time (observed >1 minute), then it finally shows.
**Why:** The progress modal only opens *after* the `create-from-snapshot` IPC handler returns. Before returning, that handler re-resolves the standalone release/variant from R2 from scratch:
- `getFieldOptions('release', {}, { includeLatestStable: true })` → `fetchJSON(latest.json, { refresh: true })` + one `fetchJSON(releases.json, { refresh: true })` per vendor.
- `fetchJSON` (`fetchJSONOnce` in `src/main/lib/fetch.ts`) builds an Electron `net.request` with **no timeout**, so a slow/stalled R2 socket can hang for minutes.
- `detectGPU()` is also re-run here (see item 2).
This duplicates work the modal already did: when the modal opened, `loadReleaseOptions()` already fetched the exact release/variant data the user is looking at.
**Consistency bug (the more important half):** because the Install-time fetch uses `refresh: true`, it bypasses the just-warmed cache and can return *different* data than the modal showed (a bundle shipped or got pruned in between). For a "frozen restore," the install must use what the user saw, not a re-fetched moving target.
**Fix direction:** Don't re-resolve in the main process. Reuse the renderer's already-resolved `selectedRelease` / `selectedVariant` (which carry `vendorReleases` + the pinned `r2Release`) so `createFromSnapshot` installs exactly what the user saw — fixing both the freeze and the consistency bug. Fall back to a re-fetch only if the renderer passed nothing.
Note: simply deleting `refresh: true` is **not** the right lever — it's hardcoded in `getFieldOptions`, which the Install Wizard relies on for freshness, and `fetchJSON` would still do an untimed conditional request.
**Secondary hardening:** give `fetchJSON` (`net.request`) a timeout (~10s) + abort so any R2 call fails fast and falls back to cache/mirror instead of hanging.
**Relevant code:**
- `src/main/lib/ipc/registerSnapshotHandlers.ts` — `create-from-snapshot` handler (release/variant re-resolution)
- `src/main/sources/standalone/index.ts` — `getFieldOptions('release')` (hardcoded `refresh: true`)
- `src/main/lib/fetch.ts` — `fetchJSONOnce` (no timeout)
- `src/renderer/src/views/LoadSnapshotModal.vue` — `handleCreate` / `loadReleaseOptions` (already-resolved selection)
---
## 2. `detectGPU` is uncached — repeated multi-second spawns per flow
`detectGPU` (`src/main/lib/gpu.ts`) spawns external processes (WMI/PowerShell on Windows, `lspci` on Linux, `sysctl` on macOS) with per-call timeouts up to ~10s, and is **not memoized**. It runs fresh on every call, and the snapshot flow calls it multiple times (modal open → release resolution, variant resolution, and again in `createFromSnapshot`).
**Fix direction:** Memoize `detectGPU` with a short TTL + in-flight collapsing, mirroring `getLatestStableTag` in `src/main/lib/comfyui-releases.ts` (success TTL + short failure TTL so a transient detection hiccup isn't cached as "no GPU"). GPU hardware is effectively static within a session.
> A ready-to-use implementation was prototyped during #998 review and then reverted to keep that PR focused; it renames the current body to `detectGPUUncached` and wraps it with a memoizing `detectGPU` + a `_clearGpuCache()` test hook.
---
## Acceptance criteria
- [ ] Restore-from-Snapshot shows install progress within ~1–2s of clicking Install (no minute-long freeze).
- [ ] The created install matches the release/variant the user saw in the modal (no re-fetch drift).
- [ ] `fetchJSON` cannot hang indefinitely (bounded timeout + fallback).
- [ ] `detectGPU` is memoized; repeated calls within a flow don't re-spawn detection processes.
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.