baichun-framework-cache 0.1.0

Cache module for Baichun-Rust framework
Documentation
#[cfg(feature = "redis")]
mod client;
mod config;
mod error;

#[cfg(feature = "redis")]
pub use client::RedisClient;
pub use config::{PoolConfig, RedisCluster, RedisConfig, RedisMode, RedisNode, RedisSentinel};
pub use error::{RedisError, Result};

#[cfg(feature = "redis")]
use std::sync::Arc;
#[cfg(feature = "redis")]
use tokio::sync::OnceCell;

#[cfg(feature = "redis")]
pub static REDIS_CLIENT: OnceCell<Arc<RedisClient>> = OnceCell::const_new();

/// Get the global Redis client instance
#[cfg(feature = "redis")]
pub async fn get_client() -> Arc<RedisClient> {
    REDIS_CLIENT
        .get()
        .expect("Redis client not initialized")
        .clone()
}

/// Initialize the Redis client with configuration
#[cfg(feature = "redis")]
pub async fn init(config: RedisConfig) -> Result<Arc<RedisClient>> {
    let client = RedisClient::new(config).await?;
    let client = Arc::new(client);

    if REDIS_CLIENT.set(client.clone()).is_err() {
        return Err(RedisError::AlreadyInitialized);
    }

    Ok(client)
}

#[cfg(all(test, feature = "redis"))]
mod tests {
    use super::*;

    #[tokio::test]
    async fn test_redis_global_client() {
        // Create test config
        let config = RedisConfig {
            mode: RedisMode::Standalone,
            node: Some(RedisNode {
                host: "localhost".to_string(),
                port: 6379,
            }),
            sentinel: None,
            cluster: None,
            pool: PoolConfig::default(),
            password: Some("1qaz!QAZ".to_string()),
            database: None,
        };

        // Initialize global client
        let client = init(config).await.unwrap();

        // Test set using initialized client
        client
            .set("test_init_key", "test_init_value")
            .await
            .unwrap();

        // Get client from global instance
        let global_client = get_client().await;

        // Test get using global client
        let value = global_client.get("test_init_key").await.unwrap();
        assert_eq!(value, Some("test_init_value".to_string()));

        // Test delete using global client
        // let deleted = global_client.del("test_init_key").await.unwrap();
        // assert!(deleted);

        // Verify deletion
        // let value = global_client.get("test_init_key").await.unwrap();
        // assert_eq!(value, None);
    }

    #[tokio::test]
    async fn test_redis_init_twice() {
        // Create test config
        let config = RedisConfig {
            mode: RedisMode::Standalone,
            node: Some(RedisNode {
                host: "localhost".to_string(),
                port: 6379,
            }),
            sentinel: None,
            cluster: None,
            pool: PoolConfig::default(),
            password: Some("1qaz!QAZ".to_string()),
            database: None,
        };

        // First initialization should succeed
        let result = init(config.clone()).await;
        match result {
            Err(RedisError::AlreadyInitialized) => (),
            _ => panic!("Expected AlreadyInitialized error"),
        }
    }
}