flowon failureinvoice v1examples/invoice/invoice.flow · dandori doc
An order holds its goods until its payment is due, then ships them once paid, or puts them back
flowon failure| Line | Call | Calls | Retries | Timeout | When it fails | Case after |
|---|---|---|---|---|---|---|
| 56 | hold ← reserve(…) | book stock.reserve.hold, starts stock.reserve | — | — | out_of_stock → line 57timeout, failure → on failure | hold: held |
| 58 | due = terms.payment(…) | the date payment of payment_terms.cal | 2 times, after 1 second and 2 (failure) | — | timeout, failure → on failure | — |
| 60 | payment = check_payment(…) | GET https://payments.example.com/orders/{order}/payment, idempotent | 2 times every 10 seconds (failure, timeout) | — | timeout, failure → on failure | — |
| 63 | hold ← ship(…) | book stock.reserve.post, sends post | — | — | expired → line 64timeout, failure → on failure | hold: posted |
| 67 | hold ← put_back(…) | book stock.reserve.void, sends void | — | — | expired → line 68already_posted, timeout, failure → on failure | hold: voided |
| 75 | hold ← put_back(…) | book stock.reserve.void, sends void | — | — | expired → line 76already_posted → line 77timeout, failure → line 78 | hold: voided |
| Line | End | hold |
|---|---|---|
| 57 | succeed outcome = out_of_stock, due = none | not started |
| 64 | succeed outcome = not_paid, due = due.day | expired |
| 65 | succeed outcome = shipped, due = due.day | posted |
| 69 | succeed outcome = not_paid, due = due.day | voided, expired |
| 78 | fail NotPutBack "the goods held for the order could not be put back" leaving hold | handed over as it is: held, posted, voided, expired |
| 78 | on failure runs to its end, and the workflow fails with the error that started it | not started, or posted, voided, expired |
Pick a step to see what the checker knows there. Pick a scenario on the left to light up the way its run goes; the number beside a step is how often the run passes it.
invoice v1An order holds its goods until its payment is due, then ships them once paid, or puts them back
order: Orderoutcome: Outcome, due: date?examples/invoice/invoice.flowhold ← reserve(…) line 5656 hold <- reserve(order: order.id, sku: order.sku, qty: order.quantity) 57 on out_of_stock => succeed outcome = out_of_stock, due = none
hold: not startedbook stock.reserve.hold, starts stock.reserveout_of_stock → line 57timeout, failure → on failurehold: held29 # The book holds the goods for the order: chobo's client runs the hold, and a refusal comes back 30 # with the reason the book gives it. 31 task reserve(order: string, sku: string, qty: int) -> stock.reserve 32 book stock.reserve.hold 33 starts stock.reserve 34 errors out_of_stock
succeed outcome = out_of_stock, due = none line 57 57 on out_of_stock => succeed outcome = out_of_stock, due = none
hold: not startedhold: not starteddue = terms.payment(…) line 58 58 let due = terms.payment(received: now)
hold: heldpayment of payment_terms.caltimeout, failure → on failure7 use dates terms from "dates/payment_terms.cal" 8 lambda "arn:aws:lambda:eu-west-2:123456789012:function:payment-terms"
wait until due.at line 59 59 wait until due.at
hold: heldpayment = check_payment(…) line 60 60 let payment = check_payment(order: order.id, due: due.day)
hold: heldGET https://payments.example.com/orders/{order}/payment, idempotenttimeout, failure → on failure46 task check_payment(order: string, due: date) -> Payment 47 http GET "https://payments.example.com/orders/{order}/payment" 48 connection "arn:aws:events:eu-west-2:123456789012:connection/payments/1a2b3c" 49 retry 2 times every 10 seconds 50 idempotent
match payment.paid line 6161 match payment.paid 62 true => 66 false =>
hold: heldhold ← ship(…) line 6363 hold <- ship(order: order.id, sku: order.sku) 64 on expired => succeed outcome = not_paid, due = due.day
hold: heldbook stock.reserve.post, sends postexpired → line 64timeout, failure → on failurehold: posted36 task ship(order: string, sku: string) -> stock.reserve 37 book stock.reserve.post 38 sends post 39 errors expired
succeed outcome = not_paid, due = due.day line 64 64 on expired => succeed outcome = not_paid, due = due.day
hold: expiredhold: expiredsucceed outcome = shipped, due = due.day line 65 65 succeed outcome = shipped, due = due.day
hold: postedhold: postedhold ← put_back(…) line 6767 hold <- put_back(order: order.id, sku: order.sku) 68 on expired => pass
hold: heldbook stock.reserve.void, sends voidexpired → line 68already_posted, timeout, failure → on failurehold: voided41 task put_back(order: string, sku: string) -> stock.reserve 42 book stock.reserve.void 43 sends void 44 errors expired, already_posted
succeed outcome = not_paid, due = due.day line 69 69 succeed outcome = not_paid, due = due.day
hold: voided, expiredhold: voided, expiredend: succeedsThe flow runs to its end, and the workflow succeeds.
on failure line 71Runs when a call fails and nothing at the call handles the error. When it runs to its end, the workflow fails with that error. It comes here from the calls on lines 56, 58, 60, 63 and 67.
match hold.state line 7272 match hold.state 73 none => pass 74 held =>
hold: not started, or held, posted, voided, expiredhold ← put_back(…) line 7575 hold <- put_back(order: order.id, sku: order.sku) 76 on expired => pass 77 on already_posted => pass 78 on failure => fail NotPutBack "the goods held for the order could not be put back" leaving hold
hold: held, posted, voided, expiredbook stock.reserve.void, sends voidexpired → line 76already_posted → line 77timeout, failure → line 78hold: voided41 task put_back(order: string, sku: string) -> stock.reserve 42 book stock.reserve.void 43 sends void 44 errors expired, already_posted
fail NotPutBack line 78 78 on failure => fail NotPutBack "the goods held for the order could not be put back" leaving hold
hold: held, posted, voided, expiredhold: handed over as it is: held, posted, voided, expiredfails with the same erroron failure runs to its end, and the workflow fails with the error that started it.
hold: not started, or posted, voided, expiredhold ← reserve(…) okdue = terms.payment(…) okwait until due.atpayment = check_payment(…) okmatch payment.paid → truehold ← ship(…) oksucceed outcome = shipped, due = due.dayhold ← reserve(…) out_of_stock → on out_of_stocksucceed outcome = out_of_stock, due = nonehold ← reserve(…) failure → not handled hereon failurematch hold.state → nonehold ← reserve(…) okdue = terms.payment(…) failure failure failure → not handled hereon failurematch hold.state → heldhold ← put_back(…) okhold ← reserve(…) okdue = terms.payment(…) failure failure failure → not handled hereon failurematch hold.state → heldhold ← put_back(…) expired → on expiredhold ← reserve(…) okdue = terms.payment(…) okhold ← reserve(…) okdue = terms.payment(…) okwait until due.atpayment = check_payment(…) failure failure failure → not handled hereon failurematch hold.state → heldhold ← put_back(…) expired → on expiredhold ← reserve(…) okdue = terms.payment(…) okwait until due.atpayment = check_payment(…) failure okmatch payment.paid → falsehold ← put_back(…) oksucceed outcome = not_paid, due = due.dayhold ← reserve(…) okdue = terms.payment(…) okwait until due.atpayment = check_payment(…) okhold ← reserve(…) okdue = terms.payment(…) okwait until due.atpayment = check_payment(…) okmatch payment.paid → falsehold ← put_back(…) expired → on expiredsucceed outcome = not_paid, due = due.dayhold ← reserve(…) okdue = terms.payment(…) okwait until due.atpayment = check_payment(…) okmatch payment.paid → truehold ← ship(…) expired → on expiredsucceed outcome = not_paid, due = due.dayhold ← reserve(…) okdue = terms.payment(…) okwait until due.atpayment = check_payment(…) okmatch payment.paid → truehold ← ship(…) expired → on expiredsucceed outcome = not_paid, due = due.dayhold ← reserve(…) okdue = terms.payment(…) okwait until due.atpayment = check_payment(…) okmatch payment.paid → truehold ← ship(…) failure → not handled hereon failurematch hold.state → heldhold ← put_back(…) already_posted → on already_postedhold ← reserve(…) okdue = terms.payment(…) okwait until due.atpayment = check_payment(…) okmatch payment.paid → truehold ← ship(…) oksucceed outcome = shipped, due = due.dayhold ← reserve(…) okdue = terms.payment(…) okwait until due.atpayment = check_payment(…) failure failure failure → not handled hereon failurematch hold.state → heldhold ← put_back(…) failure → on failurefail NotPutBackhold ← reserve(…) okdue = terms.payment(…) failure failure failure → not handled hereon failurematch hold.state → heldhold ← put_back(…) okhold ← reserve(…) okdue = terms.payment(…) okwait until due.atpayment = check_payment(…) failure okmatch payment.paid → falsehold ← put_back(…) expired → on expiredsucceed outcome = not_paid, due = due.dayhold ← reserve(…) okdue = terms.payment(…) okwait until due.atpayment = check_payment(…) failure okmatch payment.paid → falsehold ← put_back(…) failure → not handled hereon failurematch hold.state → heldhold ← put_back(…) okhold ← reserve(…) okdue = terms.payment(…) okwait until due.atpayment = check_payment(…) failure okmatch payment.paid → falsehold ← put_back(…) oksucceed outcome = not_paid, due = due.day