Since #6846 both settlement handlers - <Name>OnPayment (create topic) and <Name>OnPaymentUpdated (-updated topic) - contain the release branch, and both trust the AMOUNT carried in the message payload rather than re-reading the store.
The two handlers are subscribers on two different topics with no cross-topic ordering guarantee, so:
- payment created at 100 - create event published;
- quick upward correction to 150 -
-updated published;
OnPaymentUpdated delivers first and allocates 150;
- the DELAYED create event (payload pot = 100) computes
pot - allocated = -50 and releases 50 - the payment sits under-allocated until the next payment event re-converges it.
Milliseconds-scale window and self-healing, but new with #6846: before it, the create-only handler was floored at zero (.max(BigDecimal.ZERO)) and could never shrink allocations.
The Rollup template is deliberately stale-proof by recomputing from the store; the settlement parses the payload because a cross-model payment is a projection with no local repository to re-read. Options that keep that constraint:
- re-read the payment through its repository when the payment is LOCAL (the common case), keeping the payload only for cross-model sources;
- make the create handler allocation-only again (never release) - a create event can only ever be the FIRST word about a payment, so it has nothing to release that it should;
- both: the second is a one-line floor restore and closes the race outright, the first improves the updated handler's accuracy too.
Follow-up to #6846.
Since #6846 both settlement handlers -
<Name>OnPayment(create topic) and<Name>OnPaymentUpdated(-updatedtopic) - contain the release branch, and both trust the AMOUNT carried in the message payload rather than re-reading the store.The two handlers are subscribers on two different topics with no cross-topic ordering guarantee, so:
-updatedpublished;OnPaymentUpdateddelivers first and allocates 150;pot - allocated = -50and releases 50 - the payment sits under-allocated until the next payment event re-converges it.Milliseconds-scale window and self-healing, but new with #6846: before it, the create-only handler was floored at zero (
.max(BigDecimal.ZERO)) and could never shrink allocations.The Rollup template is deliberately stale-proof by recomputing from the store; the settlement parses the payload because a cross-model payment is a projection with no local repository to re-read. Options that keep that constraint:
Follow-up to #6846.