From ed322c9ec2f5edb3c55dfb3a0acf0f74ab82f372 Mon Sep 17 00:00:00 2001 From: Ethanfel Date: Sun, 21 Jun 2026 20:52:43 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20disabled=20mode=20(TENACIOUSLOAD=5FDISA?= =?UTF-8?q?BLED=3D1)=20=E2=80=94=20no-op=20but=20keep=20the=20loading=20ba?= =?UTF-8?q?r?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A one-flag kill-switch: when set, the pack installs no middleware, registers no refresh routes, computes no fingerprint and exposes no graph node — ComfyUI runs exactly as if it weren't installed. Only the read-only /tenaciousload/status route stays so the loading-screen overlay still shows (a generic 'Loading node definitions…' bar, since there's no build to track). The refresh menu buttons hide themselves when status reports enabled:false. Useful for A/B testing or as a safety kill-switch. Requires a restart (the middleware is installed at startup). Unit-tested both modes. Co-Authored-By: Claude Opus 4.8 --- README.md | 9 +++++++++ __init__.py | 21 +++++++++++++++++---- web/loading-status.js | 11 +++++++++-- web/tenaciousload.js | 9 ++++++++- 4 files changed, 43 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 48d9c84..2d2c11e 100644 --- a/README.md +++ b/README.md @@ -140,5 +140,14 @@ This pack is a quiet neighbour: changes an existing node's inputs *without* adding/removing a node class, use a refresh button. +## Disabling (keep only the loading bar) +Set **`TENACIOUSLOAD_DISABLED=1`** (and restart) to turn the pack into a no-op: +no caching middleware, no fingerprint, no refresh routes, no graph node — ComfyUI +behaves exactly as if the pack weren't installed. The **loading-screen status +bar stays** (it just shows a generic "Loading node definitions…" since there's no +build to track). Useful for A/B comparing, or as a one-flag kill-switch if you +ever suspect the cache. Remove the variable (or set it to `0`) and restart to +re-enable. + ## License MIT — see [LICENSE](LICENSE). diff --git a/__init__.py b/__init__.py index 1a880bb..5451888 100644 --- a/__init__.py +++ b/__init__.py @@ -41,6 +41,12 @@ log = logging.getLogger("Tenaciousload") WEB_DIRECTORY = "./web" +# Disabled mode: do NOTHING to ComfyUI (no caching middleware, no refresh routes, +# no fingerprint, no graph node) — but still serve the loading-bar overlay. +# Toggle with TENACIOUSLOAD_DISABLED=1. Requires a restart, since the middleware +# is installed at startup. +_DISABLED = os.environ.get("TENACIOUSLOAD_DISABLED", "").strip().lower() in ("1", "true", "yes", "on") + # --------------------------------------------------------------------------- # # object_info response cache (memory + disk) # --------------------------------------------------------------------------- # @@ -551,7 +557,10 @@ def _install_middleware(): log.error("Tenaciousload: could not install cache middleware (loads will be slow): %s", e) -_install_middleware() +if _DISABLED: + log.info("Tenaciousload: DISABLED — no middleware / caching / refresh (loading overlay only)") +else: + _install_middleware() # --------------------------------------------------------------------------- # @@ -560,6 +569,7 @@ _install_middleware() @PromptServer.instance.routes.get("/tenaciousload/status") async def _status(request): st = { + "enabled": not _DISABLED, "building": _build_state["building"], "done": _build_state["done"], "total": _build_state["total"], @@ -573,7 +583,6 @@ async def _status(request): return web.json_response(st) -@PromptServer.instance.routes.post("/tenaciousload/refresh") async def _refresh(request): try: data = await request.json() @@ -605,6 +614,10 @@ async def _refresh(request): return web.json_response({"status": "ok", "mode": "full"}) +if not _DISABLED: + PromptServer.instance.routes.post("/tenaciousload/refresh")(_refresh) + + # --------------------------------------------------------------------------- # # Optional graph node (workflow automation) # --------------------------------------------------------------------------- # @@ -640,7 +653,7 @@ class TenaciousloadRefresh: return (trigger,) -NODE_CLASS_MAPPINGS = {"TenaciousloadRefresh": TenaciousloadRefresh} -NODE_DISPLAY_NAME_MAPPINGS = {"TenaciousloadRefresh": "🔄 Refresh Models/LoRAs (Tenaciousload)"} +NODE_CLASS_MAPPINGS = {} if _DISABLED else {"TenaciousloadRefresh": TenaciousloadRefresh} +NODE_DISPLAY_NAME_MAPPINGS = {} if _DISABLED else {"TenaciousloadRefresh": "🔄 Refresh Models/LoRAs (Tenaciousload)"} __all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"] diff --git a/web/loading-status.js b/web/loading-status.js index c9e933e..5bd7eac 100644 --- a/web/loading-status.js +++ b/web/loading-status.js @@ -71,12 +71,19 @@ async function tick() { : `first build / refresh · ${fmt(st.elapsed || 0)}`; bar.classList.add("indet"); bar.style.width = "35%"; - } else { + } else if (st && st.cached) { + // known fast path: serving the cached object_info msg.textContent = "Loading node definitions…"; - sub.textContent = st && st.cached ? `from cache · ${mb(st.gz_bytes || st.cache_bytes || 0)} gzipped` : ""; + sub.textContent = `from cache · ${mb(st.gz_bytes || st.cache_bytes || 0)} gzipped`; bar.classList.remove("indet"); bar.style.left = "0"; bar.style.width = "90%"; + } else { + // disabled, or server busy/frozen building natively — show "working" + msg.textContent = "Loading node definitions…"; + sub.textContent = ""; + bar.classList.add("indet"); + bar.style.width = "35%"; } } diff --git a/web/tenaciousload.js b/web/tenaciousload.js index ec9814a..5eaa24c 100644 --- a/web/tenaciousload.js +++ b/web/tenaciousload.js @@ -65,7 +65,14 @@ async function doRegister() { await runRefresh("register", { folder, files }); } -app.registerExtension({ +// Skip the refresh buttons entirely when Tenaciousload is disabled. +let _tlEnabled = true; +try { + const r = await api.fetchApi("/tenaciousload/status"); + if (r.ok) _tlEnabled = (await r.json()).enabled !== false; +} catch (e) { /* assume enabled */ } + +if (_tlEnabled) app.registerExtension({ name: "Tenaciousload.Refresh", commands: [ {