Running Pipelines
Running Pipelines
Start a pipeline, watch its progress, and stop it. Method tables live in the API reference; this page covers the workflow.
Start with use()
use() starts a pipeline from a file (Node only) or an in-memory config and
resolves to an object whose token identifies the running task — every data and
control call takes it.
const { token } = await client.use({ filepath: './pipeline.pipe', ttl: 3600 });
Beyond filepath/pipeline, the options accept token (a custom task token;
the server generates one when omitted), source, threads,
useExisting, args, ttl, pipelineTraceLevel (trace verbosity for the
run log), name (a display name for the task), and
env (per-run variable overrides). Pass the pipeline config as-is — do not
wrap it in { pipeline: ... }; the client sends it to the server, which resolves
${ROCKETRIDE_*} variables.
Running the same pipeline more than once at a time. Without a custom token,
the server names the task after its owner, project_id and source, so a second
use() of the same pipe fails with Pipeline is already running. Give each
instance its own token and they run side by side:
const { token } = await client.use({ filepath: './pipeline.pipe', token: `tk_${crypto.randomUUID()}` });
The value you choose is the run's
private token: full control of
the run for anyone who presents it. So make it unguessable, and keep the tk_
prefix (without it the token cannot authenticate on webhook or dropper
endpoints). Tokens share one namespace across every user of the server: a
predictable value collides with other people's tasks, and with useExisting a
token that matches a running task attaches to it, whoever started it.
What two instances still share:
- The
pk_public authorization key. Both get the same one, and a webhook call or dropper upload that uses it always reaches the instance that started first. To send data to one specific instance, use that instance'stk_token. getTaskToken(), keyed by the pipe'sproject_idand source, returns only one of them.- The monitor subscription. Both instances' events arrive in one
subscription. Each event carries the emitting run's id in
body.__id(the first eight characters of the token aftertk_, plus the source id); it is truncated and can collide, so treat it as a best-effort way to tell them apart. A few minutes after one instance ends, when the server removes it from its registry, the shared subscription is dropped and the surviving instance's events stop arriving; resubscribe. - The run log, written per identity and not built for two instances at once; treat a forked run's log as unreliable.
Check reused before trusting the result. useExisting returns the
instance that is already running under that token rather than starting the one
you submitted, and the result's reused flag is true when that happened. A
reused instance keeps the configuration it was created with — the pipeline in
this call is ignored, edits included — along with whatever state it has
accumulated. Benchmarks and A/B comparisons are where an unnoticed reuse costs
the most. Call restart() to apply new configuration to a live token.
Why a token: the server runs each pipeline as a separate task. The token
targets send(), sendFiles(), pipe(), chat(), getTaskStatus(), and
terminate() at the correct pipeline.
Watch progress
Poll getTaskStatus(token) — it returns completedCount, totalCount,
completed, state, exitCode, and more. A per-call
{ timeout } option defaults to 15000 ms; pass false to disable the bound:
while (true) {
const status = await client.getTaskStatus(token);
console.log(`Progress: ${status.completedCount}/${status.totalCount}`);
if (status.completed) break;
await new Promise((r) => setTimeout(r, 2000));
}
Events
For push-style progress instead of polling, add a monitor subscription; events
arrive at your onEvent callback:
await client.addMonitor({ token }, ['apaevt_status_upload', 'apaevt_status_processing']);
// ... later:
await client.removeMonitor({ token }, ['apaevt_status_upload', 'apaevt_status_processing']);
addMonitor(key, types) / removeMonitor(key, types) are reference-counted —
adding the same key merges types, removing unsubscribes a type only when its count
reaches zero. The MonitorKey is { token } for a running task, or
{ projectId, source, pipeId?, teamId? } (a team ID addresses that team's deployed
run). The older setEvents(token, eventTypes, pipeId?) still works but is
deprecated in favor of the monitor pair.
Validate before you run
validate({ pipeline, source? }) checks a pipeline config server-side without
starting it and returns errors and warnings — cheap insurance before use().
Stop with terminate()
terminate(token) stops the pipeline and frees server resources. Long-lived tasks
without a ttl run until terminated.
Discover services
getServices() returns lightweight summaries of every service the server
supports (plus a deduplicated icon table and the server version). For a full
definition — config schema included — fetch one by name with getService(name),
which returns a ServiceDefinition and throws on failure (it never resolves to
undefined).
const services = await client.getServices();
const ocr = await client.getService('ocr'); // throws if unknown
Liveness
ping(token?) performs a liveness check and throws on failure; the optional token
scopes the ping to a task.
Deploying a pipeline so it persists server-side and runs on a schedule is a separate surface — see Deployments.