proposal: a step's failure is part of the model — retry, onError and {error}, on a delegate and on a send - #71
Open
iliyan-velichkov wants to merge 1 commit into
Conversation
…{error}, on a delegate and on a send
A process step that calls out fails sometimes, and the format has nothing to say
about it: everything else about the flow is modelled, and what happens when the
work of a step does not succeed is left entirely to the platform's defaults.
The send is the sharpest case, because the format already prescribes the failure
- it says a sending process step SHOULD fail the activity, since the message is
that step's whole purpose - and then offers nothing to handle it. So a flow with
the send ordered where it reads most naturally leaves a document that was issued
correctly sitting in Issued for ever when a mail server is briefly unreachable,
with no error message and no failure status, because the failure was recorded
against the job. The workaround is to make the send the last step, which
constrains process design for a reason unrelated to the domain.
Specifies retry: { count, every }, onError: <step | end> and the {error}
placeholder on the two service-task shapes whose work is such a call, with the
refusals spelled out: a setter step (a gated status write is refused to the
person who acted), a call: or bare step, a fan-out send (fail-soft per row, so
neither key could ever fire - its deliveries are observed with outcome: and
onNotifyFailed), and any other step kind.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
proposals/0033-step-failure-is-part-of-the-model.md. Noversions/change.Why
A process step that calls out — provision a schema, register a client with an identity provider, ask a partner API, send a document — fails sometimes, and the format has nothing to say about it. Everything else about a flow is modelled: which step follows which, how a decision branches, what a boundary timer does when a task is not worked in time. The one thing left entirely to the platform's defaults is what happens when the work of a step does not succeed — so the model describes the application fully right up to the first failure, and then stops.
The send is the sharpest case, because the version document already prescribes the failure. It says of a delivery failure that "a sending process step SHOULD [fail the activity], since the message is that step's whole purpose" — which is right — and then offers no way to handle it. A failed activity is handled however the engine handles one: some bounded number of automatic attempts, then an incident against the job. The record the process is about is untouched. So a flow ordered the way it reads most naturally (issue → notify → mark sent) leaves a document that was issued correctly sitting in
Issuedfor ever when a mail server is briefly unreachable, with no error message and no failure status. It is not visibly wrong; it is invisibly stalled.The available workaround is to make the send the last step, so the worst case is an incident about the message alone. It works, and it constrains process design for a reason that has nothing to do with the domain: the end of a process becomes the only safe place to put a declared send.
What it specifies
retry: { count, every },onError: <step | end>and the whole-value{error}placeholder, on the two service-task shapes whose work is such a call:delegate:and non-fan-outnotify:.The refusals are as much of the proposal as the keys, because a key that is accepted and inert is worse than one that is refused:
setField/setRelationFieldstep — a status write is refused by the model's own gates, and a gated one is refused to the person who acted, in the same interaction; routing that failure away would take the refusal out of their hands, and re-attempting a deterministic refusal recovers nothing;call:step, or a service task carrying neither shape;notifywithforEach) — the version already says a fan-out "MUST NOT fail its activity, because a retry would resend", so the step never fails and neither key could ever fire; those deliveries are observed per row with the notify block'soutcome:field and theonNotifyFailedaxis;serviceTask.One rule is worth singling out: the message made readable as
{error}must name the cause, not just the step. It is the only account of the failure the record will carry, and "the message could not be sent" tells an operator nothing the status did not.Declared step data (
vars:+produces:/uses:/clearAfter) shipped alongside this in the reference implementation and is also unspecified here — deliberately out of scope, as a construct of its own.Implementation
Proven out in the reference implementation: eclipse-dirigible/dirigible#7056 (the send half) and #6762 (the delegate half, which shipped earlier and was never proposed here). Covered there at the parser, emission, real-engine and end-to-end layers, including the case that decides whether the widening is safe at all: a handler raising its own business error still reaches its own boundary rather than being retried or re-coded.