# Redisclient Module The `redisclient` module in Herolib provides a comprehensive client for interacting with Redis, supporting various commands, caching, queues, and RPC mechanisms. ## Key Features - **Direct Redis Commands**: Access to a wide range of Redis commands (strings, hashes, lists, keys, etc.). - **Caching**: Built-in caching mechanism with namespace support and expiration. - **Queues**: Simple queue implementation using Redis lists. - **RPC**: Remote Procedure Call (RPC) functionality over Redis queues for inter-service communication. ## Basic Usage To get a Redis client instance, use `redisclient.core_get()`. By default, it connects to `127.0.0.1:6379`. You can specify a different address and port using the `RedisURL` struct. ```v import incubaid.herolib.core.redisclient // Connect to default Redis instance (127.0.0.1:6379) mut redis := redisclient.core_get()! // Or connect to a specific Redis instance // mut redis_url := redisclient.RedisURL{address: 'my.redis.server', port: 6380} // mut redis := redisclient.core_get(redis_url)! // Example: Set and Get a key redis.set('mykey', 'myvalue')! value := redis.get('mykey')! // assert value == 'myvalue' // Example: Check if a key exists exists := redis.exists('mykey')! // assert exists == true // Example: Delete a key redis.del('mykey')! ``` ## Redis Commands The `Redis` object provides methods for most standard Redis commands. Here are some examples: ### String Commands - `set(key string, value string) !`: Sets the string value of a key. - `get(key string) !string`: Gets the string value of a key. - `set_ex(key string, value string, ex string) !`: Sets a key with an expiration time in seconds. - `incr(key string) !int`: Increments the integer value of a key by one. - `decr(key string) !int`: Decrements the integer value of a key by one. - `append(key string, value string) !int`: Appends a value to a key. - `strlen(key string) !int`: Gets the length of the value stored in a key. ```v redis.set('counter', '10')! redis.incr('counter')! // counter is now 11 val := redis.get('counter')! // "11" ``` ### Hash Commands - `hset(key string, skey string, value string) !`: Sets the string value of a hash field. - `hget(key string, skey string) !string`: Gets the value of a hash field. - `hgetall(key string) !map[string]string`: Gets all fields and values in a hash. - `hexists(key string, skey string) !bool`: Checks if a hash field exists. - `hdel(key string, skey string) !int`: Deletes one or more hash fields. ```v redis.hset('user:1', 'name', 'John Doe')! redis.hset('user:1', 'email', 'john@example.com')! user_name := redis.hget('user:1', 'name')! // "John Doe" user_data := redis.hgetall('user:1')! // map['name':'John Doe', 'email':'john@example.com'] ``` ### List Commands - `lpush(key string, element string) !int`: Inserts all specified values at the head of the list stored at key. - `rpush(key string, element string) !int`: Inserts all specified values at the tail of the list stored at key. - `lpop(key string) !string`: Removes and returns the first element of the list stored at key. - `rpop(key string) !string`: Removes and returns the last element of the list stored at key. - `llen(key string) !int`: Gets the length of a list. - `lrange(key string, start int, end int) ![]resp.RValue`: Gets a range of elements from a list. ```v redis.lpush('mylist', 'item1')! redis.rpush('mylist', 'item2')! first_item := redis.lpop('mylist')! // "item1" ``` ### Set Commands - `sadd(key string, members []string) !int`: Adds the specified members to the set stored at key. - `smismember(key string, members []string) ![]int`: Returns if member is a member of the set stored at key. ```v redis.sadd('myset', ['member1', 'member2'])! is_member := redis.smismember('myset', ['member1', 'member3'])! // [1, 0] ``` ### Key Management - `keys(pattern string) ![]string`: Finds all keys matching the given pattern. - `del(key string) !int`: Deletes a key. - `expire(key string, seconds int) !int`: Sets a key's time to live in seconds. - `ttl(key string) !int`: Gets the time to live for a key in seconds. - `flushall() !`: Deletes all the keys of all the existing databases. - `flushdb() !`: Deletes all the keys of the currently selected database. - `selectdb(database int) !`: Changes the selected database. ```v redis.set('temp_key', 'value')! redis.expire('temp_key', 60)! // Expires in 60 seconds ``` ## Redis Cache The `RedisCache` struct provides a convenient way to implement caching using Redis. ```v import incubaid.herolib.core.redisclient mut redis := redisclient.core_get()! mut cache := redis.cache('my_app_cache') // Set a value in cache with expiration (e.g., 3600 seconds) cache.set('user:profile:123', '{ "name": "Alice" }', 3600)! // Get a value from cache cached_data := cache.get('user:profile:123') or { // Cache miss, fetch from source println('Cache miss for user:profile:123') return } // println('Cached data: ${cached_data}') // Check if a key exists in cache exists := cache.exists('user:profile:123') // assert exists == true // Reset the cache for the namespace cache.reset()! ``` ## Redis Queue The `RedisQueue` struct provides a simple queue mechanism using Redis lists. ```v import incubaid.herolib.core.redisclient import time mut redis := redisclient.core_get()! mut my_queue := redis.queue_get('my_task_queue') // Add items to the queue my_queue.add('task1')! my_queue.add('task2')! // Get an item from the queue with a timeout (e.g., 1000 milliseconds) task := my_queue.get(1000)! // assert task == 'task1' // Pop an item without timeout (returns error if no item) task2 := my_queue.pop()! // assert task2 == 'task2' ``` ## Redis RPC The `RedisRpc` struct enables Remote Procedure Call (RPC) over Redis, allowing services to communicate by sending messages to queues and waiting for responses. ```v import incubaid.herolib.core.redisclient import json import time mut redis := redisclient.core_get()! mut rpc_client := redis.rpc_get('my_rpc_service') // Define a function to process RPC requests (server-side) fn my_rpc_processor(cmd string, data string) !string { // Simulate some processing based on cmd and data return 'Processed: cmd=${cmd}, data=${data}' } // --- Client Side (calling the RPC) --- // Call the RPC service response := rpc_client.call( cmd: 'greet', data: '{"name": "World"}', wait: true, timeout: 5000 // 5 seconds timeout )! // println('RPC Response: ${response}') // assert response == 'Processed: cmd=greet, data={"name": "World"}' // --- Server Side (processing RPC requests) --- // In a separate goroutine or process, you would run: // rpc_client.process(my_rpc_processor, timeout: 0)! // timeout 0 means no timeout, keeps processing // Example of how to process a single request (for testing/demonstration) // In a real application, this would be in a loop or a background worker // return_queue_name := rpc_client.process(my_rpc_processor, timeout: 1000)! // result := rpc_client.result(1000, return_queue_name)! // println('Processed result: ${result}')