Problem/Motivation
A consumer brackets the payment round-trip around kessai's events: it holds whatever it must protect when the handoff is announced, and releases it when an outcome that took no money is announced. Both halves hang off the payment, which is where they belong, and neither is the workflow's to know about.
The payment step's own timeout is the one road that announces nothing. It is a backstop, since the payer's real clock is the payment's and is cut short to land first, so ordinarily the payment resolves and the step is resumed by its own outcome. When the backstop fires instead, no payment event exists, so the consumer's release never runs. The only way to get it to run has been to draw a release step on an outgoing edge of the workflow, which puts one half of the bracket on the diagram while the other half stays invisible, and obliges every consumer to model the same cleanup by hand.
The step also has no documented vocabulary for the outcomes it is resumed with. PaymentWorkflowBridge announces paid and expired as bare strings, and they are not the visitor-initiated outcomes signalOutcomes() lists, so an author has nothing to route on but the source.
Proposed resolution
Add a payment_lapsed timeout action. It makes the payment lapse for real, through the one expire() the reaper calls, and lets the consumer's bracket close the way it always does, so no workflow needs a release step and a window closing by either road leaves the run in the same place through the same flow.
It will not claim that no money moved. For a payment the provider has already seen, only the provider can say, and there is no way to ask here without duplicating the reaper's budget and deferral rules, nor any provider-side way to abandon a session nobody answered. Such a payment is left alone and the token left parked: its deadline has already passed, so the next reaper run asks and either answer resumes the token. What the action does end are the two cases nothing else will: a payment that never reached a provider, where no money can have moved, and a step whose payer never asked to pay, which would otherwise sit parked for ever because an instance- or node-anchored timeout is a one-shot the sweep does not re-arm.
Also declare the two outcomes the bridge announces as constants on the payment interaction, and use them in the bridge, so the vocabulary has one source.
Remaining tasks
- The timeout action and the outcome constants.
- Tests: a lapsed window resumes the step by either road; a payment the provider has seen is neither expired nor routed on; a step with no payment is not left parked.
- Documentation.
Issue fork orchestra-3615627
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
Comment #4
mably commented