openzeppelin_monitor/repositories/
network.rs#![allow(clippy::result_large_err)]
use std::{collections::HashMap, path::Path};
use async_trait::async_trait;
use crate::{
models::{ConfigLoader, Network},
repositories::error::RepositoryError,
};
#[derive(Clone)]
pub struct NetworkRepository {
pub networks: HashMap<String, Network>,
}
impl NetworkRepository {
pub async fn new(path: Option<&Path>) -> Result<Self, RepositoryError> {
let networks = Self::load_all(path).await?;
Ok(NetworkRepository { networks })
}
}
#[async_trait]
pub trait NetworkRepositoryTrait: Clone {
async fn new(path: Option<&Path>) -> Result<Self, RepositoryError>
where
Self: Sized;
async fn load_all(path: Option<&Path>) -> Result<HashMap<String, Network>, RepositoryError>;
fn get(&self, network_id: &str) -> Option<Network>;
fn get_all(&self) -> HashMap<String, Network>;
}
#[async_trait]
impl NetworkRepositoryTrait for NetworkRepository {
async fn new(path: Option<&Path>) -> Result<Self, RepositoryError> {
NetworkRepository::new(path).await
}
async fn load_all(path: Option<&Path>) -> Result<HashMap<String, Network>, RepositoryError> {
Network::load_all(path).await.map_err(|e| {
RepositoryError::load_error(
"Failed to load networks",
Some(Box::new(e)),
Some(HashMap::from([(
"path".to_string(),
path.map_or_else(|| "default".to_string(), |p| p.display().to_string()),
)])),
)
})
}
fn get(&self, network_id: &str) -> Option<Network> {
self.networks.get(network_id).cloned()
}
fn get_all(&self) -> HashMap<String, Network> {
self.networks.clone()
}
}
#[derive(Clone)]
pub struct NetworkService<T: NetworkRepositoryTrait> {
repository: T,
}
impl<T: NetworkRepositoryTrait> NetworkService<T> {
pub async fn new(
path: Option<&Path>,
) -> Result<NetworkService<NetworkRepository>, RepositoryError> {
let repository = NetworkRepository::new(path).await?;
Ok(NetworkService { repository })
}
pub fn new_with_repository(repository: T) -> Result<Self, RepositoryError> {
Ok(NetworkService { repository })
}
pub async fn new_with_path(
path: Option<&Path>,
) -> Result<NetworkService<NetworkRepository>, RepositoryError> {
let repository = NetworkRepository::new(path).await?;
Ok(NetworkService { repository })
}
pub fn get(&self, network_id: &str) -> Option<Network> {
self.repository.get(network_id)
}
pub fn get_all(&self) -> HashMap<String, Network> {
self.repository.get_all()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_load_error_messages() {
let invalid_path = Path::new("/non/existent/path");
let result = NetworkRepository::load_all(Some(invalid_path)).await;
assert!(result.is_err());
let err = result.unwrap_err();
match err {
RepositoryError::LoadError(message) => {
assert!(message.to_string().contains("Failed to load networks"));
}
_ => panic!("Expected RepositoryError::LoadError"),
}
}
}