use crate::core::handle::ScanHandle;
use crate::core::models::target::{Target, TargetMap};
use rand::seq::SliceRandom;
use tokio::sync::mpsc;
pub struct Dispatcher {
target_map: TargetMap,
batch_size: usize,
}
impl Dispatcher {
pub fn new(target_map: TargetMap) -> Self {
Self {
target_map,
batch_size: 8192,
}
}
pub fn with_batch_size(mut self, batch_size: usize) -> Self {
self.batch_size = batch_size;
self
}
pub fn run_shuffled(self, scan_handle: &ScanHandle) -> mpsc::Receiver<Target> {
let (tx, rx) = mpsc::channel(self.batch_size * 2);
let scan_handle = scan_handle.clone();
tokio::spawn(async move {
let mut batch = Vec::with_capacity(self.batch_size);
for mut unit in self.target_map.units {
for target in unit.iter() {
batch.push(target);
if batch.len() >= self.batch_size {
batch.shuffle(&mut rand::rng());
for t in batch.drain(..) {
if tx.send(t).await.is_err() || scan_handle.should_stop() {
return;
}
}
}
}
}
if !batch.is_empty() {
batch.shuffle(&mut rand::rng());
for t in batch {
if tx.send(t).await.is_err() || scan_handle.should_stop() {
return;
}
}
}
});
rx
}
}