feat: disabled mode (TENACIOUSLOAD_DISABLED=1) — no-op but keep the loading bar
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 <noreply@anthropic.com>
This commit is contained in:
@@ -140,5 +140,14 @@ This pack is a quiet neighbour:
|
|||||||
changes an existing node's inputs *without* adding/removing a node class, use a
|
changes an existing node's inputs *without* adding/removing a node class, use a
|
||||||
refresh button.
|
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
|
## License
|
||||||
MIT — see [LICENSE](LICENSE).
|
MIT — see [LICENSE](LICENSE).
|
||||||
|
|||||||
+17
-4
@@ -41,6 +41,12 @@ log = logging.getLogger("Tenaciousload")
|
|||||||
|
|
||||||
WEB_DIRECTORY = "./web"
|
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)
|
# 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)
|
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")
|
@PromptServer.instance.routes.get("/tenaciousload/status")
|
||||||
async def _status(request):
|
async def _status(request):
|
||||||
st = {
|
st = {
|
||||||
|
"enabled": not _DISABLED,
|
||||||
"building": _build_state["building"],
|
"building": _build_state["building"],
|
||||||
"done": _build_state["done"],
|
"done": _build_state["done"],
|
||||||
"total": _build_state["total"],
|
"total": _build_state["total"],
|
||||||
@@ -573,7 +583,6 @@ async def _status(request):
|
|||||||
return web.json_response(st)
|
return web.json_response(st)
|
||||||
|
|
||||||
|
|
||||||
@PromptServer.instance.routes.post("/tenaciousload/refresh")
|
|
||||||
async def _refresh(request):
|
async def _refresh(request):
|
||||||
try:
|
try:
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
@@ -605,6 +614,10 @@ async def _refresh(request):
|
|||||||
return web.json_response({"status": "ok", "mode": "full"})
|
return web.json_response({"status": "ok", "mode": "full"})
|
||||||
|
|
||||||
|
|
||||||
|
if not _DISABLED:
|
||||||
|
PromptServer.instance.routes.post("/tenaciousload/refresh")(_refresh)
|
||||||
|
|
||||||
|
|
||||||
# --------------------------------------------------------------------------- #
|
# --------------------------------------------------------------------------- #
|
||||||
# Optional graph node (workflow automation)
|
# Optional graph node (workflow automation)
|
||||||
# --------------------------------------------------------------------------- #
|
# --------------------------------------------------------------------------- #
|
||||||
@@ -640,7 +653,7 @@ class TenaciousloadRefresh:
|
|||||||
return (trigger,)
|
return (trigger,)
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {"TenaciousloadRefresh": TenaciousloadRefresh}
|
NODE_CLASS_MAPPINGS = {} if _DISABLED else {"TenaciousloadRefresh": TenaciousloadRefresh}
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {"TenaciousloadRefresh": "🔄 Refresh Models/LoRAs (Tenaciousload)"}
|
NODE_DISPLAY_NAME_MAPPINGS = {} if _DISABLED else {"TenaciousloadRefresh": "🔄 Refresh Models/LoRAs (Tenaciousload)"}
|
||||||
|
|
||||||
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"]
|
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"]
|
||||||
|
|||||||
@@ -71,12 +71,19 @@ async function tick() {
|
|||||||
: `first build / refresh · ${fmt(st.elapsed || 0)}`;
|
: `first build / refresh · ${fmt(st.elapsed || 0)}`;
|
||||||
bar.classList.add("indet");
|
bar.classList.add("indet");
|
||||||
bar.style.width = "35%";
|
bar.style.width = "35%";
|
||||||
} else {
|
} else if (st && st.cached) {
|
||||||
|
// known fast path: serving the cached object_info
|
||||||
msg.textContent = "Loading node definitions…";
|
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.classList.remove("indet");
|
||||||
bar.style.left = "0";
|
bar.style.left = "0";
|
||||||
bar.style.width = "90%";
|
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%";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,14 @@ async function doRegister() {
|
|||||||
await runRefresh("register", { folder, files });
|
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",
|
name: "Tenaciousload.Refresh",
|
||||||
commands: [
|
commands: [
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user