manual submit
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user