Pipeline APIs¶
fxquinox ships a small set of pipeline primitives on top of the publish chain: path resolution from a project's anatomy, a host-agnostic universal loader with scene inventory, a render farm queue, and multi-site sync. They are all reachable from the SDK and the HTTP API, and they are deliberately thin - the host (Houdini, Nuke, a farm blade) supplies only the host-specific bit; everything else is shared core.
Project anatomy, path resolution¶
A project's anatomy is a set of named templates (work, publish, …) and
roots (named filesystem prefixes, e.g. work vs publish storage) stored on
the Project. Templates are token strings like
{root}/{project}/{entity}/{task}/v{version}/{product}.{ext} that resolve
against an entity plus extra fields.
resolve_path turns a template into a concrete path for a specific entity:
path = fxq.resolve_path(
template_key="publish",
entity_type="Task",
entity_id=task.id,
root_name="work", # which root to resolve against
extra={"product": "lightingMain", "ext": "exr"},
)
Resolving on the server (not in each DCC) keeps every host and the farm in agreement about where files live, and means a studio can retarget storage by editing the anatomy in one place.
Universal loader, scene inventory¶
The universal loader lets any host place a published version without the core knowing which host it is. Each integration registers a loader for the product types it understands:
@loader.register_loader("houdini_file", product_types=["geometry", "render", "pointcache"])
def load_file_node(session, version_id, files, **_):
... # host builds the node; the core resolves the files
To drive a loader UI, ask the server what is loadable into a context:
# everything publishable into a context (latest only)
items = fxq.browse_loadable(project_id=pid, product_type="render", latest_only=True)
Scene inventory keeps an open scene honest. Given the version ids currently loaded, it reports which are outdated so the host can offer an update:
This is the same contract the Houdini and Nuke adapters use.
Render farm¶
Submit and track farm jobs. The farm itself reports progress back through the update call:
job = fxq.submit_farm_job(task_id=task.id, version_id=ver_id, frames="1-100")
fxq.farm_jobs(status="running") # list / filter tracked jobs
fxq.update_farm_job(job["id"], status="completed", progress=100)
Jobs are tracked records, so they flow through events and show up in activity like any other entity.
Multi-site sync (SiteSync)¶
For multi-location studios, SiteSync queues transfers of a representation between named sites and processes them as a batch:
fxq.request_sync(representation_id=rep_id, target_site_id=site_id)
fxq.sync_jobs(status="queued") # list transfer jobs
fxq.process_sync_queue() # process the queue once → completed count
The full method surface is in the SDK reference.