Upscale in Always mode tries again after a running generation instead of giving up; tests for relink wiring, first-40 window, RTX at job start

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tw9fjX7o2YfeGQE18MEtPu
This commit is contained in:
Claude
2026-11-08 19:59:38 +00:00
parent 76c707b81c
commit cc93830a96
3 changed files with 44 additions and 1 deletions
+6 -1
View File
@@ -12,7 +12,7 @@ export default {
modules: ["render"],
setup({ host, app }) {
const p = app.project, sel = app.selection;
const put = inPlace(host), busy = new Set();
const put = inPlace(host), busy = new Set(), waited = new Map(); // waited: how often "Always" put a render off for a running generation
const render = (id) => ((p.project || {}).scene_renders || {})[id];
const target = () => { // the picked clip's generation unit root, when it has a render
const open = p.project, sc = open && open.scenes.find((s) => s.id === sel.focus);
@@ -55,6 +55,11 @@ export default {
else c.toast.good({ text: "Upscaled: the render now plays the larger video." });
} catch (err) {
if (err.stopped) c.toast.info({ text: "Upscale stopped. The render stays as it was." });
else if (!pressed && /^ComfyUI is generating/.test(err.message || "") && (waited.get(key) || 0) < 60) { // Always: not lost, tried again when the generation is over
if (!waited.has(key)) c.toast.info({ text: "Upscale waits for the generation to finish." });
waited.set(key, (waited.get(key) || 0) + 1);
setTimeout(() => run(media), 15000);
}
else { gaveUp(media, "upscale"); c.toast.warn({ text: `Upscale failed: ${err.message}` }); }
}
finally { busy.delete(key); draw(); }
+28
View File
@@ -138,3 +138,31 @@ def test_a_hand_over_with_no_parent_is_logged_after_the_first_forty(monkeypatch)
leak_report.watch_switch(mm)
LM()._switch_parent()
assert lines and "hand-over" in lines[0][1] and "gone" in lines[0][1]
def test_install_runs_relink_before_comfyuis_own_cleanup(monkeypatch):
order = []
mm = type("MM", (), {})()
mm.cleanup_models_gc = lambda: order.append("comfy")
monkeypatch.setattr(leak_report, "watch_switch", lambda m: True)
monkeypatch.setattr(leak_report, "relink", lambda m: order.append("relink") or 0)
monkeypatch.setattr(leak_report, "report", lambda m, when: order.append(when) or 0)
assert leak_report.install(mm)
mm.cleanup_models_gc()
assert order == ["relink", "before ComfyUI's gc", "comfy", "after ComfyUI's gc"]
def test_the_first_forty_hand_overs_with_a_parent_are_logged_and_the_forty_first_is_not(monkeypatch):
monkeypatch.setattr(leak_report, "_seen", [0])
lines = []
monkeypatch.setattr(leak_report.log, "info", lambda *a, **k: lines.append(a))
mm = type("MM", (), {})()
class LM:
def __init__(self): self._parent_model = lambda: object(); self.real_model = lambda: None
def _switch_parent(self): pass
mm.LoadedModel = LM
leak_report.watch_switch(mm)
for _ in range(45):
LM()._switch_parent()
assert len(lines) == 40
@@ -344,3 +344,13 @@ def test_upscale_job_with_a_model_file_stops_if_comfyui_got_busy_after_the_route
import pytest
with pytest.raises(RuntimeError, match="ComfyUI is generating"):
upscale.run({"filename": "x.mp4"}, "4x.safetensors")
def test_rtx_upscale_job_runs_while_comfyui_is_busy(monkeypatch, tmp_path):
from modules.output.render import upscale, rtx
monkeypatch.setattr(upscale, "comfy_busy", lambda: True)
import pytest
# the busy check is passed (RTX); the run then stops on the missing file, not on the busy message
with pytest.raises(RuntimeError) as e:
upscale.run({"filename": "missing.mp4"}, rtx.NAME)
assert "ComfyUI is generating" not in str(e.value)