use dashmap::DashMap;
use pushwire_core::ChannelKind;
use std::collections::HashMap;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CursorResult {
Sequential,
GapDetected { expected: u64, got: u64 },
Duplicate,
}
pub struct CursorTracker<C: ChannelKind> {
cursors: DashMap<C, u64>,
}
impl<C: ChannelKind> CursorTracker<C> {
pub fn new() -> Self {
Self {
cursors: DashMap::new(),
}
}
pub fn advance(&self, channel: C, cursor: u64) -> CursorResult {
let prev = self.cursors.get(&channel).map(|v| *v).unwrap_or(0);
if cursor == prev + 1 || prev == 0 {
self.cursors.insert(channel, cursor);
CursorResult::Sequential
} else if cursor > prev + 1 {
self.cursors.insert(channel, cursor);
CursorResult::GapDetected {
expected: prev + 1,
got: cursor,
}
} else {
CursorResult::Duplicate
}
}
pub fn export(&self) -> HashMap<C, u64> {
self.cursors
.iter()
.map(|entry| (*entry.key(), *entry.value()))
.collect()
}
pub fn reset(&self) {
self.cursors.clear();
}
}
impl<C: ChannelKind> Default for CursorTracker<C> {
fn default() -> Self {
Self::new()
}
}