use dashmap::DashMap;
use crate::api::naming::{Instance, Service};
use crate::common::build_service_key;
pub struct ServiceInfoCache {
services: DashMap<String, Service>,
}
impl ServiceInfoCache {
pub fn new() -> Self {
Self {
services: DashMap::new(),
}
}
pub fn get(&self, namespace: &str, group_name: &str, service_name: &str) -> Option<Service> {
let key = build_service_key(service_name, group_name, namespace);
self.services.get(&key).map(|r| r.value().clone())
}
pub fn put(&self, namespace: &str, service: Service) {
let key = build_service_key(&service.name, &service.group_name, namespace);
self.services.insert(key, service);
}
pub fn remove(
&self,
namespace: &str,
group_name: &str,
service_name: &str,
) -> Option<Service> {
let key = build_service_key(service_name, group_name, namespace);
self.services.remove(&key).map(|(_, v)| v)
}
pub fn contains(&self, namespace: &str, group_name: &str, service_name: &str) -> bool {
let key = build_service_key(service_name, group_name, namespace);
self.services.contains_key(&key)
}
pub fn get_healthy_instances(
&self,
namespace: &str,
group_name: &str,
service_name: &str,
) -> Vec<Instance> {
self.get(namespace, group_name, service_name)
.map(|s| s.hosts.into_iter().filter(|i| i.healthy && i.enabled).collect())
.unwrap_or_default()
}
pub fn get_all_instances(
&self,
namespace: &str,
group_name: &str,
service_name: &str,
) -> Vec<Instance> {
self.get(namespace, group_name, service_name)
.map(|s| s.hosts)
.unwrap_or_default()
}
pub fn update_instances(
&self,
namespace: &str,
group_name: &str,
service_name: &str,
instances: Vec<Instance>,
) {
let key = build_service_key(service_name, group_name, namespace);
if let Some(mut service) = self.services.get_mut(&key) {
service.hosts = instances;
} else {
let mut service = Service::new(service_name, group_name);
service.hosts = instances;
self.services.insert(key, service);
}
}
pub fn keys(&self) -> Vec<String> {
self.services.iter().map(|r| r.key().clone()).collect()
}
pub fn clear(&self) {
self.services.clear();
}
pub fn len(&self) -> usize {
self.services.len()
}
pub fn is_empty(&self) -> bool {
self.services.is_empty()
}
}
impl Default for ServiceInfoCache {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_service_info_cache() {
let cache = ServiceInfoCache::new();
let mut service = Service::new("test-service", "DEFAULT_GROUP");
service.hosts.push(Instance::new("127.0.0.1", 8080));
cache.put("public", service);
assert!(cache.contains("public", "DEFAULT_GROUP", "test-service"));
let instances = cache.get_all_instances("public", "DEFAULT_GROUP", "test-service");
assert_eq!(instances.len(), 1);
assert_eq!(instances[0].ip, "127.0.0.1");
}
}