manual submit

This commit is contained in:
Khoa (Revenovich) Tran Gia
2026-03-07 21:49:16 +07:00
parent 1748cbf8d2
commit 6004b000a7
39 changed files with 5794 additions and 614 deletions

View File

@@ -17,6 +17,32 @@ router = APIRouter()
logger = logging.getLogger(__name__)
def _materialize_image_slots(
overrides: dict, comfy_input_path: str
) -> tuple[dict, list[str]]:
"""
For each override whose value is an existing ttb_* file, copy it to a
unique name so concurrent jobs each have an immutable copy on disk.
Returns (updated_overrides, paths_to_delete_after_generation).
"""
import shutil
import uuid as _uuid
if not comfy_input_path:
return overrides, []
updated = dict(overrides)
cleanup: list[str] = []
input_dir = Path(comfy_input_path)
for key, val in overrides.items():
if isinstance(val, str) and val.startswith("ttb_") and "." in val:
src = input_dir / val
if src.is_file():
unique_name = f"{src.stem}_{_uuid.uuid4().hex[:8]}{src.suffix}"
shutil.copy2(src, input_dir / unique_name)
updated[key] = unique_name
cleanup.append(str(input_dir / unique_name))
return updated, cleanup
class GenerateRequest(BaseModel):
prompt: str
negative_prompt: Optional[str] = None
@@ -105,7 +131,8 @@ async def generate(body: GenerateRequest, user: dict = Depends(require_auth)):
from generation_db import record_generation, record_file
gen_id = record_generation(pid, "web", user_label, overrides_for_gen, seed_used)
for i, img_data in enumerate(images):
record_file(gen_id, f"image_{i:04d}.png", img_data)
file_id = record_file(gen_id, f"image_{i:04d}.png", img_data)
comfy._schedule_face_scan("image", file_id, img_data)
if config and videos:
for vid in videos:
vsub = vid.get("video_subfolder", "")
@@ -116,7 +143,9 @@ async def generate(body: GenerateRequest, user: dict = Depends(require_auth)):
else Path(config.comfy_output_path) / vname
)
try:
record_file(gen_id, vname, vpath.read_bytes())
vid_data = vpath.read_bytes()
file_id = record_file(gen_id, vname, vid_data)
comfy._schedule_face_scan("video", file_id, vid_data)
except OSError:
pass
except Exception as exc:
@@ -163,25 +192,32 @@ async def workflow_gen(body: WorkflowGenRequest, user: dict = Depends(require_au
registry = get_user_registry()
count = max(1, min(body.count, 20)) # cap at 20
async def _run_one():
# Use the user's own state and template
if registry:
user_sm = registry.get_state_manager(user_label)
user_template = registry.get_workflow_template(user_label)
else:
user_sm = comfy.state_manager
user_template = comfy.workflow_manager.get_workflow_template()
# --- snapshot state at queue time, not at execution time ---
if registry:
_user_sm = registry.get_state_manager(user_label)
_user_template = registry.get_workflow_template(user_label)
else:
_user_sm = comfy.state_manager
_user_template = comfy.workflow_manager.get_workflow_template()
if not user_template:
base_overrides = _user_sm.get_overrides()
if body.overrides:
base_overrides = {**base_overrides, **body.overrides}
_config = get_config()
async def _run_one(overrides: dict, cleanup_paths: list[str]):
if not _user_template:
await bus.broadcast_to_user(user_label, "generation_error", {
"prompt_id": None, "error": "No workflow template loaded"
})
for p in cleanup_paths:
try:
Path(p).unlink(missing_ok=True)
except Exception:
pass
return
overrides = user_sm.get_overrides()
if body.overrides:
overrides = {**overrides, **body.overrides}
import uuid
pid = str(uuid.uuid4())
@@ -190,7 +226,7 @@ async def workflow_gen(body: WorkflowGenRequest, user: dict = Depends(require_au
"node": node, "prompt_id": pid_
}))
workflow, applied = comfy.inspector.inject_overrides(user_template, overrides)
workflow, applied = comfy.inspector.inject_overrides(_user_template, overrides)
seed_used = applied.get("seed")
comfy.last_seed = seed_used
@@ -201,17 +237,23 @@ async def workflow_gen(body: WorkflowGenRequest, user: dict = Depends(require_au
await bus.broadcast_to_user(user_label, "generation_error", {
"prompt_id": None, "error": str(exc)
})
for p in cleanup_paths:
try:
Path(p).unlink(missing_ok=True)
except Exception:
pass
return
comfy.last_prompt_id = pid
comfy.total_generated += 1
config = get_config()
config = _config
try:
from generation_db import record_generation, record_file
gen_id = record_generation(pid, "web", user_label, overrides, seed_used)
for i, img_data in enumerate(images):
record_file(gen_id, f"image_{i:04d}.png", img_data)
file_id = record_file(gen_id, f"image_{i:04d}.png", img_data)
comfy._schedule_face_scan("image", file_id, img_data)
if config and videos:
for vid in videos:
vsub = vid.get("video_subfolder", "")
@@ -222,7 +264,9 @@ async def workflow_gen(body: WorkflowGenRequest, user: dict = Depends(require_au
else Path(config.comfy_output_path) / vname
)
try:
record_file(gen_id, vname, vpath.read_bytes())
vid_data = vpath.read_bytes()
file_id = record_file(gen_id, vname, vid_data)
comfy._schedule_face_scan("video", file_id, vid_data)
except OSError:
pass
except Exception as exc:
@@ -236,6 +280,13 @@ async def workflow_gen(body: WorkflowGenRequest, user: dict = Depends(require_au
config.media_upload_pass,
))
# Clean up unique image copies now that ComfyUI has ingested them
for p in cleanup_paths:
try:
Path(p).unlink(missing_ok=True)
except Exception:
pass
await bus.broadcast("queue_update", {"prompt_id": pid, "status": "complete"})
await bus.broadcast_to_user(user_label, "generation_complete", {
"prompt_id": pid,
@@ -246,7 +297,10 @@ async def workflow_gen(body: WorkflowGenRequest, user: dict = Depends(require_au
depth = await comfy.get_queue_depth()
for _ in range(count):
asyncio.create_task(_run_one())
job_overrides, cleanup = _materialize_image_slots(
base_overrides, _config.comfy_input_path if _config else ""
)
asyncio.create_task(_run_one(job_overrides, cleanup))
return {
"queued": True,