Axis 03 · Monotonicity: Does it ever go backwards?

An odometer. It only goes up. A version number, a count of processed items, a "last updated" time: values that may only move one way. If one goes back, something has overwritten newer data with older data.

An operation reset the version to zero. An older result silently overwrote a newer one, and nothing said so. In a distributed system this is how a stale write wins.

public static readonly Constraint<Order> VersionNeverGoesBack = Constraints<Order>.Monotonic(o => o.Version, MonotonicDirection.NonDecreasing);
		

For a value kept per key (an entry per repository and branch), MonotonicPerKey.

It runs the operations of the type from many starting orders, and compares the value before and after each. It also checks that some operation actually moved the value; a rule watching a number nothing ever changes is a rule that was never tested.

Monotonicity failed.

Rule broken version-never-goes-back: Expected NonDecreasing but moved from 1 to 0. Operation Reset() Started from Order { Lines = [], Status = Cancelled, Version = 1, Total = 0, Label = "" } Produced Order { Lines = [], Status = Cancelled, Version = 0, Total = 0, Label = "" }

Law No operation moves a value that may only go one way in the other direction. Consequence An older result overwrites a newer one, a counter goes back or a timestamp regresses, without anything saying so.

Smallest case found, after 4 shrinks. To run this case again: .Seed("7ub38ErvzD2a")

How to read this:

  • Rule broken says which way it was allowed to move and how it moved: moved from 1 to 0.
  • Operation is Reset(). Started from and Produced differ only in the version.

A scenario test checks the version after one operation. It does not check, for every operation from every state, that the version never decreases.

In docs-builder, a rule says an entry of the link registry never moves back to an older update time, and the operation that adds an entry is tested against it.


Previous: 02 Idempotency · Next: 04 Conservation · All nine axes