Concurrent Submit | zhenzhen-moss-image(生成/编辑·平价小屋)
The concurrent submit node, and the collector you can't skip
- image1
- api_config
- task
Here's the thing about API nodes: your GPU does nothing while they run. zhenzhen-moss-image fires off a job, then sits in a poll loop for a minute or two using none of your hardware. Queue six prompt variants in a row and you wait six times for no reason. ComflyConcurrent_T8Zhenzhen_Moss_Image_LowPrice_Submit exists to fix exactly that, and it's the node in this pack I'd argue is worth learning even if you only use it occasionally.
What it actually is
It's a generated twin, not hand-written. When the pack loads, it walks its own node registry, finds every zhenzhen node whose first output is an IMAGE, and synthesizes a second class alongside it - same category, same inputs, one task output of type COMFLY_IMAGE_FUTURE. The display name gets "Concurrent Submit |" glued to the front. The original node is never replaced, so your old workflows keep working, and moss-image qualified automatically the moment it was added.
The submit function does one thing: it takes the arguments you'd have handed the real node, drops them into a shared bounded thread pool - 30 image workers by default - and returns a handle immediately. Everything else (upload, the POST to /v1/image/generations, polling, download, decode) still runs the original node's code, just on a worker thread.
The collector is not optional
This is where people get stuck, and it isn't their fault. The submit node outputs a task handle - you cannot wire it to Preview Image, and there's nothing to save. You need the matching collector: ComflyConcurrent_Image_Await, titled "Concurrent Collect Images (30)". Wire each submit's task into task_1, task_2, and so on; the collector waits for all of them and emits image_1 through image_30 plus a status string.
The payoff is that slots keep their order. Whatever you wired into task_3 comes out of image_3, so a six-variant sweep lands in six predictable slots instead of "whichever finished first."
The inputs you set
Identical to the base node, because they're a deep copy of it: prompt, ratio (eight fixed aspects, default 9:16 - still the thing you'll forget), one optional image1, the api_config from the settings node, skip_error, and the execution-only seed. There are no new knobs; the only real change is the shape of the output.
Which means the one new discipline: every submit node needs its own api_config connection (or the SEEDANCE_API_KEY env var set once). Sixteen nodes, sixteen wires, and a single forgotten one fails with the same "empty api_key" error as the base node. Fan-out the settings node's output to all of them.
At the collector, the one field worth a decision is failure_mode. Default is fail_fast - any slot failing aborts the whole collect, which is honest but loses the images that did finish. Switch to placeholder and a failed slot returns a small all-red 64×64 image instead, letting the rest through. For a 20-variant sweep where you'd rather keep 19 good ones, placeholder is the right call, as long as you actually look at status afterwards instead of assuming everything rendered.
Tuning and installing
Install is the same as the rest of the pack - Manager search zhenzhen, or:
cd ComfyUI/custom_nodes
git clone https://github.com/T8mars/Comfyui-zhenzhen
cd Comfyui-zhenzhen && pip install -r requirements.txt
# restart ComfyUI
The pool is configurable via environment variables before you start ComfyUI, if 30 is too aggressive for your patience or your budget:
export COMFLY_IMAGE_CONCURRENCY=8 # worker threads (default 30)
export COMFLY_IMAGE_PENDING=8 # extra queued submissions beyond the workers
Where it bites
Cost is the honest one. Thirty concurrent calls are thirty billed calls, and they all leave at once. Concurrency doesn't make anything cheaper - it just compresses the wait. Point this at a 20-prompt sweep on release day and you'll feel it. Do a two-node smoke test first.
Identical inputs may not cost you anything at all, which is its own confusion: the author's changelog is explicit that the submit nodes honour the fixed-seed cache, so the same prompt with a fixed seed can return a cached result rather than a fresh generation. That's the behaviour you want for a re-run of an unchanged graph, and the reason a "batch of 8" of the same prompt can come back as 8 identical images. Vary the prompt.
Wall-clock equals your slowest slot, not the average. One model wobbling for fifteen minutes holds the collector open for fifteen minutes while the other 29 results sit finished in memory. Since the underlying poll ceiling is 30 minutes, budget for it.
And watch the status string - it's per-slot (not_connected, pending, or the outcome), which tells you instantly whether a blank slot is a failure or just a wire you forgot. That output is the cheapest debugging you'll get anywhere in this pack.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| prompt | STRING | Required image description or editing instruction. | |
| ratio | COMBO | 9:16 | 8 options: 1:1, 2:3, 3:2, 3:4, 4:3, 9:16, +2 |
| image1opt | IMAGE | One optional reference image; disconnect for text generation. Batches are not supported. | |
| api_configopt | ZHENZHEN_SEEDANCE2_CONFIG | — | |
| skip_erroropt | BOOLEAN | false | — |
| seedopt | INT | 00–18446744073709550000 | Execution seed for ComfyUI cache control. Fixed reuses the cached result; randomize/increment/decrement requests a new run. This compatibility seed is not sent to APIs that do not expose a native seed parameter. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| task | COMFLY_IMAGE_FUTURE | — |