unleash-edge 16.0.4

Unleash edge is a proxy for Unleash. It can return both evaluated feature toggles as well as the raw data from Unleash's client API
Documentation
use std::{collections::HashMap, sync::Arc, time::Duration};

use async_trait::async_trait;
use dashmap::DashMap;
use tracing::{debug, warn};
use unleash_types::client_features::ClientFeatures;

use crate::types::{EdgeResult, EdgeToken, TokenRefresh, TokenValidationStatus};

pub mod file;
pub mod redis;

#[async_trait]
pub trait EdgePersistence: Send + Sync {
    async fn load_tokens(&self) -> EdgeResult<Vec<EdgeToken>>;
    async fn save_tokens(&self, tokens: Vec<EdgeToken>) -> EdgeResult<()>;
    async fn load_refresh_targets(&self) -> EdgeResult<Vec<TokenRefresh>>;
    async fn save_refresh_targets(&self, refresh_targets: Vec<TokenRefresh>) -> EdgeResult<()>;
    async fn load_features(&self) -> EdgeResult<HashMap<String, ClientFeatures>>;
    async fn save_features(&self, features: Vec<(String, ClientFeatures)>) -> EdgeResult<()>;
}

#[cfg(not(tarpaulin_include))]
pub async fn persist_data(
    persistence: Option<Arc<dyn EdgePersistence>>,
    token_cache: Arc<DashMap<String, EdgeToken>>,
    features_cache: Arc<DashMap<String, ClientFeatures>>,
    refresh_targets_cache: Arc<DashMap<String, TokenRefresh>>,
) {
    loop {
        tokio::select! {
            _ = tokio::time::sleep(Duration::from_secs(60)) => {
                if let Some(persister) = persistence.clone() {
                    match persister.save_tokens(token_cache.iter().filter(|t| t.value().status == TokenValidationStatus::Validated).map(|e| e.value().clone()).collect()).await {
                        Ok(()) => debug!("Persisted tokens"),
                        Err(save_error) =>
                            warn!("Could not persist tokens: {save_error:?}")


                    }
                    match persister.save_features(features_cache.iter().map(|e| (e.key().clone(), e.value().clone())).collect()).await {
                        Ok(()) => debug!("Persisted features"),
                        Err(save_error) =>
                            warn!("Could not persist features: {save_error:?}")

                    }

                    match persister.save_refresh_targets(refresh_targets_cache.iter().map(|e| e.value().clone()).collect()).await {
                        Ok(()) => debug!("Persisted refresh targets"),
                        Err(save_error) => warn!("Could not persist refresh targets: {save_error:?}")
                    }
                } else {
                    debug!("Had no persister. Nothing was persisted");
                }
            }
        }
    }
}