distkit
Instance-aware counters

LaxInstanceAwareCounter

Buffered per-instance counting for high-frequency updates.

LaxInstanceAwareCounter is a buffered wrapper around StrictInstanceAwareCounter. inc and dec accumulate locally and flush to the strict counter in bulk every flush_interval (default ~20 ms). Global operations (set, del, clear) flush any pending delta first, then delegate immediately.

Reach for it when you have many inc/dec calls per second per node and can tolerate a small consistency lag.

Construct

use std::time::Duration;
use distkit::DistkitRedisKey;
use distkit::icounter::{
    InstanceAwareCounterTrait,
    LaxInstanceAwareCounter, LaxInstanceAwareCounterOptions,
};

let prefix = DistkitRedisKey::try_from("my_app".to_string())?;
let counter = LaxInstanceAwareCounter::new(LaxInstanceAwareCounterOptions {
    prefix,
    connection_manager: conn,
    dead_instance_threshold_ms: 30_000,
    flush_interval: Duration::from_millis(20),
    allowed_lag:    Duration::from_millis(20),
});

LaxInstanceAwareCounterOptions::new(prefix, conn) fills these with defaults if you don't need to tune them.

Operations return the local estimate

let key = DistkitRedisKey::try_from("connections".to_string())?;

// Returns immediately - no Redis round-trip on the warm path.
let (local_total, mine) = counter.inc(&key, 1).await?;
let (local_total, mine) = counter.dec(&key, 1).await?;

// get() also returns the local estimate: cumulative + pending delta.
let (total, mine) = counter.get(&key).await?;

inc, dec, and get reflect your own unflushed deltas immediately. Other instances see them only after the next flush.

Background flushing

Like the lax plain counter, the flush task holds a Weak reference and stops automatically when the last Arc is dropped.

Same cleanup semantics

Because it delegates to the strict counter, dead-instance cleanup works exactly as in the strict variant - a node's slice is reclaimed once it stops heartbeating past the threshold.