Counters
Overview
Distributed integer counters in strict and lax flavors, both behind one trait.
Counters are distkit's default feature. They are distributed i64 counters keyed by a DistkitRedisKey, stored in a Redis hash under the prefix you give them.
There are two implementations, and they share the same interface:
StrictCounter- every call is atomic and immediately consistent.LaxCounter- increments buffer locally and flush on an interval.
Pick between them based on the strict vs lax trade-off.
The shared trait
Both implement CounterTrait. Bring it into scope to call any of these:
pub trait CounterTrait {
async fn inc(&self, key: &DistkitRedisKey, count: i64) -> Result<i64, DistkitError>;
async fn dec(&self, key: &DistkitRedisKey, count: i64) -> Result<i64, DistkitError>;
async fn get(&self, key: &DistkitRedisKey) -> Result<i64, DistkitError>;
async fn set(&self, key: &DistkitRedisKey, count: i64) -> Result<i64, DistkitError>;
async fn del(&self, key: &DistkitRedisKey) -> Result<i64, DistkitError>;
async fn clear(&self) -> Result<(), DistkitError>;
// Conditional - return (new, old).
async fn inc_if(&self, key: &DistkitRedisKey, cmp: CounterComparator, count: i64)
-> Result<(i64, i64), DistkitError>;
async fn set_if(&self, key: &DistkitRedisKey, cmp: CounterComparator, count: i64)
-> Result<(i64, i64), DistkitError>;
// Batch - preserve input order.
async fn get_all(&self, keys: &[&DistkitRedisKey]) -> Result<Vec<(&DistkitRedisKey, i64)>, DistkitError>;
async fn inc_all(&self, updates: &[(&DistkitRedisKey, i64)]) -> Result<Vec<(&DistkitRedisKey, i64)>, DistkitError>;
async fn set_all(&self, updates: &[(&DistkitRedisKey, i64)]) -> Result<Vec<(&DistkitRedisKey, i64)>, DistkitError>;
async fn inc_all_if(&self, updates: &[(&DistkitRedisKey, CounterComparator, i64)])
-> Result<Vec<(&DistkitRedisKey, i64, i64)>, DistkitError>;
async fn set_all_if(&self, updates: &[(&DistkitRedisKey, CounterComparator, i64)])
-> Result<Vec<(&DistkitRedisKey, i64, i64)>, DistkitError>;
}
Constructing
Both take CounterOptions and return an Arc:
use distkit::{DistkitRedisKey, counter::{CounterOptions, StrictCounter}};
let prefix = DistkitRedisKey::try_from("my_app".to_string())?;
let options = CounterOptions::new(prefix, conn); // conn: ConnectionManager
let counter = StrictCounter::new(options); // Arc<StrictCounter>
CounterOptions also carries allowed_lag (default ~20 ms), which only matters for the lax counter's flush interval.

