use dashmap::DashMap;
use std::sync::atomic::{AtomicU64, Ordering};
#[derive(Debug)]
pub struct SequenceManager {
current_sequence: DashMap<String, u64>,
next_id: AtomicU64,
}
impl SequenceManager {
#[must_use]
pub fn new() -> Self {
Self {
current_sequence: DashMap::new(),
next_id: AtomicU64::new(1),
}
}
pub fn resolve(&self, connection_id: &str, thought_number: u32) -> (u64, bool, Option<u64>) {
if thought_number == 1 {
let previous = self.current_sequence.remove(connection_id).map(|(_, v)| v);
let new_seq = self.next_id.fetch_add(1, Ordering::Relaxed);
self.current_sequence.insert(connection_id.to_string(), new_seq);
log::debug!(
"New sequence {} for connection {} (thought_number=1, previous={:?})",
new_seq,
connection_id,
previous
);
return (new_seq, true, previous);
}
if let Some(entry) = self.current_sequence.get(connection_id) {
let seq_id = *entry;
return (seq_id, false, None);
}
let new_seq = self.next_id.fetch_add(1, Ordering::Relaxed);
self.current_sequence.insert(connection_id.to_string(), new_seq);
log::debug!(
"New sequence {} for connection {} (thought_number={}, no previous)",
new_seq,
connection_id,
thought_number
);
(new_seq, true, None)
}
#[must_use]
pub fn current(&self, connection_id: &str) -> Option<u64> {
self.current_sequence.get(connection_id).map(|r| *r)
}
pub fn cleanup(&self, connection_id: &str) {
if let Some((_, seq_id)) = self.current_sequence.remove(connection_id) {
log::debug!("Cleaned up sequence {} for connection {}", seq_id, connection_id);
}
}
}
impl Default for SequenceManager {
fn default() -> Self {
Self::new()
}
}