Axis 02 · Idempotency: Does doing it twice change anything?
Pressing the lift button twice. The lift still comes once. An operation is idempotent when doing it again changes nothing: cancelling a cancelled order leaves it cancelled and untouched.
Cancelling an order that was already cancelled bumped its version again. A retry after a timeout, a user double-clicking, a message delivered twice: each one changed the state a second time, so the order ended up different from a single run.
public static readonly Constraint<Order> CancelIsRepeatable = Constraints<Order>.Idempotent(o => o.Cancel());
It makes many orders, applies the operation, applies it again to the result, and compares the two. It also checks that the operation changed at least some of the orders: if it never changed any, the test would pass without proving anything, so it fails as vacuous instead.
Idempotency failed.
Rule broken cancel-is-repeatable: doing it twice is not the same as doing it once. Started from Order { Lines = [], Status = Pending, Version = 0, Total = 0, Label = "" } Once gave Order { Lines = [], Status = Cancelled, Version = 1, Total = 0, Label = "" } Twice gave Order { Lines = [], Status = Cancelled, Version = 2, Total = 0, Label = "" }
Law Doing an operation twice gives what doing it once gives, for every generated value. Consequence A retry, a double submit or a re-run changes the state a second time, so it ends up different from a single run.
This is the smallest case: nothing smaller failed. To run this case again: .Seed("0N0XIzNsQ0O2")
How to read this:
- Started from is the order before the operation.
- Once gave is the order after one cancel. Twice gave is the order after cancelling that again. They differ (the version), and they must not.
An example test calls the operation once and checks the result. Calling it twice is a different test, and it only gets written by someone who has been bitten by retries.
In docs-builder, applying a changelog bundle's amends twice used to give a different bundle from applying them once.
Previous: 01 Invariant · Next: 03 Monotonicity · All nine axes