# Redis Client API Reference

Complete reference for **raw Redis operations** available in the Forge Server extension. This module returns native Redis values without JSON formatting.

> **Note**: This is a low-level data access layer. Higher-level game modules (actor, garage, etc.) will provide structured JSON responses for SQF consumption.

## 🏗️ Implementation

All Redis operations are implemented using the `redis_operation!` macro for:
- **Consistent Error Handling**: All functions return identical error formats
- **Connection Management**: Automatic pool and connection handling
- **Synchronous Interface**: Functions block until Redis operations complete
- **Performance**: Zero-cost abstraction with compile-time optimization

## 🔗 Command Structure

All redis client commands follow the pattern: `"forge_server" callExtension ["redis:command", [parameters]]`

## 📝 Common Operations

### SET - Store a key-value pair
**Command**: `redis:common:set`
**Parameters**: `[key, value]`

```sqf
"forge_server" callExtension ["redis:common:set", ["player_name", "John"]]
```

**Raw Response**: `"OK"`

### GET - Retrieve a value by key
**Command**: `redis:common:get`
**Parameters**: `[key]`

```sqf
"forge_server" callExtension ["redis:common:get", ["player_name"]]
```

**Raw Response**: `"John"` (the actual stored value)

### INCR - Increment a numeric value
**Command**: `redis:common:incr`
**Parameters**: `[key, increment_amount]`

```sqf
"forge_server" callExtension ["redis:common:incr", ["player_score", 10]]
```

**Raw Response**: `"110"` (the new value as string)

### DECR - Decrement a numeric value
**Command**: `redis:common:decr`
**Parameters**: `[key, decrement_amount]`

```sqf
"forge_server" callExtension ["redis:common:decr", ["player_lives", 1]]
```

**Raw Response**: `"2"` (the new value as string)

### DEL - Delete a key
**Command**: `redis:common:del`
**Parameters**: `[key]`

```sqf
"forge_server" callExtension ["redis:common:del", ["temp_data"]]
```

**Raw Response**: `"1"` (number of keys deleted)

### KEYS - List all keys matching pattern
**Command**: `redis:common:keys`
**Parameters**: `[]` (currently returns all keys with "*" pattern)

```sqf
"forge_server" callExtension ["redis:common:keys", []]
```

**Raw Response**: `"player_name,player_score,mission_state"` (comma-separated list)

## 🗂️ Hash Operations

### HSET - Set hash field
**Command**: `redis:hash:set`
**Parameters**: `[hash_key, field, value]`

```sqf
"forge_server" callExtension ["redis:hash:set", ["player:123", "name", "John"]]
```

**Raw Response**: `"1"` (number of fields added)

### HGET - Get hash field
**Command**: `redis:hash:get`
**Parameters**: `[hash_key, field]`

```sqf
"forge_server" callExtension ["redis:hash:get", ["player:123", "name"]]
```

**Raw Response**: `"John"` (the field value)

### HMSET - Set multiple hash fields
**Command**: `redis:hash:mset`
**Parameters**: `[hash_key, [[field1, value1], [field2, value2], ...]]`

```sqf
"forge_server" callExtension ["redis:hash:mset", ["player:123", [["name", "John"], ["score", "100"]]]]
```

**Raw Response**: `"OK"`

### HGETALL - Get all hash fields
**Command**: `redis:hash:getall`
**Parameters**: `[hash_key]`

```sqf
"forge_server" callExtension ["redis:hash:getall", ["player:123"]]
```

**Raw Response**: `"name,John,score,100,level,5"` (comma-separated key-value pairs)

### HDEL - Delete hash field
**Command**: `redis:hash:del`
**Parameters**: `[hash_key, field]`

```sqf
"forge_server" callExtension ["redis:hash:del", ["player:123", "temp_field"]]
```

**Raw Response**: `"1"` (number of fields removed)

### HKEYS - Get all hash field names
**Command**: `redis:hash:keys`
**Parameters**: `[hash_key]`

```sqf
"forge_server" callExtension ["redis:hash:keys", ["player:123"]]
```

**Raw Response**: `"name,score,level"` (comma-separated field names)

### HVALS - Get all hash values
**Command**: `redis:hash:vals`
**Parameters**: `[hash_key]`

```sqf
"forge_server" callExtension ["redis:hash:vals", ["player:123"]]
```

**Raw Response**: `"John,100,5"` (comma-separated values)

### HLEN - Get hash field count
**Command**: `redis:hash:len`
**Parameters**: `[hash_key]`

```sqf
"forge_server" callExtension ["redis:hash:len", ["player:123"]]
```

**Raw Response**: `"3"` (number of fields in hash)

## 📋 List Operations

### LSET - Set list element by index
**Command**: `redis:list:set`
**Parameters**: `[list_key, index, value]`

```sqf
"forge_server" callExtension ["redis:list:set", ["mission_queue", 0, "patrol_alpha"]]
```

**Raw Response**: `"OK"`

### LGET - Get list element by index
**Command**: `redis:list:get`
**Parameters**: `[list_key, index]`

```sqf
"forge_server" callExtension ["redis:list:get", ["mission_queue", 0]]
```

**Raw Response**: `"patrol_alpha"` (the element value)

### LLEN - Get list length
**Command**: `redis:list:len`
**Parameters**: `[list_key]`

```sqf
"forge_server" callExtension ["redis:list:len", ["mission_queue"]]
```

**Raw Response**: `"5"` (list length)

### LRANGE - Get list elements in range
**Command**: `redis:list:range`
**Parameters**: `[list_key, start_index, end_index]`

```sqf
"forge_server" callExtension ["redis:list:range", ["mission_queue", 0, 2]]
```

**Raw Response**: `"patrol_alpha,escort_beta,defend_gamma"` (comma-separated values)

### LPUSH - Add element to list head
**Command**: `redis:list:lpush`
**Parameters**: `[list_key, value]`

```sqf
"forge_server" callExtension ["redis:list:lpush", ["recent_actions", "player_joined"]]
```

**Raw Response**: `"6"` (new list length)

### RPUSH - Add element to list tail
**Command**: `redis:list:rpush`
**Parameters**: `[list_key, value]`

```sqf
"forge_server" callExtension ["redis:list:rpush", ["mission_queue", "new_objective"]]
```

**Raw Response**: `"6"` (new list length)

### LPOP - Remove and return element from list head
**Command**: `redis:list:lpop`
**Parameters**: `[list_key, count]`

```sqf
"forge_server" callExtension ["redis:list:lpop", ["recent_actions", 1]]
```

**Raw Response**: `"player_joined"` (removed element) or `"item1,item2"` (if count > 1)

### RPOP - Remove and return element from list tail
**Command**: `redis:list:rpop`
**Parameters**: `[list_key, count]`

```sqf
"forge_server" callExtension ["redis:list:rpop", ["mission_queue", 1]]
```

**Raw Response**: `"new_objective"` (removed element) or `"item1,item2"` (if count > 1)

### LTRIM - Trim list to specified range
**Command**: `redis:list:trim`
**Parameters**: `[list_key, start_index, end_index]`

```sqf
"forge_server" callExtension ["redis:list:trim", ["recent_actions", 0, 9]]  // Keep only last 10 items
```

**Raw Response**: `"OK"`

### LREM - Remove elements from list
**Command**: `redis:list:del`
**Parameters**: `[list_key, count, value]`

```sqf
"forge_server" callExtension ["redis:list:del", ["mission_queue", 1, "completed_mission"]]
```

**Raw Response**: `"1"` (number of elements removed)

## 🎯 Set Operations

### SADD - Add element to set
**Command**: `redis:set:add`
**Parameters**: `[set_key, value]`

```sqf
"forge_server" callExtension ["redis:set:add", ["online_players", "player_123"]]
```

**Raw Response**: `"1"` (1 if element was added, 0 if already existed)

### SMEMBERS - Get all set members
**Command**: `redis:set:members`
**Parameters**: `[set_key]`

```sqf
"forge_server" callExtension ["redis:set:members", ["online_players"]]
```

**Raw Response**: `"player_123,player_456,player_789"` (comma-separated members)

### SCARD - Get set size
**Command**: `redis:set:card`
**Parameters**: `[set_key]`

```sqf
"forge_server" callExtension ["redis:set:card", ["online_players"]]
```

**Raw Response**: `"3"` (number of elements in set)

### SREM - Remove element from set
**Command**: `redis:set:del`
**Parameters**: `[set_key, value]`

```sqf
"forge_server" callExtension ["redis:set:del", ["online_players", "player_456"]]
```

**Raw Response**: `"1"` (1 if element was removed, 0 if didn't exist)

### SISMEMBER - Check if element is in set
**Command**: `redis:set:ismember`
**Parameters**: `[set_key, value]`

```sqf
"forge_server" callExtension ["redis:set:ismember", ["online_players", "player_123"]]
```

**Raw Response**: `"1"` (1 if member exists, 0 if not)

### SPOP - Remove and return random element
**Command**: `redis:set:pop`
**Parameters**: `[set_key]`

```sqf
"forge_server" callExtension ["redis:set:pop", ["available_missions"]]
```

**Raw Response**: `"mission_alpha"` (the removed element)

### SRANDMEMBER - Get random element without removing
**Command**: `redis:set:randmember`
**Parameters**: `[set_key]`

```sqf
"forge_server" callExtension ["redis:set:randmember", ["available_missions"]]
```

**Raw Response**: `"mission_beta"` (a random element)

### SRANDMEMBER - Get multiple random elements
**Command**: `redis:set:randmembers`
**Parameters**: `[set_key, count]`

```sqf
"forge_server" callExtension ["redis:set:randmembers", ["available_missions", 3]]
```

**Raw Response**: `"mission_alpha,mission_gamma,mission_delta"` (comma-separated random elements)

## ⚠️ Error Responses

All commands may return error responses in this format:

**Raw Error Response**: `"Error: <description>"`

### Common Error Types
- **Pool not initialized**: `"Error: Redis pool not initialized"`
- **Connection failed**: `"Error: Connection refused (os error 61)"`
- **Key not found**: `"Error: key not found"` (for operations on non-existent keys)
- **Invalid type**: `"Error: WRONGTYPE Operation against a key holding the wrong kind of value"`
- **Index out of range**: `"Error: index out of range"` (for list operations)

### Error Handling in Game Modules
Higher-level game modules should check if the response starts with `"Error: "` to distinguish between successful responses and errors.

```json
{
  "status": "error",
  "error": "Failed to connect to Redis server"
}
```

Common error types:
- **Connection errors**: Redis server unavailable
- **Operation errors**: Invalid data type for operation
- **Parameter errors**: Missing or invalid parameters
- **Pool errors**: Connection pool exhausted

## 📊 Response Fields

### Common Fields
- `status`: Always present - "success" or "error"
- `key`: The Redis key being operated on
- `error`: Error message (only on error responses)

### Success-Specific Fields
- `data`: The retrieved data (for GET operations)
- `value`: The stored value (for SET operations)
- `was_new`: Boolean indicating if operation created new data
- `removed_count`: Number of elements removed
- `fields_set`: Number of fields set in hash operations
