use tokio::sync::mpsc;
use tokio::sync::mpsc::UnboundedSender;
use uuid::Uuid;
#[derive(Debug, Clone)]
pub struct QueueItem<T> {
id: Uuid,
#[allow(dead_code)]
input: T,
#[allow(dead_code)]
sequence_length: usize,
sender: mpsc::UnboundedSender<T>
}
impl<T> QueueItem<T> {
#[allow(dead_code)]
pub fn new(input: T, sequence_length: usize, sender: mpsc::UnboundedSender<T>) -> Self {
Self {
input,
id: Uuid::new_v4(),
sequence_length,
sender,
}
}
#[allow(dead_code)]
pub fn sender(&self) -> &mpsc::UnboundedSender<T> {
&self.sender
}
#[allow(dead_code)]
pub fn increment_sequence_length(&mut self, amount: usize) {
self.sequence_length += amount
}
#[allow(dead_code)]
pub fn len(&self) -> usize {
self.sequence_length
}
#[allow(dead_code)]
pub fn is_empty(&self) -> bool {
self.sequence_length == 0
}
#[allow(dead_code)]
pub fn id(&self) -> Uuid {
self.id
}
#[allow(dead_code)]
pub fn input(&self) -> &T {
&self.input
}
#[allow(dead_code)]
pub fn max_seq_len_for_batch_items(
batch_items: &[QueueItem<T>]
) -> usize {
batch_items.iter()
.map(|item| item.len())
.max()
.unwrap_or(0)
}
}
impl<T> PartialEq for QueueItem<T> {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl<T> Eq for QueueItem<T> {}
impl<T> AsRef<UnboundedSender<T>> for QueueItem<T> {
fn as_ref(&self) -> &UnboundedSender<T> {
&self.sender
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_new_queue_item() {
let (tx, mut rx) = mpsc::unbounded_channel::<String>();
let input = String::from("test input");
let sequence_length = 5;
let item = QueueItem::new(input.clone(), sequence_length, tx);
assert_eq!(item.len(), sequence_length);
assert_eq!(*item.input(), input);
assert!(!item.is_empty());
item.sender().send(String::from("response")).unwrap();
let received = rx.recv().await.unwrap();
assert_eq!(received, "response");
}
#[test]
fn test_increment_sequence_length() {
let (tx, _rx) = mpsc::unbounded_channel::<String>();
let mut item = QueueItem::new(String::from("test"), 10, tx);
item.increment_sequence_length(5);
assert_eq!(item.len(), 15);
item.increment_sequence_length(7);
assert_eq!(item.len(), 22);
}
#[test]
fn test_is_empty() {
let (tx, _rx) = mpsc::unbounded_channel::<String>();
let item_empty = QueueItem::new(String::from("test"), 0, tx.clone());
assert!(item_empty.is_empty());
let item_not_empty = QueueItem::new(String::from("test"), 1, tx);
assert!(!item_not_empty.is_empty());
}
#[test]
fn test_equality() {
let (tx1, _rx1) = mpsc::unbounded_channel::<String>();
let (tx2, _rx2) = mpsc::unbounded_channel::<String>();
let item1 = QueueItem::new(String::from("test1"), 5, tx1);
let item2 = QueueItem::new(String::from("test2"), 10, tx2);
assert_eq!(item1, item1);
assert_ne!(item1, item2);
}
#[test]
fn test_max_seq_len_for_batch_items() {
let (tx, _rx) = mpsc::unbounded_channel::<String>();
let item1 = QueueItem::new(String::from("test1"), 5, tx.clone());
let item2 = QueueItem::new(String::from("test2"), 10, tx.clone());
let item3 = QueueItem::new(String::from("test3"), 7, tx);
let items = vec![item1, item2, item3];
let max_len = QueueItem::max_seq_len_for_batch_items(&items);
assert_eq!(max_len, 10);
}
#[test]
fn test_max_seq_len_empty_batch() {
let empty_batch: Vec<QueueItem<String>> = vec![];
let max_len = QueueItem::max_seq_len_for_batch_items(&empty_batch);
assert_eq!(max_len, 0);
}
#[test]
fn test_as_ref_implementation() {
let (tx, _rx) = mpsc::unbounded_channel::<String>();
let item = QueueItem::new(String::from("test"), 5, tx);
let sender_ref: &mpsc::UnboundedSender<String> = item.as_ref();
assert!(std::ptr::eq(sender_ref, item.sender()));
}
}