How Modly Workflow Runs Track Status and Handle Cancellation
Modly uses an in-memory job dictionary (_jobs), a global cancellation set (_cancelled), and threading Events to track workflow run progress and allow clients to abort generation through the /workflow-runs/{run_id}/cancel endpoint.
The lightningpixel/modly repository implements a lightweight, in-process job manager for 3D generation workflows. When clients initiate workflow runs via the API, the system tracks status through shared state containers defined in the generation router and exposes endpoints to query progress or cancel execution.
Understanding Modly's Job Tracking Architecture
The JobStatus Model and In-Memory Storage
Modly stores all active workflow runs in a global dictionary named _jobs defined in api/routers/generation.py (lines 17‑20). Each entry maps a UUID to a JobStatus object that tracks status, progress, step, output_url, and error fields. This model, defined in schemas/generation.py, serves as the single source of truth for run state across the application.
The system also maintains two parallel structures for lifecycle management: _cancelled (a set of run IDs marked for cancellation) and _cancel_events (a dictionary mapping run IDs to threading Events).
UUID-Based Run Identification
Every workflow run receives a unique identifier generated upon creation. In api/routers/workflow_runs.py (lines 54‑58), the POST /workflow-runs/from-image endpoint generates this UUID, instantiates a JobStatus object with initial status, and stores it in _jobs before returning the run_id to the client.
How Modly Tracks Workflow Run Status
Creating a Workflow Run
When a client submits an image to start generation, the router immediately returns a run ID while the actual processing occurs asynchronously. The background coroutine _run_generation in api/routers/generation.py receives this ID and updates the shared job object via the progress_cb callback.
import httpx, uuid, json
async def create_run():
async with httpx.AsyncClient(base_url="http://localhost:8000") as client:
with open("my_image.png", "rb") as f:
files = {"image": ("my_image.png", f, "image/png")}
data = {"model_id": "sf3d", "params": json.dumps({"remesh": "quad"})}
resp = await client.post("/workflow-runs/from-image", files=files, data=data)
return resp.json()["run_id"]
Polling Status via GET /workflow-runs/{run_id}
The get_run function in api/routers/workflow_runs.py (lines 65‑84) handles status retrieval. It queries the _jobs dictionary for the provided UUID, builds a WorkflowRunStatus model from the stored JobStatus, and returns the current state. If the job completed successfully, the response includes a scene_candidate field pointing to the generated workspace file.
async def poll_status(client, run_id):
while True:
status = await client.get(f"/workflow-runs/{run_id}")
info = status.json()
print(f"Status: {info['status']} Progress: {info['progress']}%")
if info["status"] in ("done", "error", "cancelled"):
break
await asyncio.sleep(1)
return info
Real-Time Progress Updates
The _run_generation coroutine continuously updates the job object through the progress_cb callback defined in api/routers/generation.py (lines 29‑34). This callback modifies job.progress, job.step, and job.status as the generation pipeline advances through stages such as image preprocessing, model inference, and mesh post-processing.
Workflow Run Cancellation Mechanism
The Three-Layer Cancellation Signal
The cancel_run function in api/routers/workflow_runs.py (lines 86‑107) implements a robust cancellation strategy that operates on three levels:
- Set Membership – Adds the
run_idto the global_cancelledset for quick lookup - Event Signaling – Sets the threading Event stored in
_cancel_eventsfor the specific run ID - Process Termination – Kills the underlying generator subprocess via
gen._proc.kill()and clears generator state
Background Task Polling
The _run_generation function checks for cancellation signals at critical points in the execution flow (lines 60‑62 and 78‑92 in api/routers/generation.py). Before and after the expensive model inference step, it verifies whether the run ID exists in _cancelled or whether the associated Event has been set. If detected, the function returns early and updates the job status to cancelled.
Process Termination
For workflows utilizing external generators (such as Stable Fast 3D), the cancellation endpoint accesses the active generator instance through services/generator_registry.py. If gen._proc exists and is running, the system sends a kill signal to immediately terminate the subprocess, preventing resource waste on abandoned jobs.
await client.post(f"/workflow-runs/{run_id}/cancel")
# Subsequent polls return: {"status": "cancelled"}
Summary
- Modly stores workflow run state in an in-memory
_jobsdictionary using theJobStatusmodel defined inschemas/generation.py - The
GET /workflow-runs/{run_id}endpoint queries this store via theget_runfunction inapi/routers/workflow_runs.py - Cancellation works through a combination of set membership checks (
_cancelled), threading Events (_cancel_events), and subprocess termination - Background generation occurs in
_run_generationwithinapi/routers/generation.py, which polls cancellation signals before and after model inference - Completed jobs are eventually purged by
_purge_old_jobsto prevent memory leaks
Frequently Asked Questions
How does Modly store workflow run status internally?
Modly uses a global dictionary named _jobs defined in api/routers/generation.py that maps UUIDs to JobStatus objects. These objects track status, progress, step, output_url, and error information in-memory. This approach provides low-latency status updates without requiring an external database.
What happens to the subprocess when I cancel a workflow run?
The POST /workflow-runs/{run_id}/cancel endpoint kills the generator subprocess via gen._proc.kill() if it exists, sets a threading Event for the specific run ID, and adds the ID to a global cancellation set. This three-layer approach ensures that even if the subprocess termination fails, the background task will detect the cancellation signal and terminate gracefully.
Can I poll workflow status from multiple clients simultaneously?
Yes, because Modly stores job status in shared memory (_jobs), any client can query GET /workflow-runs/{run_id} to receive the current state. The endpoint simply reads from the shared dictionary and builds a WorkflowRunStatus model, making the system inherently safe for concurrent status polling across multiple HTTP connections.
What status values can a workflow run have?
According to the source code in schemas/generation.py and api/routers/generation.py, jobs typically progress through states including pending, running, done, error, and cancelled. The _run_generation coroutine updates these values via the progress_cb callback as the workflow advances through its pipeline stages.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →