use std::sync::{Arc, RwLock};
#[derive(Clone, Debug)]
pub(crate) enum PrecommitTokenTracker {
NoOp,
Track(Arc<RwLock<Option<crate::model::MultiplexedSessionPrecommitToken>>>),
}
impl PrecommitTokenTracker {
pub(crate) fn new() -> Self {
Self::Track(Arc::new(RwLock::new(None)))
}
pub(crate) fn new_noop() -> Self {
Self::NoOp
}
pub(crate) fn update(&self, token: Option<crate::model::MultiplexedSessionPrecommitToken>) {
if let (Some(token), Self::Track(tracker)) = (token, self) {
let mut guard = tracker.write().unwrap();
if guard.as_ref().is_none_or(|c| c.seq_num < token.seq_num) {
*guard = Some(token);
}
}
}
pub(crate) fn get(&self) -> Option<crate::model::MultiplexedSessionPrecommitToken> {
let Self::Track(tracker) = self else {
return None;
};
tracker.read().unwrap().clone()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::model::MultiplexedSessionPrecommitToken;
#[test]
fn auto_traits() {
static_assertions::assert_impl_all!(PrecommitTokenTracker: Send, Sync, std::fmt::Debug);
}
#[test]
fn test_noop_tracker() {
let tracker = PrecommitTokenTracker::new_noop();
assert!(
tracker.get().is_none(),
"NoOp tracker should not return a token"
);
tracker.update(Some(MultiplexedSessionPrecommitToken::new().set_seq_num(1)));
assert!(
tracker.get().is_none(),
"NoOp tracker should ignore updates"
);
}
#[test]
fn test_tracker_update_highest_seq() {
let tracker = PrecommitTokenTracker::new();
assert!(tracker.get().is_none(), "Tracker should initially be empty");
let token1 = MultiplexedSessionPrecommitToken::new()
.set_precommit_token(bytes::Bytes::from("token1"))
.set_seq_num(1);
tracker.update(Some(token1));
let retrieved = tracker.get().expect("expected token to be tracked");
assert_eq!(retrieved.precommit_token, "token1");
assert_eq!(retrieved.seq_num, 1);
let token0 = MultiplexedSessionPrecommitToken::new()
.set_precommit_token(bytes::Bytes::from("token0"))
.set_seq_num(0);
tracker.update(Some(token0));
let retrieved = tracker.get().expect("expected token 1 to be retained");
assert_eq!(retrieved.precommit_token, "token1");
assert_eq!(retrieved.seq_num, 1);
let token2 = MultiplexedSessionPrecommitToken::new()
.set_precommit_token(bytes::Bytes::from("token2"))
.set_seq_num(2);
tracker.update(Some(token2));
let retrieved = tracker.get().expect("expected token 2 to be tracked");
assert_eq!(retrieved.precommit_token, "token2");
assert_eq!(retrieved.seq_num, 2);
tracker.update(None::<MultiplexedSessionPrecommitToken>);
let retrieved = tracker.get().expect("expected token 2 to be unmodified");
assert_eq!(retrieved.precommit_token, "token2");
assert_eq!(retrieved.seq_num, 2);
}
}