# Forge Server - Redis Client Module

A high-performance arma-rs extension for Arma 3, featuring a **low-level Redis data access layer** that provides raw Redis operations as a foundation for higher-level game modules.

## 🎯 Overview

The Forge Server Redis module is designed as a **foundational data access layer** that:
- **Returns raw Redis responses** for maximum performance and flexibility
- **Serves as the foundation** for higher-level game modules (actor, garage, locker, bank, etc.)
- **Provides connection pooling** and error handling for Redis operations
- **Enables persistent data storage** across server restarts
- **Supports cross-server data sharing** in multi-server environments

## 🏗️ Layered Architecture

```
SQF Scripts
    ↓ (JSON responses)
Game Modules (actor, garage, locker, bank)
    ↓ (raw Redis responses)  
Redis Client Module
    ↓ (Redis protocol)
Redis Server
```

**This module handles the bottom layer** - raw Redis operations with connection pooling and error handling.

## 🏗️ Internal Architecture

```
forge_server_x64.dll Extension
├── lib.rs                 # Core extension initialization & global runtime
├── config.example.toml    # Example configuration file
└── redis/                 # Redis Client module
    ├── mod.rs             # Group definitions & module exports
    ├── client.rs          # Connection pool management
    ├── config.rs          # Configuration system
    ├── macros.rs          # redis_operation! macro for boilerplate elimination
    ├── common.rs          # String/key operations
    ├── hash.rs            # Hash operations (HSET, HGET, etc.)
    ├── list.rs            # List operations (LPUSH, LPOP, etc.)
    └── set.rs             # Set operations (SADD, SMEMBERS, etc.)
```

### Key Components
- **lib.rs**: Manages global Redis pool and single Tokio runtime
- **macros.rs**: Provides `redis_operation!` macro to eliminate boilerplate
- **Operation modules**: Focus purely on Redis logic using the macro
- **Synchronous Interface**: All functions appear synchronous to Arma while using async Redis internally

## 🚀 Features

### Raw Redis Operations
- **String Operations**: SET, GET, INCR, DECR, DEL, KEYS
- **Hash Operations**: HSET, HGET, HMSET, HGETALL, HDEL, HKEYS, HVALS, HLEN
- **List Operations**: LSET, LGET, LLEN, LRANGE, LPUSH, RPUSH, LPOP, RPOP, LTRIM, LREM
- **Set Operations**: SADD, SMEMBERS, SCARD, SREM, SISMEMBER, SPOP, SRANDMEMBER

### Performance Features
- **Connection Pooling**: bb8-redis pool with configurable size and timeouts
- **Single Runtime**: One shared Tokio runtime for all async operations
- **Macro-Based**: `redis_operation!` macro eliminates boilerplate while maintaining performance
- **Synchronous Interface**: Functions block until completion, compatible with Arma's threading model
- **Raw Responses**: Returns native Redis values for maximum performance
- **Thread Safety**: Safe concurrent access from multiple Arma threads

## ⚙️ Configuration System

Forge Server uses a TOML-based configuration system for flexible Redis connection management.

### Configuration File

Create a `config.toml` file in your extension directory:

```toml
[redis]
host = "127.0.0.1"
port = 6379
# db = 0                    # Optional: Redis database number
# username = "user"         # Optional: Redis username
# password = "password"     # Optional: Redis password
# max_connections = 10       # Optional: Maximum connections in pool
# min_connections = 2        # Optional: Minimum idle connections in pool
# idle_timeout = 60          # Optional: Connection idle timeout (seconds)
```

### Fallback Behavior

The extension uses a robust fallback system:
1. **Loads `config.toml`** if present in the extension directory
2. **Falls back to defaults** if configuration fails or file is missing
3. **Only fails** if both config and defaults cannot establish connection

**Default Settings:**
- **Host**: `127.0.0.1`
- **Port**: `6379`
- **Max Connections**: `10`
- **Min Connections**: `2`
- **Idle Timeout**: `60 seconds`

### Common Configurations

**Development (Local Redis)**:
```toml
[redis]
host = "127.0.0.1"
port = 6379
max_connections = 5
min_connections = 1
```

**Production (Remote Redis with Authentication)**:
```toml
[redis]
host = "redis.example.com"
port = 6379
username = "arma_server"
password = "secure_password"
max_connections = 20
min_connections = 5
idle_timeout = 60
```

### Troubleshooting

**Connection Issues:**
- Verify Redis server is running: `redis-cli ping`
- Check host/port settings in `config.toml`
- Ensure firewall allows connection

**Authentication Issues:**
- Verify username/password in config
- Check Redis server auth settings

**Config File Issues:**
- Check TOML syntax with online validators
- Ensure quotes are properly closed
- Verify file permissions

**Connection Pool Benefits:**
- Pre-warmed connections for zero-latency operations
- Automatic connection recovery on network issues
- Resource-efficient connection sharing
- Configurable pool sizing for different deployment scenarios

## 🔧 Installation

1. **Prerequisites**:
   - Redis server (local or remote)
   - Arma 3 server with extension support

2. **Extension Setup**:
   - Build the extension: `cargo build --release`
   - Copy the compiled `forge_server_x64.dll` to your Arma 3 server
   - Copy `config.example.toml` to `config.toml` and configure as needed
   - Load in server config or mission

3. **Redis Server**:
   ```bash
   # Start Redis server
   redis-server
   
   # Verify connection
   redis-cli ping
   ```

## 📝 Documentation

- **[API Reference](./api-reference.md)** - Complete Redis command reference
- **[Usage Examples](./usage-examples.md)** - Practical SQF integration examples

## 📊 Performance

- **Connection Pool**: 2-10 persistent connections using bb8-redis
- **Single Runtime**: One shared Tokio runtime eliminates overhead from multiple runtimes
- **Macro Efficiency**: Zero-cost abstraction – macros expand to optimal code at compile time
- **Synchronous Blocking**: Functions use `block_on()` for Arma compatibility without sacrificing async I/O benefits
- **Response Format**: Raw Redis responses for minimal overhead
- **Thread Safety**: Multiple Arma threads can safely call operations concurrently
- **Memory Efficient**: Minimal resource usage per operation

## 🔄 Response Format

This module returns **raw Redis responses** as strings for maximum performance:

### Success Responses
- **String values**: `"John"` (raw string)
- **Numbers**: `"42"` (number as string)
- **Lists/Arrays**: `"item1,item2,item3"` (comma-separated)
- **Hashes**: `"key1,value1,key2,value2"` (comma-separated key-value pairs)
- **Boolean**: `"1"` or `"0"` (for exists checks)
- **Status**: `"OK"` (for successful SET operations)

### Error Responses
- **Format**: `"Error: <error description>"`
- **Pool errors**: `"Error: Redis pool not initialized"`
- **Connection errors**: `"Error: <connection error>"`
- **Redis errors**: `"Error: <Redis operation error>"`

### Higher-Level JSON Formatting
Game modules (actor, garage, etc.) will wrap these raw responses in structured JSON for SQF consumption.

## ⚙️ Macro-Based Implementation

This extension uses a **macro-based architecture** to eliminate boilerplate while maintaining performance:

### The `redis_operation!` Macro

```rust
pub fn set_key(key: String, value: String) -> String {
    redis_operation!(conn => {
        match conn.set::<_, _, ()>(&key, &value).await {
            Ok(()) => "OK".to_string(),
            Err(e) => format!("Error: {}", e),
        }
    })
}
```

### What the Macro Handles

- **Pool Management**: Retrieves Redis connection pool
- **Error Handling**: Returns "Error: ..." for pool/connection failures  
- **Async Bridging**: Uses shared Tokio runtime via `block_on()`
- **Connection Acquisition**: Gets connection from pool with error handling
- **Cleanup**: Automatic connection return to pool

### Benefits

- **Reduced Code**: 70% less boilerplate per function
- **Consistency**: Identical error handling across all operations
- **Maintainability**: Changes to connection logic in one place
- **Performance**: No runtime overhead from abstraction
- **Synchronous Interface**: Functions block until Redis operation completes

## 🛠️ Development

- **Language**: Rust (Edition 2024)
- **Dependencies**: arma-rs, bb8-redis, redis, tokio
- **Architecture**: Macro-based design with single runtime and connection pool
- **Key Patterns**: 
  - Global state management in `lib.rs`
  - Boilerplate elimination via `redis_operation!` macro
  - Synchronous interfaces over async operations
  - Raw Redis responses for minimal overhead
- **Testing**: Unit tests for core functionality


## 🚨 Error Handling

The extension provides comprehensive error handling:
- Connection failures
- Redis operation errors  
- Invalid parameters
- Pool initialization errors

All errors include descriptive messages for debugging.

## 🔍 Monitoring

Connection pool status and Redis operations can be monitored through:
- Extension logs
- Redis server logs  
- Connection pool metrics

---

**Built with ❤️ for the Arma 3 community**