7.8 KiB
7.8 KiB
Redis/Valkey Caching & Search Implementation
Overview
This implementation adds Redis/Valkey caching and search functionality to the Job-List application, following the same patterns used in Job-Info-Prod.
Features Implemented
1. Redis/Valkey Connection Module (redis.ts)
Connection Management:
- Automatic connection to Redis/Valkey using
REDIS_URLenvironment variable - Defaults to
redis://localhost:6379if not configured - Connection pooling and automatic reconnection on failures
- Error handling and logging
Cache Operations:
getCached<T>(key)- Retrieve cached data by keysetCached(key, data, options)- Store data with TTL (default 5 minutes)deleteCached(keyOrPattern)- Delete cache by key or pattern (supports wildcards)invalidateSearchCache()- Clear all search results cache
Search Operations:
cacheSearchResults(query, results, options)- Cache search resultsgetCachedSearchResults(query)- Retrieve cached search results
2. API Endpoints (server.ts)
GET /api/jobs
Purpose: Fetch all job records with Redis caching
Headers:
X-PocketBase-Token- User authentication token (required)
Response:
{
"success": true,
"data": [...],
"cached": true/false
}
Caching:
- Cache key:
jobs:all:Job_Info_TestEnv - TTL: 5 minutes (300 seconds)
- Automatically fetches from PocketBase if cache miss
GET /api/jobs/search?q=<query>
Purpose: Search jobs across multiple fields with caching
Headers:
X-PocketBase-Token- User authentication token (required)
Query Parameters:
q- Search query (required)
Searchable Fields:
- Job_Number
- Job_Full_Name
- Job_Name
- Company_Client
- Contact_Person
- Estimator
- Job_Status
- Project_Manager
- Notes
Response:
{
"success": true,
"data": [...],
"query": "search term",
"cached": true/false
}
Caching:
- Cache key:
search:<lowercase_query> - TTL: 3 minutes (180 seconds)
- Case-insensitive query matching
POST /api/cache/clear
Purpose: Manually clear all caches (admin/debugging)
Headers:
X-PocketBase-Token- User authentication token (required)
Response:
{
"success": true,
"message": "Cache cleared successfully"
}
3. Cache Invalidation
Automatic Cache Clearing:
- When data is submitted via
/api/submit, all job caches are automatically cleared - Ensures cache consistency with PocketBase data
- Clears both job data cache and search result caches
Manual Cache Clearing:
- Use
/api/cache/clearendpoint for manual cache invalidation
Configuration
Environment Variables
Add to your .env file (or secrets location):
# Redis/Valkey Configuration
REDIS_URL=redis://localhost:6379
# For production, connect to the same instance as Job-Info-Prod
# REDIS_URL=redis://redis-server:6379
# With authentication: REDIS_URL=redis://:password@redis-server:6379
Dependencies Added
{
"dependencies": {
"ioredis": "^5.8.2"
},
"devDependencies": {
"@types/ioredis": "^5.0.0"
}
}
Architecture
┌──────────────┐
│ Frontend │
│ (HTML/JS) │
└──────┬───────┘
│
│ HTTP Requests
│ X-PocketBase-Token header
│
┌──────▼────────────────────────────────┐
│ Server (server.ts) │
│ ┌────────────────────────────────┐ │
│ │ 1. Check Redis Cache │ │
│ │ ↓ (if miss) │ │
│ │ 2. Fetch from PocketBase │ │
│ │ ↓ │ │
│ │ 3. Store in Redis Cache │ │
│ │ ↓ │ │
│ │ 4. Return to client │ │
│ └────────────────────────────────┘ │
└───────────┬───────────────────────────┘
│
├─────────────┬──────────────┐
│ │ │
┌───────▼──────┐ ┌──▼──────────┐ │
│ Redis/ │ │ PocketBase │ │
│ Valkey │ │ Database │ │
│ (Cache) │ │ (Source) │ │
└──────────────┘ └─────────────┘ │
│
Same Redis instance
as Job-Info-Prod
Cache Strategy
Read Path
- Client requests data via
/api/jobsor/api/jobs/search - Server checks Redis cache first
- On cache hit: Return cached data immediately
- On cache miss: Fetch from PocketBase, cache it, then return
Write Path
- Client submits update via
/api/submit - Server updates PocketBase directly
- Server invalidates all related caches
- Next read will fetch fresh data from PocketBase and cache it
Benefits
- Reduced Load: Minimizes PocketBase queries
- Faster Response: Cached responses are ~10-100x faster
- Scalability: Multiple instances can share the same cache
- Consistency: Cache invalidation ensures data freshness
Future Migration to Job-Info-Prod
The current implementation:
- ✅ Uses Redis/Valkey for caching and search
- ✅ Keeps PocketBase as source of truth for writes
- ✅ Can connect to the same Redis instance as Job-Info-Prod
Future migration path:
- Connect to the same Redis instance used by Job-Info-Prod
- Implement Redis PubSub or webhooks for real-time cache invalidation
- Gradually transition writes to Job-Info-Prod backend
- Eventually use Job-Info-Prod as primary data source
Testing
Test Cache Functionality
- Test cached reads:
# First request (cache miss)
curl -H "X-PocketBase-Token: YOUR_TOKEN" http://localhost:3025/api/jobs
# Second request within 5 minutes (cache hit)
curl -H "X-PocketBase-Token: YOUR_TOKEN" http://localhost:3025/api/jobs
- Test search:
# Search for jobs
curl -H "X-PocketBase-Token: YOUR_TOKEN" "http://localhost:3025/api/jobs/search?q=Estimating"
- Test cache invalidation:
# Clear cache
curl -X POST -H "X-PocketBase-Token: YOUR_TOKEN" http://localhost:3025/api/cache/clear
Verify Redis Connection
# Check if Redis is running
redis-cli ping
# Should return: PONG
# Monitor Redis operations
redis-cli monitor
# Then make API requests to see cache operations
Monitoring
Redis operations are logged to console:
- "Jobs fetched from cache" - Data served from cache
- "Jobs fetched from PocketBase and cached" - Cache miss, data fetched and cached
- "Search results fetched from cache" - Search results from cache
- "Cache cleared successfully" - Manual cache clear
Troubleshooting
Redis Connection Issues
If Redis connection fails:
- Check
REDIS_URLenvironment variable - Verify Redis/Valkey is running:
redis-cli ping - Check network connectivity to Redis server
- Review server logs for connection errors
Cache Not Working
If cache doesn't seem to work:
- Verify Redis is accessible
- Check server logs for cache errors
- Try manually clearing cache:
POST /api/cache/clear - Verify TTL values are appropriate for your use case
Stale Data
If seeing stale data:
- Cache invalidation should happen automatically on updates
- Manually clear cache if needed
- Consider reducing TTL values for more frequent updates
- Check if updates are going through
/api/submitendpoint