Files
ComfyUI-Tenaciousload/README.md
T
Ethanfel a8d8b3792c feat: add Quick (incremental) and Register refresh modes
- quick:    incremental rescan — re-walks only folders whose mtime changed
            (per-dir snapshot persisted to cache/scan_snapshot.json); reuses
            the cache for unchanged folders. Catches new/removed/renamed files.
- register: append specific file path(s) with NO folder walk (instant disk-wise)
- full:     unchanged default (clear cache -> full re-walk)

Frontend exposes all three as Extensions-menu commands; the graph node gains a
quick/full mode widget. POST /tenaciousload/refresh now takes {mode, folder, files}.
Unit-tested: incremental scan rescans only the changed dir; register adds/skips.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 01:25:12 +02:00

113 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<p align="center">
<img src="assets/banner.svg" alt="ComfyUI-Tenaciousload" width="100%">
</p>
# ComfyUI-Tenaciousload
Self-contained fix for slow / black-screen ComfyUI loading when you have a huge
model/LoRA collection (especially on a network mount). **Just install the pack
and restart ComfyUI — no nginx, no docker, no extra port.**
## The problem
ComfyUI's `/api/object_info` enumerates every node's inputs. With thousands of
LoRAs (worse on a network mount) it becomes tens of MB and takes **minutes to
build on every page load** — and the build **freezes ComfyUI's whole event
loop**, so you get a long black screen, worst over a remote network.
## How this pack fixes it
<p align="center">
<img src="assets/how-it-works.svg" alt="How it works: requests are served straight from an in-process cache; the slow build only runs on a miss or refresh" width="100%">
</p>
On load it injects an aiohttp **middleware** into ComfyUI that intercepts
`/object_info` and `/api/object_info` and:
- **caches the built response in memory _and_ on disk** (`./cache/`), so it is
built once instead of on every load — and the disk copy makes **restarts
instant** (no rebuild);
- **serves it gzipped** (≈85% smaller transfer, independent of any CLI flag),
straight from cache **without running the build**;
- because the build never runs on a normal load, the event-loop freeze (and the
long black screen) is gone — page loads drop from **minutes to seconds**.
The only time a build runs is the first load after install, or when you
explicitly refresh (below).
## Refreshing after you add / remove models or LoRAs
The cache holds the old model lists until you refresh. Three modes are available
from the **`Extensions`** menu (and the command palette):
| Mode | What it does | Speed |
|------|--------------|-------|
| ⚡ **Quick refresh** | Re-walks only the folders whose timestamp **changed** since the last scan; reuses the cache for the rest. Catches new / removed / renamed files. | Fast on local disks; **~2× faster** on a slow network mount (it still has to stat every folder to find which changed). |
| 🔄 **Full refresh** | Clears ComfyUI's folder cache and re-walks **everything**. Catches moves/deletes anywhere. | Slowest (the original behaviour). |
| **Register new file…** | You give it the path(s) of the file(s) you just added; it appends them to the cache with **no folder walk**. | Instant disk-wise — only the `object_info` rebuild remains. |
Also available:
- **Graph node** `🔄 Refresh Models/LoRAs (Tenaciousload)` with a `mode` widget
(`quick` / `full`), for automated workflows.
- **HTTP:** `POST /tenaciousload/refresh` with
`{"mode": "quick" | "full" | "register", "folder": "loras", "files": ["pack/new.safetensors"]}`,
then `GET /object_info?nocache=1`.
> The **first** Quick refresh after install builds a folder index (one full walk),
> so it's as slow as a Full refresh that one time; every Quick refresh after that
> is incremental. The index is saved to `./cache/scan_snapshot.json`.
Whichever mode you pick, the button shows a "refreshing…" toast and normal loads
stay instant.
## Requirements
**None to install.** Only ComfyUI itself (tested on 0.23.0) and Python ≥ 3.8.
Everything used is Python stdlib or already bundled with ComfyUI (`aiohttp`,
`folder_paths`, `server`). The web button needs no npm packages.
## Install
Clone (or copy) this repo into your ComfyUI `custom_nodes/` folder and restart
ComfyUI:
```bash
cd ComfyUI/custom_nodes
git clone https://github.com/ethanfel/ComfyUI-Tenaciousload.git
# then restart ComfyUI
```
Nothing to `pip install`. ComfyUI-Manager can also install it from the registry.
## Verify it's working
After restart, load the page once (first time builds + caches), then:
```bash
curl -s -H 'Accept-Encoding: gzip' -o /dev/null \
-w '%{time_total}s | %{size_download} bytes | %header{x-tenaciousload-cache} | %header{content-encoding}\n' \
http://127.0.0.1:8188/api/object_info # use your ComfyUI port
# expect after the first load: ~0.00Xs | ~10 MB | HIT | gzip
```
ComfyUI's startup log should show `Tenaciousload: object_info cache middleware installed`.
## Recommended: gzip the rest of ComfyUI
This pack already gzips the cached `object_info` on its own. To **also** gzip
everything else ComfyUI serves — most importantly the *hundreds* of frontend
extension scripts, plus the other API responses — launch ComfyUI with its
built-in compression flag:
```bash
python main.py --listen --port 8188 --enable-compress-response-body
```
- It's a **stock ComfyUI** option (defined in `comfy/cli_args.py`), not part of
this pack, and it's **optional** — Tenaciousload works fine without it.
- It's strongly recommended for **remote access**: those extension scripts are
many small requests that compress very well, so the flag noticeably cuts the
total transfer on top of the `object_info` cache.
- It costs a little CPU per response to compress; on a fast machine this is
negligible compared to the bytes saved over the network.
## Notes
- The disk cache lives in `./cache/` (git-ignored). Delete it, or use the refresh
button, to force a rebuild.
- An nginx reverse proxy can cache `object_info` at the HTTP layer too, but this
pack does it in-process so no extra service, container, or port is needed.
## License
MIT — see [LICENSE](LICENSE).