Canceling or moving a step¶
A request was approved by mistake, and it now waits at Notify the requester. On the instance's page, the operator opens Move to another step on that row, picks Approve, and clicks Move. The notification task is canceled, and the approval is asked for again, as if the request had just arrived there.
An operator can change a step that is waiting in two ways, from the process trace on the instance's page:
- Move to another step: the step is canceled, and the step chosen starts.
- Cancel step: the step is canceled, and the rest of the instance goes on.
Both need the Cancel and move steps of running Orchestra instances permission. It is restricted: a move skips work the workflow expected, and nothing in the workflow decided it.
Which steps can be changed¶
A step that waits: a task waiting for a person, a step waiting for an event or for a program's job, a step waiting for its child. Not:
- a timer, which waits for its deadline: Fire timer now fires it;
- a handler waiting for its trigger;
- a step on an incident: its own actions resolve it (see Resolving an incident);
- a branch waiting at a join.
Starting a step beside the rest¶
A step cannot be started on its own, except a handler waiting for its trigger: Signal on its row fires it, as its event, its deadline or its person would. A handler that does not interrupt starts its branch beside the rest; one that interrupts cancels the rest. Signal needs the Administer Orchestra permission.
So a step an operator may need to start at any time, such as Ask the requester for more information, is drawn as a handler that does not interrupt.
Moving a step¶
The step is left as when it is canceled. Its task is canceled, and the people it was offered to are told so. Its timers stop, and its child, if it waits on one, is canceled.
The step chosen then starts on a new token, as on any arrival: its task is offered, its timers are armed, its child is started. The new token goes on from the old one, so it reads the same values: the variables of its branch, the item of a split creating one branch per item, and those of the embedded child it runs in.
Where a step can go¶
The form offers only the steps where the moved token stands as a token arriving there would. A step in a parallel section belongs to a branch, and the join at the end of the section counts it. So a step can go:
- anywhere outside every parallel section, from a step outside them: back to an earlier step, or forward past a step, across any choice of one way;
- inside the same parallel section, from a step inside it, in its own branch or in another one.
For example, a split sends a request to Check the budget then Approve the budget, and, in parallel, to Check the law. The branches meet before Sign:
| The step waiting | It can go to |
|---|---|
| Approve the budget | Check the budget, Check the law |
| Sign | the steps before the split, and the steps after Sign |
It cannot go to:
- a step in another parallel section, or out of its own: the join ahead would wait for a branch that is not there any more, or count one it does not wait for;
- a step where branches meet, nor a split that waits for its incoming branches, as a parallel gateway does;
- a handler;
- a step of another embedded child, or of the workflow around the child it runs in;
- a step a loop takes round a join, from after the join back into the branches: there, a token stands inside the branches or after the join depending on how it came.
When no step qualifies, the form says so.
Moving a step to another branch¶
Moving a step to a step of another branch of the same parallel section keeps it in its own branch: the join counts it as that branch, wherever it arrives from. The other branch's step then runs twice, once for each branch.
Canceling a step¶
The step is canceled as if a join had no more use for it: its task is canceled and its people are told so. The joins it was on its way to go on without it, or stop on an incident when they can no longer fire (see A join that can no longer fire).
The last step running in the instance cannot be canceled: the instance would end as completed, when nobody completed it. To stop the instance, cancel the instance. A handler waiting for its trigger, and the timers of the step, do not count as running steps.
The same goes for the last step running in an embedded child: the child would end as completed, and the instance would go on past it, even when other steps of the instance run beside the child. To end the child there, move the step to the child's end.
The audit trail¶
A canceled step is recorded as canceled, with the reason canceled by an operator. A moved step is recorded as canceled, with the reason moved to another step, then as moved, with the step it went to and the new token.
From code¶
To move a step back to n_approve:
$engine = \Drupal::service('orchestra_engine.engine');
// The steps the token can go to, by node ID: empty when the step cannot be
// changed.
$targets = $engine->listMoveTargets($token);
if (in_array('n_approve', $targets, TRUE)) {
// FALSE when the step was completed meanwhile.
$moved = $engine->moveStep($token, 'n_approve');
}
To cancel a step instead:
if ($engine->canChangeStep($token)) {
// FALSE when it is the last step running, in the instance or in its
// embedded child.
$canceled = $engine->cancelStep($token);
}
moveStep() throws an \InvalidArgumentException for a step
listMoveTargets() does not list.