sal/redisclient/src/rhai.rs
Mahmoud-Emad 3e617c2489
Some checks are pending
Rhai Tests / Run Rhai Tests (push) Waiting to run
feat: Add redisclient package to the monorepo
- Integrate the redisclient package into the workspace.
- Update the MONOREPO_CONVERSION_PLAN.md to reflect the
  completion of the redisclient package conversion.
  This includes marking its conversion as complete and
  updating the success metrics.
- Add the redisclient package's Cargo.toml file.
- Add the redisclient package's source code files.
- Add tests for the redisclient package.
- Add README file for the redisclient package.
2025-06-18 17:53:03 +03:00

324 lines
9.2 KiB
Rust

//! Rhai wrappers for Redis client module functions
//!
//! This module provides Rhai wrappers for the functions in the Redis client module.
use crate::redisclient;
use rhai::{Engine, EvalAltResult, Map};
use std::collections::HashMap;
/// Register Redis client module functions with the Rhai engine
///
/// # Arguments
///
/// * `engine` - The Rhai engine to register the functions with
///
/// # Returns
///
/// * `Result<(), Box<EvalAltResult>>` - Ok if registration was successful, Err otherwise
pub fn register_redisclient_module(engine: &mut Engine) -> Result<(), Box<EvalAltResult>> {
// Register basic Redis operations
engine.register_fn("redis_ping", redis_ping);
engine.register_fn("redis_set", redis_set);
engine.register_fn("redis_get", redis_get);
engine.register_fn("redis_del", redis_del);
// Register hash operations
engine.register_fn("redis_hset", redis_hset);
engine.register_fn("redis_hget", redis_hget);
engine.register_fn("redis_hgetall", redis_hgetall);
engine.register_fn("redis_hdel", redis_hdel);
// Register list operations
engine.register_fn("redis_rpush", redis_rpush);
engine.register_fn("redis_lpush", redis_lpush);
engine.register_fn("redis_llen", redis_llen);
engine.register_fn("redis_lrange", redis_lrange);
// Register other operations
engine.register_fn("redis_reset", redis_reset);
Ok(())
}
/// Ping the Redis server
///
/// # Returns
///
/// * `Result<String, Box<EvalAltResult>>` - "PONG" if successful, error otherwise
pub fn redis_ping() -> Result<String, Box<EvalAltResult>> {
let mut cmd = redis::cmd("PING");
redisclient::execute(&mut cmd).map_err(|e| {
Box::new(EvalAltResult::ErrorRuntime(
format!("Redis error: {}", e).into(),
rhai::Position::NONE,
))
})
}
/// Set a key-value pair in Redis
///
/// # Arguments
///
/// * `key` - The key to set
/// * `value` - The value to set
///
/// # Returns
///
/// * `Result<bool, Box<EvalAltResult>>` - true if successful, error otherwise
pub fn redis_set(key: &str, value: &str) -> Result<bool, Box<EvalAltResult>> {
let mut cmd = redis::cmd("SET");
cmd.arg(key).arg(value);
let result: redis::RedisResult<String> = redisclient::execute(&mut cmd);
match result {
Ok(s) if s == "OK" => Ok(true),
Ok(_) => Ok(false),
Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime(
format!("Redis error: {}", e).into(),
rhai::Position::NONE,
))),
}
}
/// Get a value from Redis by key
///
/// # Arguments
///
/// * `key` - The key to get
///
/// # Returns
///
/// * `Result<String, Box<EvalAltResult>>` - The value if found, empty string if not found, error otherwise
pub fn redis_get(key: &str) -> Result<String, Box<EvalAltResult>> {
let mut cmd = redis::cmd("GET");
cmd.arg(key);
let result: redis::RedisResult<Option<String>> = redisclient::execute(&mut cmd);
match result {
Ok(Some(value)) => Ok(value),
Ok(None) => Ok(String::new()),
Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime(
format!("Redis error: {}", e).into(),
rhai::Position::NONE,
))),
}
}
/// Delete a key from Redis
///
/// # Arguments
///
/// * `key` - The key to delete
///
/// # Returns
///
/// * `Result<bool, Box<EvalAltResult>>` - true if successful, error otherwise
pub fn redis_del(key: &str) -> Result<bool, Box<EvalAltResult>> {
let mut cmd = redis::cmd("DEL");
cmd.arg(key);
let result: redis::RedisResult<i64> = redisclient::execute(&mut cmd);
match result {
Ok(n) => Ok(n > 0),
Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime(
format!("Redis error: {}", e).into(),
rhai::Position::NONE,
))),
}
}
/// Set a field in a hash
///
/// # Arguments
///
/// * `key` - The hash key
/// * `field` - The field to set
/// * `value` - The value to set
///
/// # Returns
///
/// * `Result<bool, Box<EvalAltResult>>` - true if successful, error otherwise
pub fn redis_hset(key: &str, field: &str, value: &str) -> Result<bool, Box<EvalAltResult>> {
let mut cmd = redis::cmd("HSET");
cmd.arg(key).arg(field).arg(value);
let result: redis::RedisResult<i64> = redisclient::execute(&mut cmd);
match result {
Ok(_) => Ok(true),
Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime(
format!("Redis error: {}", e).into(),
rhai::Position::NONE,
))),
}
}
/// Get a field from a hash
///
/// # Arguments
///
/// * `key` - The hash key
/// * `field` - The field to get
///
/// # Returns
///
/// * `Result<String, Box<EvalAltResult>>` - The value if found, empty string if not found, error otherwise
pub fn redis_hget(key: &str, field: &str) -> Result<String, Box<EvalAltResult>> {
let mut cmd = redis::cmd("HGET");
cmd.arg(key).arg(field);
let result: redis::RedisResult<Option<String>> = redisclient::execute(&mut cmd);
match result {
Ok(Some(value)) => Ok(value),
Ok(None) => Ok(String::new()),
Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime(
format!("Redis error: {}", e).into(),
rhai::Position::NONE,
))),
}
}
/// Get all fields and values from a hash
///
/// # Arguments
///
/// * `key` - The hash key
///
/// # Returns
///
/// * `Result<Map, Box<EvalAltResult>>` - A map of field-value pairs, error otherwise
pub fn redis_hgetall(key: &str) -> Result<Map, Box<EvalAltResult>> {
let mut cmd = redis::cmd("HGETALL");
cmd.arg(key);
let result: redis::RedisResult<HashMap<String, String>> = redisclient::execute(&mut cmd);
match result {
Ok(hash_map) => {
let mut map = Map::new();
for (k, v) in hash_map {
map.insert(k.into(), v.into());
}
Ok(map)
}
Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime(
format!("Redis error: {}", e).into(),
rhai::Position::NONE,
))),
}
}
/// Delete a field from a hash
///
/// # Arguments
///
/// * `key` - The hash key
/// * `field` - The field to delete
///
/// # Returns
///
/// * `Result<bool, Box<EvalAltResult>>` - true if successful, error otherwise
pub fn redis_hdel(key: &str, field: &str) -> Result<bool, Box<EvalAltResult>> {
let mut cmd = redis::cmd("HDEL");
cmd.arg(key).arg(field);
let result: redis::RedisResult<i64> = redisclient::execute(&mut cmd);
match result {
Ok(n) => Ok(n > 0),
Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime(
format!("Redis error: {}", e).into(),
rhai::Position::NONE,
))),
}
}
/// Push an element to the end of a list
///
/// # Arguments
///
/// * `key` - The list key
/// * `value` - The value to push
///
/// # Returns
///
/// * `Result<i64, Box<EvalAltResult>>` - The new length of the list, error otherwise
pub fn redis_rpush(key: &str, value: &str) -> Result<i64, Box<EvalAltResult>> {
let mut cmd = redis::cmd("RPUSH");
cmd.arg(key).arg(value);
redisclient::execute(&mut cmd).map_err(|e| {
Box::new(EvalAltResult::ErrorRuntime(
format!("Redis error: {}", e).into(),
rhai::Position::NONE,
))
})
}
/// Push an element to the beginning of a list
///
/// # Arguments
///
/// * `key` - The list key
/// * `value` - The value to push
///
/// # Returns
///
/// * `Result<i64, Box<EvalAltResult>>` - The new length of the list, error otherwise
pub fn redis_lpush(key: &str, value: &str) -> Result<i64, Box<EvalAltResult>> {
let mut cmd = redis::cmd("LPUSH");
cmd.arg(key).arg(value);
redisclient::execute(&mut cmd).map_err(|e| {
Box::new(EvalAltResult::ErrorRuntime(
format!("Redis error: {}", e).into(),
rhai::Position::NONE,
))
})
}
/// Get the length of a list
///
/// # Arguments
///
/// * `key` - The list key
///
/// # Returns
///
/// * `Result<i64, Box<EvalAltResult>>` - The length of the list, error otherwise
pub fn redis_llen(key: &str) -> Result<i64, Box<EvalAltResult>> {
let mut cmd = redis::cmd("LLEN");
cmd.arg(key);
redisclient::execute(&mut cmd).map_err(|e| {
Box::new(EvalAltResult::ErrorRuntime(
format!("Redis error: {}", e).into(),
rhai::Position::NONE,
))
})
}
/// Get a range of elements from a list
///
/// # Arguments
///
/// * `key` - The list key
/// * `start` - The start index
/// * `stop` - The stop index
///
/// # Returns
///
/// * `Result<Vec<String>, Box<EvalAltResult>>` - The elements in the range, error otherwise
pub fn redis_lrange(key: &str, start: i64, stop: i64) -> Result<Vec<String>, Box<EvalAltResult>> {
let mut cmd = redis::cmd("LRANGE");
cmd.arg(key).arg(start).arg(stop);
redisclient::execute(&mut cmd).map_err(|e| {
Box::new(EvalAltResult::ErrorRuntime(
format!("Redis error: {}", e).into(),
rhai::Position::NONE,
))
})
}
/// Reset the Redis client connection
///
/// # Returns
///
/// * `Result<bool, Box<EvalAltResult>>` - true if successful, error otherwise
pub fn redis_reset() -> Result<bool, Box<EvalAltResult>> {
match redisclient::reset() {
Ok(_) => Ok(true),
Err(e) => Err(Box::new(EvalAltResult::ErrorRuntime(
format!("Redis error: {}", e).into(),
rhai::Position::NONE,
))),
}
}