The node-set fingerprint only hashed NODE_CLASS_MAPPINGS keys, so updating an
existing node (new feature, same class name) didn't change it -> the stale
object_info kept being served across restarts and the update never appeared
(removing Tenaciousload 'fixed' it because the cache was gone).
Now the fingerprint also hashes every custom-node .py path+mtime, so an in-place
update (git pull/edit) changes it and the cache auto-invalidates on the next
restart -- which is when node code reloads anyway, so the update just shows up.
__pycache__/.git/node_modules are skipped (no false positives). Measured 0.27s
for 4268 .py files; runs once per startup. Unit-tested.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Root cause of 'refresh hangs ComfyUI': object_info is built by walking the model
folders synchronously on the single aiohttp event loop. When the model tree is on
a slow/stalling network mount (CIFS), that walk blocks in 'wait_for_response' and
freezes the entire UI until the NAS answers.
Fix:
- Run the object_info build in a worker thread (folder-walk syscalls release the
GIL, so the loop stays responsive). Uses ComfyUI's real node_info, resolved
from the /object_info route closure, with a safe fallback to the in-loop build.
- Offload the Quick scan and Register work to a thread too (POST no longer freezes).
- Guard the incremental scanner against symlink cycles (visited realpaths).
Unit-tested: threaded build bypasses the in-loop handler; node_info resolves;
cycle guard terminates.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fingerprints NODE_CLASS_MAPPINGS; on the first object_info request after a
restart, drops the cached object_info if a node was installed/updated/enabled/
removed, so new nodes appear without a manual refresh. First run (no stored
signature) does not invalidate. Unit-tested.
Also documents that the pack has no deps and does not interfere with other
nodes' installs/updates or their own routes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 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>
ComfyUI-Tenaciousload speeds up ComfyUI page loads for large model/LoRA
collections by caching the slow /api/object_info response in memory and on
disk (survives restarts) and serving it gzipped in ~milliseconds, instead of
rebuilding it (and freezing the event loop) on every load.
Adds a "Refresh Models / LoRAs" menu button, a graph node, and a
POST /tenaciousload/refresh endpoint to rebuild the cache after adding or
removing models. No external dependencies; no nginx/docker required.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>