use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::Semaphore;
use crate::error::Result;
use crate::RedfishClient;
#[derive(Debug)]
pub struct HostResult<T> {
pub host: String,
pub result: Result<T>,
}
pub struct RedfishPool {
clients: HashMap<String, RedfishClient>,
concurrency: Arc<Semaphore>,
}
impl RedfishPool {
pub fn new(max_concurrent: usize) -> Self {
Self {
clients: HashMap::new(),
concurrency: Arc::new(Semaphore::new(max_concurrent)),
}
}
pub fn add(&mut self, host: &str, username: &str, password: &str) -> Result<()> {
let client = RedfishClient::new(host, username, password)?;
self.clients.insert(host.to_string(), client);
Ok(())
}
pub fn add_client(&mut self, host: &str, client: RedfishClient) {
self.clients.insert(host.to_string(), client);
}
pub fn remove(&mut self, host: &str) {
self.clients.remove(host);
}
pub fn hosts(&self) -> Vec<&str> {
self.clients.keys().map(|s| s.as_str()).collect()
}
pub async fn login_all(&mut self) -> Vec<HostResult<()>> {
let hosts: Vec<String> = self.clients.keys().cloned().collect();
let mut results = Vec::new();
for host in hosts {
let _permit = self.concurrency.acquire().await.unwrap();
let result = if let Some(client) = self.clients.get_mut(&host) {
client.login().await
} else {
continue;
};
results.push(HostResult { host, result });
}
results
}
pub async fn logout_all(&mut self) {
for client in self.clients.values_mut() {
let _ = client.logout().await;
}
}
pub fn get(&self, host: &str) -> Option<&RedfishClient> {
self.clients.get(host)
}
pub fn get_mut(&mut self, host: &str) -> Option<&mut RedfishClient> {
self.clients.get_mut(host)
}
pub async fn for_each<F, Fut, T>(&self, op: F) -> Vec<HostResult<T>>
where
F: Fn(&RedfishClient) -> Fut,
Fut: std::future::Future<Output = Result<T>>,
{
let mut results = Vec::new();
for (host, client) in &self.clients {
let _permit = self.concurrency.acquire().await.unwrap();
let result = op(client).await;
results.push(HostResult { host: host.clone(), result });
}
results
}
}