use std::sync::Arc;
use tokio::time::Instant;
use crate::Result;
use crate::backend::Backend;
use crate::frontier::seed::Seed;
use crate::http::Request;
use crate::identity::{Health, Identities, Identity, IdentityPool};
pub(crate) struct Connector<B> {
backend: Arc<B>,
identities: Option<IdentityPool>,
}
impl<B: Backend> Connector<B> {
pub(crate) const fn new(backend: Arc<B>) -> Self {
Self {
backend,
identities: None,
}
}
pub(crate) fn with_identities(backend: Arc<B>, identities: Identities) -> Self {
Self {
backend,
identities: Some(IdentityPool::new(identities)),
}
}
pub(crate) fn identify(&self, seed: &Seed, request: &mut Request) -> Result<Option<Identity>> {
let Some(pool) = &self.identities else {
return Ok(None);
};
let identity = pool.choose(seed, Instant::now())?;
identity.apply(request);
Ok(Some(identity))
}
pub(crate) async fn connect(&self, identity: Option<&Identity>) -> Result<B::Session> {
match identity {
Some(identity) => self.backend.connect_as(identity).await,
None => self.backend.connect().await,
}
}
pub(crate) fn finished(&self, identity: &Identity, health: Health) {
if let Some(pool) = &self.identities {
pool.finished(identity, health, Instant::now());
}
}
}