Commit Graph

6 Commits

Author SHA1 Message Date
Ethanfel 0d2b5e0819 fix: detect new input-folder files across restarts
Same root cause as the node-update bug: the input file list (LoadImage etc. do
os.listdir(input) in INPUT_TYPES) is baked into the cached object_info, which
persists across restarts, so new input files were invisible until a manual
refresh. The input dir is listed non-recursively, so its own mtime reliably
flags add/remove -- fold it (one stat) into the node fingerprint so a restart
picks up new input files. Model folders are nested + on a slow mount, so they
are intentionally not fingerprinted (use a refresh button for new models).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05 11:59:05 +02:00
Ethanfel fcd7c49da5 fix: detect in-place node updates (not just install/remove)
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>
2026-06-05 11:56:09 +02:00
Ethanfel 04f6271867 fix: build object_info off the event loop so a slow mount can't hang ComfyUI
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>
2026-06-05 11:51:45 +02:00
Ethanfel 4a1c2f3a99 feat: auto-invalidate cache when installed node set changes
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>
2026-06-04 23:16:39 +02:00
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
Ethanfel 2c1777ae4e Initial commit: in-process object_info cache + refresh UI
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>
2026-06-04 00:25:41 +02:00