techfreakworm commited on
Commit
19489a8
·
unverified ·
1 Parent(s): 5bf7128

fix(backend,models): runtime corrections from end-to-end testing

Browse files

- backend: PromptExecutor needs (server, ...) not server_instance=None;
init_extra_nodes is async — can't use asyncio.run() inside Gradio's
event loop, run on a worker thread with a fresh loop instead;
add minimal _StubServer with the surface PromptExecutor requires.
- models: short-circuit ensure_models when the file already exists at
comfyui/models/<type>/<file> — local dev path with user's existing
ComfyUI models symlinked in shouldn't trigger HF Hub downloads.

Files changed (2) hide show
  1. backend.py +32 -3
  2. models.py +12 -0
backend.py CHANGED
@@ -53,6 +53,19 @@ def _on_spaces() -> bool:
53
  return bool(os.environ.get("SPACES_ZERO_GPU"))
54
 
55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  def _comfy_dir() -> pathlib.Path:
57
  if _on_spaces():
58
  return pathlib.Path("/data/comfyui")
@@ -77,14 +90,30 @@ class ComfyUILibraryBackend:
77
  # module, NOT under `comfy.execution`. Same for `nodes`. Both must be
78
  # imported AFTER the sys.path insert above.
79
  import asyncio
 
80
 
81
  import comfy.cli_args # noqa: F401 — side-effect: registers CLI flags
82
  import execution # top-level module — provides PromptExecutor
83
  import nodes # top-level module — provides init_extra_nodes (async)
84
 
85
- # init_extra_nodes is an async function in modern ComfyUI; run it once.
86
- asyncio.run(nodes.init_extra_nodes()) # discover custom_nodes/
87
- self._executor = execution.PromptExecutor(server_instance=None)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
88
 
89
  def __repr__(self) -> str:
90
  return f"ComfyUILibraryBackend(comfy_dir={self._comfy_dir!r})"
 
53
  return bool(os.environ.get("SPACES_ZERO_GPU"))
54
 
55
 
56
+ class _StubServer:
57
+ """Minimal stub matching the surface ComfyUI's PromptExecutor expects."""
58
+
59
+ client_id: str | None = "ltx23-aio"
60
+ last_node_id: str | None = None
61
+
62
+ def send_sync(self, event: str, data: dict, sid: str | None = None) -> None:
63
+ pass
64
+
65
+ def queue_updated(self) -> None:
66
+ pass
67
+
68
+
69
  def _comfy_dir() -> pathlib.Path:
70
  if _on_spaces():
71
  return pathlib.Path("/data/comfyui")
 
90
  # module, NOT under `comfy.execution`. Same for `nodes`. Both must be
91
  # imported AFTER the sys.path insert above.
92
  import asyncio
93
+ import threading
94
 
95
  import comfy.cli_args # noqa: F401 — side-effect: registers CLI flags
96
  import execution # top-level module — provides PromptExecutor
97
  import nodes # top-level module — provides init_extra_nodes (async)
98
 
99
+ # `nodes.init_extra_nodes` is async. We may be called from within a
100
+ # running event loop (Gradio's handler) — running `asyncio.run()` there
101
+ # raises. Run the coroutine in a fresh loop on a worker thread instead.
102
+ def _init_in_thread() -> None:
103
+ loop = asyncio.new_event_loop()
104
+ asyncio.set_event_loop(loop)
105
+ try:
106
+ loop.run_until_complete(nodes.init_extra_nodes())
107
+ finally:
108
+ loop.close()
109
+
110
+ thread = threading.Thread(target=_init_in_thread, daemon=False)
111
+ thread.start()
112
+ thread.join()
113
+ # PromptExecutor expects a `server` with client_id, send_sync, last_node_id,
114
+ # queue_updated. A minimal stub no-ops all of them — we don't run a real
115
+ # websocket server, we surface progress via comfy.utils.PROGRESS_BAR_HOOK.
116
+ self._executor = execution.PromptExecutor(server=_StubServer())
117
 
118
  def __repr__(self) -> str:
119
  return f"ComfyUILibraryBackend(comfy_dir={self._comfy_dir!r})"
models.py CHANGED
@@ -201,6 +201,18 @@ def ensure_models(filenames: set[str]) -> Iterator[DownloadEvent]:
201
  continue
202
  entry = MODEL_REGISTRY[filename]
203
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  # Resolve source: hf_hub_download returns the cache path (or downloads).
205
  try:
206
  source = pathlib.Path(
 
201
  continue
202
  entry = MODEL_REGISTRY[filename]
203
 
204
+ # Short-circuit: if the file is already present at its expected location
205
+ # in comfyui/models/<type>/[<subfolder>/]<filename>, skip the HF dance
206
+ # entirely. This is the local-dev hot path where the user's existing
207
+ # ComfyUI models/ is symlinked in.
208
+ existing_dest_dir = comfy_models / entry.comfy_type
209
+ if entry.subfolder:
210
+ existing_dest_dir = existing_dest_dir / entry.subfolder
211
+ existing_dest = existing_dest_dir / filename
212
+ if existing_dest.exists() or existing_dest.is_symlink():
213
+ yield DownloadEvent(filename, 0.0, 0.0)
214
+ continue
215
+
216
  # Resolve source: hf_hub_download returns the cache path (or downloads).
217
  try:
218
  source = pathlib.Path(