updated cache to support setting ttl
This commit is contained in:
parent
a49cb9ae98
commit
d6ca9fe93c
3 changed files with 336 additions and 7 deletions
148
docs/enhanced-cache-usage.md
Normal file
148
docs/enhanced-cache-usage.md
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
# Enhanced Cache Provider Usage
|
||||
|
||||
The Redis cache provider now supports advanced TTL handling and conditional operations.
|
||||
|
||||
## Basic Usage (Backward Compatible)
|
||||
|
||||
```typescript
|
||||
import { RedisCache } from '@stock-bot/cache';
|
||||
|
||||
const cache = new RedisCache({
|
||||
keyPrefix: 'trading:',
|
||||
defaultTTL: 3600 // 1 hour
|
||||
});
|
||||
|
||||
// Simple set with TTL (old way - still works)
|
||||
await cache.set('user:123', userData, 1800); // 30 minutes
|
||||
|
||||
// Simple get
|
||||
const user = await cache.get<UserData>('user:123');
|
||||
```
|
||||
|
||||
## Enhanced Set Options
|
||||
|
||||
```typescript
|
||||
// Preserve existing TTL when updating
|
||||
await cache.set('user:123', updatedUserData, { preserveTTL: true });
|
||||
|
||||
// Only set if key exists (update operation)
|
||||
const oldValue = await cache.set('user:123', newData, {
|
||||
onlyIfExists: true,
|
||||
getOldValue: true
|
||||
});
|
||||
|
||||
// Only set if key doesn't exist (create operation)
|
||||
await cache.set('user:456', newUser, {
|
||||
onlyIfNotExists: true,
|
||||
ttl: 7200 // 2 hours
|
||||
});
|
||||
|
||||
// Get old value when setting new one
|
||||
const previousData = await cache.set('session:abc', sessionData, {
|
||||
getOldValue: true,
|
||||
ttl: 1800
|
||||
});
|
||||
```
|
||||
|
||||
## Convenience Methods
|
||||
|
||||
```typescript
|
||||
// Update value preserving TTL
|
||||
await cache.update('user:123', updatedUserData);
|
||||
|
||||
// Set only if exists
|
||||
const updated = await cache.setIfExists('user:123', newData, 3600);
|
||||
|
||||
// Set only if not exists (returns true if created)
|
||||
const created = await cache.setIfNotExists('user:456', userData);
|
||||
|
||||
// Replace existing key with new TTL
|
||||
const oldData = await cache.replace('user:123', newData, 7200);
|
||||
|
||||
// Atomic field updates
|
||||
await cache.updateField('counter:views', (current) => (current || 0) + 1);
|
||||
|
||||
await cache.updateField('user:123', (user) => ({
|
||||
...user,
|
||||
lastSeen: new Date().toISOString(),
|
||||
loginCount: (user?.loginCount || 0) + 1
|
||||
}));
|
||||
```
|
||||
|
||||
## Stock Bot Use Cases
|
||||
|
||||
### 1. Rate Limiting
|
||||
```typescript
|
||||
// Only create rate limit if not exists
|
||||
const rateLimited = await cache.setIfNotExists(
|
||||
`ratelimit:${userId}:${endpoint}`,
|
||||
{ count: 1, resetTime: Date.now() + 60000 },
|
||||
60 // 1 minute
|
||||
);
|
||||
|
||||
if (!rateLimited) {
|
||||
// Increment existing counter
|
||||
await cache.updateField(`ratelimit:${userId}:${endpoint}`, (data) => ({
|
||||
...data,
|
||||
count: data.count + 1
|
||||
}));
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Session Management
|
||||
```typescript
|
||||
// Update session data without changing expiration
|
||||
await cache.update(`session:${sessionId}`, {
|
||||
...sessionData,
|
||||
lastActivity: Date.now()
|
||||
});
|
||||
```
|
||||
|
||||
### 3. Cache Warming
|
||||
```typescript
|
||||
// Only update existing cached data, don't create new entries
|
||||
const warmed = await cache.setIfExists(`stock:${symbol}:price`, latestPrice);
|
||||
if (warmed) {
|
||||
console.log(`Warmed cache for ${symbol}`);
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Atomic Counters
|
||||
```typescript
|
||||
// Thread-safe counter increments
|
||||
await cache.updateField('metrics:api:calls', (count) => (count || 0) + 1);
|
||||
await cache.updateField('metrics:errors:500', (count) => (count || 0) + 1);
|
||||
```
|
||||
|
||||
### 5. TTL Preservation for Frequently Updated Data
|
||||
```typescript
|
||||
// Keep original expiration when updating frequently changing data
|
||||
await cache.set(`portfolio:${userId}:positions`, positions, { preserveTTL: true });
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
The cache provider includes robust error handling:
|
||||
|
||||
```typescript
|
||||
try {
|
||||
await cache.set('key', value);
|
||||
} catch (error) {
|
||||
// Errors are logged and fallback values returned
|
||||
// The cache operations are non-blocking
|
||||
}
|
||||
|
||||
// Check cache health
|
||||
const isHealthy = await cache.health();
|
||||
|
||||
// Wait for cache to be ready
|
||||
await cache.waitForReady(10000); // 10 second timeout
|
||||
```
|
||||
|
||||
## Performance Benefits
|
||||
|
||||
1. **Atomic Operations**: `updateField` uses Lua scripts to prevent race conditions
|
||||
2. **TTL Preservation**: Avoids unnecessary TTL resets on updates
|
||||
3. **Conditional Operations**: Reduces network round trips
|
||||
4. **Shared Connections**: Efficient connection pooling
|
||||
5. **Error Recovery**: Graceful degradation when Redis is unavailable
|
||||
Loading…
Add table
Add a link
Reference in a new issue