distkit
Concepts

Comparators

CounterComparator drives conditional counter writes.

Conditional operations (inc_if, set_if, and their batch forms) let you change a counter only when its current value satisfies a condition - atomically, on the Redis side, with no read-modify-write race.

The condition is a CounterComparator:

pub enum CounterComparator {
    Eq(i64), // current == value
    Lt(i64), // current <  value
    Gt(i64), // current >  value
    Ne(i64), // current != value
    Nil,     // always matches
}

Nil is the "no condition" variant - it always passes, which is handy in batches where some entries are conditional and others are not.

How conditional writes report back

inc_if and set_if return (new, old):

  • If the comparison passed, the write happened and new is the updated value.
  • If it failed, nothing changed and new == old.

So you can tell whether the condition held by checking whether the two values differ.

use distkit::CounterComparator;

strict.set(&key, 10).await?;

// 10 == 10, so this applies: returns (15, 10).
assert_eq!(strict.inc_if(&key, CounterComparator::Eq(10), 5).await?, (15, 10));

// 15 is not > 20, so this is a no-op: returns (15, 15).
assert_eq!(strict.set_if(&key, CounterComparator::Gt(20), 99).await?, (15, 15));

The same comparator type is used by the instance-aware counters, where the comparison is made against the cumulative total (or, for set_on_instance_if, the calling instance's slice). See Conditional & batch operations for the batch forms.