@objectql/driver-redis
v4.2.2
Published
Production-ready Redis driver for ObjectQL with full CRUD, distinct(), aggregate(), and batch operations support
Maintainers
Readme
Redis Driver for ObjectQL
Version 4.0.1 - Enhanced with production-ready features
Status: Production-ready with retry logic, connection pooling, and enhanced error handling.
Overview
The Redis Driver adapts Redis (a key-value store) to work with ObjectQL's universal data protocol. This driver has been enhanced from a reference implementation to a production-ready solution with automatic reconnection, retry logic, and improved error handling.
This driver implements both the legacy Driver interface from @objectql/types and the standard DriverInterface from @objectstack/spec for full compatibility with the new kernel-based plugin system.
Features
- ✅ Basic CRUD operations (Create, Read, Update, Delete)
- ✅ v4.0: executeQuery() with QueryAST support
- ✅ v4.0: executeCommand() with unified command interface
- ✅ v4.0: Bulk operations (bulkCreate, bulkUpdate, bulkDelete) using Redis PIPELINE
- ✅ v4.0.1: Automatic reconnection with exponential backoff
- ✅ v4.0.1: Configurable retry logic for connection attempts
- ✅ v4.0.1: Enhanced error handling and logging
- ✅ v4.0.1: Connection health checks with latency monitoring
- ✅ Query filtering (in-memory)
- ✅ Sorting (in-memory)
- ✅ Pagination (skip/limit)
- ✅ Count operations
- ⚠️ Limited performance for complex queries (scans all keys)
- ❌ No native aggregation support
- ❌ No transaction support (planned for v4.1)
- ❌ No schema introspection
Use Cases
This driver is suitable for:
- Caching Layer: Store frequently accessed data with automatic reconnection
- Session Storage: User sessions and temporary data with high availability
- Simple Key-Value Storage: When you don't need complex queries
- Development/Testing: Quick prototyping with production-like resilience
- Microservices: Distributed systems requiring resilient Redis connections
Installation
npm install @objectql/driver-redis redisConfiguration
Basic Configuration
import { ObjectQL } from '@objectql/core';
import { RedisDriver } from '@objectql/driver-redis';
const driver = new RedisDriver({
url: 'redis://localhost:6379'
});
const app = new ObjectQL({
driver: driver
});
await app.init();Production Configuration
const driver = new RedisDriver({
url: 'redis://localhost:6379',
// Redis client options
options: {
password: 'your-password',
database: 0
},
// Connection retry configuration
retry: {
maxAttempts: 10, // Maximum retry attempts (default: 10)
initialDelay: 100, // Initial delay in ms (default: 100)
maxDelay: 3000, // Maximum delay in ms (default: 3000)
exponentialBackoff: true // Use exponential backoff (default: true)
},
// Connection pool configuration
pool: {
min: 1, // Minimum connections (default: 1)
max: 10 // Maximum connections (default: 10)
},
// Enable automatic reconnection (default: true)
autoReconnect: true
});Basic Usage
// Create a record
const user = await app.create('users', {
name: 'Alice',
email: '[email protected]',
role: 'admin'
});
console.log(user.id); // Auto-generated ID
// Find records
const users = await app.find('users', {
filters: [['role', '=', 'admin']],
sort: [['name', 'asc']],
limit: 10
});
// Update a record
await app.update('users', user.id, {
email: '[email protected]'
});
// Delete a record
await app.delete('users', user.id);Performance Considerations
⚠️ Important Limitations
This Redis driver uses full key scanning for queries, which means:
- Find Operations: Scans ALL keys matching
objectName:*pattern - Filters: Applied in-memory after loading all records
- Count: Loads all records to count matches
Performance Impact
- Small Datasets (< 1000 records): ✅ Acceptable
- Medium Datasets (1K-10K records): ⚠️ Slow for complex queries
- Large Datasets (> 10K records): ❌ Not recommended
Optimization Strategies
For production use, consider:
- Redis Modules: Use RedisJSON or RedisSearch for better query support
- Indexing: Implement secondary indexes using Redis Sets
- Hybrid Approach: Use Redis for caching, another driver for queries
- Sharding: Distribute data across multiple Redis instances
How Data is Stored
Records are stored as JSON strings with keys following the pattern:
objectName:idExample:
users:user-123 → {"id":"user-123","name":"Alice","email":"[email protected]","created_at":"2026-01-15T00:00:00.000Z"}API Reference
Constructor
new RedisDriver(config: RedisDriverConfig)Config Options:
url(string, required): Redis connection URLoptions(object, optional): Additional Redis client options
Methods
All standard Driver interface methods are implemented:
Legacy Driver Interface:
find(objectName, query, options)- Query multiple recordsfindOne(objectName, id, query, options)- Get single record by IDcreate(objectName, data, options)- Create new recordupdate(objectName, id, data, options)- Update existing recorddelete(objectName, id, options)- Delete recordcount(objectName, filters, options)- Count matching recordsdisconnect()- Close Redis connection
DriverInterface v4.0 Methods:
executeQuery(ast, options)- Execute queries using QueryAST formatexecuteCommand(command, options)- Execute commands (create, update, delete, bulk operations)
executeQuery Examples
The new executeQuery method uses the QueryAST format from @objectstack/spec:
// Basic query
const result = await driver.executeQuery({
object: 'users',
fields: ['name', 'email']
});
console.log(result.value); // Array of users
console.log(result.count); // Number of results
// Query with filters
const result = await driver.executeQuery({
object: 'users',
filters: {
type: 'comparison',
field: 'age',
operator: '>',
value: 18
},
sort: [{ field: 'name', order: 'asc' }],
top: 10,
skip: 0
});
// Complex filters (AND/OR)
const result = await driver.executeQuery({
object: 'users',
filters: {
type: 'and',
children: [
{ type: 'comparison', field: 'role', operator: '=', value: 'user' },
{ type: 'comparison', field: 'age', operator: '>', value: 30 }
]
}
});executeCommand Examples
The new executeCommand method provides a unified interface for mutations:
// Create a record
const result = await driver.executeCommand({
type: 'create',
object: 'users',
data: { name: 'Alice', email: '[email protected]' }
});
console.log(result.success); // true
console.log(result.data); // Created user object
console.log(result.affected); // 1
// Update a record
const result = await driver.executeCommand({
type: 'update',
object: 'users',
id: 'user-123',
data: { email: '[email protected]' }
});
// Delete a record
const result = await driver.executeCommand({
type: 'delete',
object: 'users',
id: 'user-123'
});
// Bulk create (uses Redis PIPELINE for performance)
const result = await driver.executeCommand({
type: 'bulkCreate',
object: 'users',
records: [
{ name: 'Alice', age: 30 },
{ name: 'Bob', age: 25 },
{ name: 'Charlie', age: 35 }
]
});
console.log(result.affected); // 3
// Bulk update
const result = await driver.executeCommand({
type: 'bulkUpdate',
object: 'users',
updates: [
{ id: 'user-1', data: { age: 31 } },
{ id: 'user-2', data: { age: 26 } }
]
});
// Bulk delete
const result = await driver.executeCommand({
type: 'bulkDelete',
object: 'users',
ids: ['user-1', 'user-2', 'user-3']
});Example: Using as Cache Layer
Redis works great as a caching layer in front of another driver:
import { SqlDriver } from '@objectql/driver-sql';
import { RedisDriver } from '@objectql/driver-redis';
// Primary database
const sqlDriver = new SqlDriver({
client: 'pg',
connection: process.env.DATABASE_URL
});
// Cache layer
const redisDriver = new RedisDriver({
url: process.env.REDIS_URL
});
// Use SQL for writes, Redis for cached reads
const app = new ObjectQL({
datasources: {
default: sqlDriver,
cache: redisDriver
}
});Development
Building
pnpm buildTesting
# Start Redis
docker run -d -p 6379:6379 redis:latest
# Run tests
pnpm testProject Structure
packages/drivers/redis/
├── src/
│ └── index.ts # Main driver implementation
├── test/
│ └── index.test.ts # Unit tests
├── package.json
├── tsconfig.json
├── jest.config.js
└── README.mdExtending This Driver
This is an example implementation. To make it production-ready:
Add Redis Modules Support
- RedisJSON for native JSON queries
- RedisSearch for full-text search
Implement Secondary Indexes
- Use Redis Sets for indexed fields
- Maintain index consistency
Add Transaction Support
- Use Redis MULTI/EXEC for atomic operations
Optimize Queries
- Avoid scanning all keys
- Implement cursor-based pagination
Add Connection Pooling
- Handle connection failures
- Implement retry logic
Related Documentation
License
MIT - Same as ObjectQL
Contributing
This is an example driver for educational purposes. For production Redis support:
- Fork this implementation
- Add production features (see "Extending This Driver")
- Publish as a community driver
- Share with the ObjectQL community
Questions?
- 📖 Read the Custom Driver Guide
- 💬 Ask in ObjectQL Discussions
- 🐛 Report Issues
