A run carries an optional first-class correlation key, the business key an external event resolves it by: a payment return, an inbound message. WorkflowExecutor::start() takes one, and the engine looks runs up by it, scoped to the acting tenant and to runs still running, so an event reaches the process that is actually waiting for it.

The HTTP API does not carry it. startProcess() takes variables, an idempotency key and an initiator; there is no field for a correlation key, and nothing on the receiving side passes one to the engine. So a run started over the API has an empty correlation key for its whole life. It can be read back, since getInstance() returns the field and the OpenAPI document describes it in the response, but there is no way to put anything there.

That removes correlation from exactly the runs that most need it, which are the runs somebody else asked for: a caller starts one because its own system has work to track, and that system knows the work by its own reference and never by the id Orchestra minted here. The key cannot be set after the fact either: it is a start-time value, and the API exposes no write for it.

A child started by a subprocess step has the same problem for a different reason. It is started by the step, not by a caller holding a reference, and the step reads only what is on the parent, so nothing names it. An event that knows the work by a business reference resolves the parent or nothing at all, and on a remote child there is no parent on that site to resolve.

Proposed resolution

startProcess() carries an optional correlation key, the start endpoint validates and forwards it, and the published contract describes it on the request as it already does on the response. It is bounded by the 255-character column the engine clamps to, and the API refuses a longer one rather than storing a key the caller will never find the run by.

Both subprocess steps take a correlation_variable: the name of a parent variable whose value names the child. The rule lives once, in the trait the two steps already share for their input and output maps, so a child is named alike whether it runs here or on another Orchestra, and the step reads the value out of the variables it already loads for that map, so it costs no query and nothing at all when the field is empty.

The field unset, a variable the run does not carry, a value that is not a scalar, or an empty string: the child starts without a name, which is what every child did before. A value too long for the column stops the launch with an incident instead of being cut to fit, on both steps, because a name cut short is one the child's own event would never match and a child quietly left unnamed loses that event just as silently.

This is not the idempotency key and should not be confused with it. The idempotency key answers whether this start request has already been served: it is read once, before anything is created, and must resolve to at most one run. The correlation key answers which live run an external event is about: it is read for as long as the run is running, and several runs may legitimately share one.

AI-Generated: Yes (Claude Code was used to help draft this issue summary and to write the code and tests on the merge request. I reviewed and ran the work myself before posting it.)

Issue fork orchestra-3624248

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

mably created an issue. See original summary.

mably’s picture

Status: Active » Needs review
mably’s picture

Title: Let a caller set a run's correlation key when it starts one over the API » Let a caller name the run it starts over the API, and a subprocess step name its child
Issue summary: View changes

  • mably committed 9364bb18 on 1.x
    feat: #3624248 Let a caller name the run it starts over the API, and a...
mably’s picture

Status: Needs review » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.