# Long-running coordination

A process that waits for several things over time, such as an order
waiting for both payment and stock, needs no workflow language. Keep its
progress in an ordinary entity, let each subscriber record one step on
it, and let a schedule handle deadlines.

Here `record_payment` sets `paid_at` on the order. If stock is already
reserved, it also sets the order's status to ready and emits
`OrderReady`. `cancel_expired_orders` cancels orders left unpaid too
long:

```jadpo
// domains/ordering/subscribers/on_payment_succeeded.jadpo
subscriber on_payment_succeeded {
    on: PaymentSucceeded
    run: record_payment(event.order_id)
}

// domains/ordering/actions/record_payment.jadpo
action record_payment(order_id: Order.id) fails OrderNotFound -> Unit {
    ...
}

// domains/ordering/schedules/cancel_unpaid_orders.jadpo
schedule cancel_unpaid_orders {
    every: 5m
    run: cancel_expired_orders()
}
```

The state is in the database, so it survives restarts and deploys, and
you can query it and show it in an admin screen. Two steps arriving
together can't both complete the order, because every write checks
whether the record changed since it was read
([All-or-nothing actions](all-or-nothing-actions-and-concurrent-changes.md)).
