alibabacloud-imm 0.1.0

A modern, easy-to-use, and reqwest-powered Rust SDK for Alibaba Cloud Intelligent Media Management (IMM)
Documentation
use std::time::Duration;

use tokio::sync::RwLock;

use crate::Result;
use crate::credentials::{Credentials, CredentialsProvider};

const DEFAULT_REFRESH_SKEW: Duration = Duration::from_secs(5 * 60);

#[derive(Debug)]
pub struct CachingCredentialsProvider<P> {
    inner: P,
    cache: RwLock<Option<Credentials>>,
    refresh_skew: Duration,
}

impl<P> CachingCredentialsProvider<P> {
    pub fn new(inner: P) -> Self {
        Self {
            inner,
            cache: RwLock::new(None),
            refresh_skew: DEFAULT_REFRESH_SKEW,
        }
    }

    pub fn with_refresh_skew(mut self, skew: Duration) -> Self {
        self.refresh_skew = skew;
        self
    }
}

impl<P> CredentialsProvider for CachingCredentialsProvider<P>
where
    P: CredentialsProvider,
{
    async fn get_credentials(&self) -> Result<Credentials> {
        {
            let cached = self.cache.read().await;
            if let Some(c) = cached.as_ref()
                && !c.is_expired_within(self.refresh_skew)
            {
                return Ok(c.clone());
            }
        }

        let mut cached = self.cache.write().await;
        if let Some(c) = cached.as_ref()
            && !c.is_expired_within(self.refresh_skew)
        {
            return Ok(c.clone());
        }

        let fresh = self.inner.get_credentials().await?;
        *cached = Some(fresh.clone());
        Ok(fresh)
    }
}