mecha10-core 0.8.0

Mecha10 core runtime and foundational types
Documentation
//! Redis client utilities for service discovery

use crate::context::Context;
use crate::error::{Mecha10Error, Result};
use anyhow::Context as _;

#[cfg(feature = "messaging")]
use redis::aio::MultiplexedConnection;

const KEY_PREFIX: &str = "mecha10:discovery";

const DISCOVERY_TTL: u64 = 60;
const DISCOVERY_TTL_EXPIRE: i64 = 60;

pub(crate) struct RedisKeys;

impl RedisKeys {
    /// Build key for node metadata
    pub fn node(node_id: &str) -> String {
        format!("{}:nodes:{}", KEY_PREFIX, node_id)
    }

    /// Build key for type index
    pub fn by_type(node_type: &str) -> String {
        format!("{}:by_type:{}", KEY_PREFIX, node_type)
    }

    /// Build key for publisher index
    pub fn publishers(topic: &str) -> String {
        format!("{}:publishers:{}", KEY_PREFIX, topic)
    }

    /// Build key for subscriber index
    pub fn subscribers(topic: &str) -> String {
        format!("{}:subscribers:{}", KEY_PREFIX, topic)
    }

    /// Get pattern for all node keys
    pub fn all_nodes_pattern() -> &'static str {
        "mecha10:discovery:nodes:*"
    }
}

/// Get TTL for discovery keys (for set_ex operations)
pub(crate) fn get_ttl() -> u64 {
    DISCOVERY_TTL
}

/// Get TTL for discovery keys (for expire operations)
pub(crate) fn get_ttl_expire() -> i64 {
    DISCOVERY_TTL_EXPIRE
}

/// Helper to get a Redis connection
#[cfg(feature = "messaging")]
pub(crate) async fn get_redis_connection(operation: &str) -> Result<MultiplexedConnection> {
    let redis_url = Context::get_redis_url()?;
    let client = redis::Client::open(redis_url.as_str())
        .with_context(|| format!("Failed to connect to Redis at '{}' for {}", redis_url, operation))
        .map_err(|e| Mecha10Error::MessagingError {
            message: format!("{:#}", e),
            suggestion: "Ensure Redis is running".to_string(),
        })?;

    client
        .get_multiplexed_async_connection()
        .await
        .with_context(|| format!("Failed to get async Redis connection for {}", operation))
        .map_err(|e| Mecha10Error::MessagingError {
            message: format!("{:#}", e),
            suggestion: "Ensure Redis is running".to_string(),
        })
}