feat(comfyui): comfyui_interrupt_queue v1.1.0 — clear_pending + cleared/queue_remaining + tests

Alinea la funcion al contrato de control de cola (punto 3 del roadmap ComfyUI):
- firma keyword-only: clear_pending (vacia pendientes con POST /queue {clear:true}) + timeout
- output {ok, interrupted, cleared, queue_remaining, error}; GET /queue al final
- no lanza en fallo de red: degrada a {ok:False, error}
- test con mock HTTP local (golden + clear + cola vacia + error path), 4/4 verde
- .md autosuficiente con gotchas + capability growth log

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-28 04:54:14 +02:00
parent fbbff7d5e7
commit ca07b25297
3 changed files with 250 additions and 44 deletions
+58 -22
View File
@@ -1,38 +1,53 @@
"""Interrumpe la generacion en curso de ComfyUI y devuelve el estado de la cola.
"""Interrumpe la generacion en curso de ComfyUI y, opcionalmente, vacia la cola.
Funcion impura: hace red (HTTP POST /interrupt + GET /queue). Solo stdlib.
Funcion impura: hace red (HTTP POST /interrupt, POST /queue, GET /queue). Solo
stdlib (urllib, json).
POST /interrupt corta el prompt que ComfyUI esta ejecutando ahora mismo (no vacia
la cola: los prompts pendientes siguen). GET /queue devuelve queue_running (lo que
se ejecuta) y queue_pending (lo encolado). Esta funcion combina ambos en un dict
honesto que NO lanza excepcion en fallo de red: devuelve {ok: False, error}.
POST /interrupt corta el prompt que ComfyUI esta ejecutando ahora mismo: NO vacia
los pendientes, solo aborta el actual y el siguiente arranca de inmediato. Para
vaciar de golpe los pendientes hay que ademas hacer POST /queue con {"clear": true}
(lo que activa el flag clear_pending). GET /queue se consulta al final para reportar
cuantos trabajos quedan en cola tras la operacion (queue_remaining).
NO lanza excepcion en fallo de red: devuelve un dict de estado {ok: False, error}.
"""
import json
import urllib.error
import urllib.request
def comfyui_interrupt_queue(server: str = "127.0.0.1:8188") -> dict:
"""Interrumpe la generacion en curso y devuelve el estado de la cola.
def comfyui_interrupt_queue(
*,
clear_pending: bool = False,
server: str = "127.0.0.1:8188",
timeout: float = 10.0,
) -> dict:
"""Corta la generacion en curso de ComfyUI y devuelve el estado de la cola.
Args:
clear_pending: si True, ademas de cortar el prompt en ejecucion vacia la
cola de pendientes con POST /queue {"clear": true}. keyword-only.
server: host:port del servidor ComfyUI sin esquema (default
"127.0.0.1:8188").
"127.0.0.1:8188"). keyword-only.
timeout: timeout de cada peticion HTTP en segundos (default 10.0).
keyword-only.
Returns:
dict con:
- ok (bool): True si tanto el interrupt como la lectura de la cola
tuvieron exito.
- ok (bool): True si el interrupt, la lectura de la cola y (si se pidio)
el clear tuvieron exito.
- interrupted (bool): True si el POST /interrupt respondio sin error.
- queue_running (int): numero de prompts ejecutandose ahora mismo.
- queue_pending (int): numero de prompts encolados pendientes.
- cleared (bool): True si clear_pending era True y el POST /queue
{"clear": true} respondio sin error; False si no se pidio o fallo.
- queue_remaining (int): trabajos que quedan en cola tras la operacion
(queue_running + queue_pending segun GET /queue al final).
- error (str): mensaje de error si algo fallo; cadena vacia si todo OK.
"""
out = {
"ok": False,
"interrupted": False,
"queue_running": 0,
"queue_pending": 0,
"cleared": False,
"queue_remaining": 0,
"error": "",
}
base = f"http://{server}"
@@ -40,19 +55,37 @@ def comfyui_interrupt_queue(server: str = "127.0.0.1:8188") -> dict:
# 1. POST /interrupt (cuerpo vacio): corta el prompt en ejecucion.
try:
req = urllib.request.Request(f"{base}/interrupt", data=b"", method="POST")
with urllib.request.urlopen(req, timeout=10.0):
with urllib.request.urlopen(req, timeout=timeout):
out["interrupted"] = True
except urllib.error.URLError as exc:
reason = getattr(exc, "reason", exc)
out["error"] = f"interrupt fallo: no se pudo conectar a {base}/interrupt: {reason}"
return out
# 2. GET /queue: estado actual de la cola tras el interrupt.
# 2. Opcional: POST /queue {"clear": true} para vaciar los pendientes.
if clear_pending:
try:
payload = json.dumps({"clear": True}).encode()
req = urllib.request.Request(
f"{base}/queue",
data=payload,
method="POST",
headers={"Content-Type": "application/json"},
)
with urllib.request.urlopen(req, timeout=timeout):
out["cleared"] = True
except urllib.error.URLError as exc:
reason = getattr(exc, "reason", exc)
out["error"] = f"clear fallo: no se pudo conectar a {base}/queue: {reason}"
return out
# 3. GET /queue: cuantos trabajos quedan en cola tras la operacion.
try:
with urllib.request.urlopen(f"{base}/queue", timeout=10.0) as resp:
with urllib.request.urlopen(f"{base}/queue", timeout=timeout) as resp:
data = json.loads(resp.read())
out["queue_running"] = len(data.get("queue_running", []))
out["queue_pending"] = len(data.get("queue_pending", []))
running = len(data.get("queue_running", []))
pending = len(data.get("queue_pending", []))
out["queue_remaining"] = running + pending
out["ok"] = True
except urllib.error.URLError as exc:
reason = getattr(exc, "reason", exc)
@@ -63,9 +96,12 @@ def comfyui_interrupt_queue(server: str = "127.0.0.1:8188") -> dict:
if __name__ == "__main__":
res = comfyui_interrupt_queue()
import sys
clear = "--clear" in sys.argv[1:]
res = comfyui_interrupt_queue(clear_pending=clear)
print(
f"ok={res['ok']} interrupted={res['interrupted']} "
f"running={res['queue_running']} pending={res['queue_pending']} "
f"cleared={res['cleared']} queue_remaining={res['queue_remaining']} "
f"error={res['error']!r}"
)