- Rework org and store UI state modules (rename/move store/getter files, add runtime and bridge wiring) - Update store UI components and page structure (navbar/cart split, new StoreView flow) - Apply broad markdown/YAML/HTML/CSS/JS formatting cleanup across docs, templates, and workflows
427 lines
10 KiB
Markdown
427 lines
10 KiB
Markdown
# 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
|