cal-redis 0.1.80

Callable Redis Implementation
Documentation
// File: cal-redis/src/region.rs

use crate::cache::get_hash;
use crate::common::{deserialize_from_json, get_hash_item, serialize_to_json};
use crate::constants::{REGIONS_KEY, REGION_IDENTS_KEY};
use crate::get_hash_all_values;
use cal_core::Region;
use redis::aio::MultiplexedConnection;
use redis::{AsyncCommands, RedisError, Value};

/// Retrieves all regions stored in Redis.
pub async fn get_regions(con: MultiplexedConnection) -> Result<Vec<Region>, RedisError> {
    println!("Getting regions from key: {}", REGIONS_KEY);

    let region_str: Vec<String> = get_hash_all_values(con.clone(), REGIONS_KEY).await?;

    println!("Regions size: {}", region_str.len());

    // Deserialize each region
    let mut regions: Vec<Region> = Vec::with_capacity(region_str.len());
    for str in region_str {
        regions.push(deserialize_from_json::<Region>(&str)?);
    }

    Ok(regions)
}

/// Retrieves a region by its identifier (could be an ID, name, etc.).
pub async fn get_region_by_ident(
    con: MultiplexedConnection,
    key: &str,
) -> Result<Option<Region>, RedisError> {
    println!("Getting region by ident {} from key: {}", key, REGION_IDENTS_KEY);
    // Look up the region ID from the identifiers hash
    match get_hash(con.clone(), REGION_IDENTS_KEY, key).await? {
        Some(region_id) => {
            get_region_by_id(con, &region_id).await
        },
        None => Ok(None),
    }
}

/// Retrieves a region by its unique ID.
pub async fn get_region_by_id(
    con: MultiplexedConnection,
    key: &str,
) -> Result<Option<Region>, RedisError> {
    println!("Getting region by id {} from key: {}", key, REGIONS_KEY);
    get_hash_item(con, REGIONS_KEY, key).await
}

/// Inserts a region into Redis.
pub async fn insert_region(
    mut con: MultiplexedConnection,
    region: Region,
) -> Result<(), RedisError> {
    let value = serialize_to_json(&region)?;

    // Set the region in Redis with explicit type annotation
    let _: String = con
        .hset(REGIONS_KEY, region.id.to_string(), value)
        .await?;

    // Build the idents
    build_region_idents(&mut con, &region).await?;

    Ok(())
}

/// Inserts region identifiers into Redis for lookup purposes.
pub async fn insert_region_idents(
    mut con: MultiplexedConnection,
    items: &[(String, String)],
) -> Result<Value, RedisError> {
    let result: Value = con.hset_multiple(REGION_IDENTS_KEY, items).await?;
    Ok(result)
}

/// Builds Redis identity mappings for a region
async fn build_region_idents(
    con: &mut MultiplexedConnection,
    region: &Region,
) -> Result<(), RedisError> {
    // Add region ID and voice server mappings
    let mut ident_entries = vec![
        (region.id.to_string(), region.id.to_string())
    ];

    // Add voice server mappings
    for vs in &region.voice_servers {
        ident_entries.push((vs.id.clone(), region.id.to_string()));
        ident_entries.push((vs.public_ip.clone(), region.id.to_string()));
        ident_entries.push((vs.private_ip.clone(), region.id.to_string()));
    }

    // Insert all identity entries
    let _: Value = con.hset_multiple(REGION_IDENTS_KEY, &ident_entries).await?;

    Ok(())
}