startOrEnqueueRun
@forge/monorepo / backend/src / startOrEnqueueRun
Function: startOrEnqueueRun()
startOrEnqueueRun(
coordinator,input):Promise<"queued"|"started">
Defined in: backend/src/runtime/serialization.ts:26
Start runId now if the conversation is free, else enqueue it FIFO. Returns whether it started.
The claim-or-enqueue is atomic, so two runs racing to start the same conversation cannot both win,
and a run can never slip into an idle-but-unclaimed slot and strand itself.
Parameters
coordinator
input
conversationId?
Absent for a run that belongs to no conversation — #198.
Then no slot is claimed at all, and the run is admitted directly. The SPEC first proposed a tenant-level slot for these; that was wrong and is corrected here. A tenant-level slot would serialise every automation a tenant owns — two unrelated webhooks would queue behind each other for no reason — and the reason there is a conversation slot in the first place is that turns in one conversation have an order a person can see. An automation has no such ordering requirement.
Concurrency for these runs is bounded where it should be: the worker's own limits, and quotas.
eventLog?
The durable log, so admission is observable — #170.
run.queued was in RUN_EVENT_TYPES, mapped to a telemetry span, and mapped by the frontend reducer to
the status queued — and nothing emitted it. So a client subscribing to a run saw nothing at all
between sending a message and a worker picking it up: the one moment where "queued" is the only true
thing to say, and the state the reducer had a case for could never be reached.
Emitted here rather than by each caller because admission is the event. Two hosts emitting their own would be two answers to "when was this queued", and the one that forgot would look like a hang.
Optional: a caller with no log still admits runs. Sequence 1 by definition — admission is the first thing that happens to a run, and the worker reconciles from the log before emitting, so its own first event continues from here rather than colliding.
now?
() => string
runId
tenantId
Returns
Promise<"queued" | "started">