use std::fmt;
use std::sync::Arc;
use super::MockSite;
use crate::backend::Backend;
use crate::dataset::{Data, Dataset, Datasets};
use crate::frontier::queue::Queue;
use crate::frontier::seed::Seed;
use crate::frontier::{Frontier, InMemFrontier};
use crate::worker::{Outcome, Worker};
use crate::{Context, Result};
pub struct Visit {
site: MockSite,
seed: Seed,
frontier: Arc<InMemFrontier>,
datasets: Arc<Datasets>,
}
impl Visit {
pub(super) fn new(site: MockSite, seed: Seed) -> Self {
Self {
site,
seed,
frontier: Arc::new(InMemFrontier::fifo()),
datasets: Arc::default(),
}
}
#[must_use]
pub fn with_dataset<T, D>(mut self, dataset: D) -> Self
where
T: Send + 'static,
D: Dataset<T>,
{
Arc::make_mut(&mut self.datasets).insert(dataset);
self
}
pub async fn run<W: Worker<<MockSite as Backend>::Session>>(&self, worker: &W) -> Outcome {
let client = match self.site.connect().await {
Ok(client) => client,
Err(error) => return Outcome::Fail(error),
};
let request = self.seed.clone().into_request();
let queue = Queue::new(Arc::clone(&self.frontier)).child_of(&request);
let cx = Context::from_parts(request, client, queue, Arc::clone(&self.datasets));
worker.handle(cx).await
}
#[must_use]
pub fn queued(&self) -> Vec<Seed> {
self.frontier.snapshot().unwrap_or_default()
}
pub fn dataset<T: Send + 'static>(&self) -> Result<Data<T>> {
self.datasets.get()
}
}
impl fmt::Debug for Visit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Visit")
.field("seed", &self.seed)
.field("queued", &self.frontier.size_hint())
.finish_non_exhaustive()
}
}