Files
Job-List/REDIS_IMPLEMENTATION.md
T

275 lines
7.8 KiB
Markdown

# 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_URL` environment variable
- Defaults to `redis://localhost:6379` if not configured
- Connection pooling and automatic reconnection on failures
- Error handling and logging
**Cache Operations:**
- `getCached<T>(key)` - Retrieve cached data by key
- `setCached(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 results
- `getCachedSearchResults(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:**
```json
{
"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:**
```json
{
"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:**
```json
{
"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/clear` endpoint for manual cache invalidation
## Configuration
### Environment Variables
Add to your `.env` file (or secrets location):
```bash
# 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
```json
{
"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
1. Client requests data via `/api/jobs` or `/api/jobs/search`
2. Server checks Redis cache first
3. On cache hit: Return cached data immediately
4. On cache miss: Fetch from PocketBase, cache it, then return
### Write Path
1. Client submits update via `/api/submit`
2. Server updates PocketBase directly
3. Server invalidates all related caches
4. 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:
1. Connect to the same Redis instance used by Job-Info-Prod
2. Implement Redis PubSub or webhooks for real-time cache invalidation
3. Gradually transition writes to Job-Info-Prod backend
4. Eventually use Job-Info-Prod as primary data source
## Testing
### Test Cache Functionality
1. **Test cached reads:**
```bash
# 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
```
2. **Test search:**
```bash
# Search for jobs
curl -H "X-PocketBase-Token: YOUR_TOKEN" "http://localhost:3025/api/jobs/search?q=Estimating"
```
3. **Test cache invalidation:**
```bash
# Clear cache
curl -X POST -H "X-PocketBase-Token: YOUR_TOKEN" http://localhost:3025/api/cache/clear
```
### Verify Redis Connection
```bash
# 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:
1. Check `REDIS_URL` environment variable
2. Verify Redis/Valkey is running: `redis-cli ping`
3. Check network connectivity to Redis server
4. Review server logs for connection errors
### Cache Not Working
If cache doesn't seem to work:
1. Verify Redis is accessible
2. Check server logs for cache errors
3. Try manually clearing cache: `POST /api/cache/clear`
4. Verify TTL values are appropriate for your use case
### Stale Data
If seeing stale data:
1. Cache invalidation should happen automatically on updates
2. Manually clear cache if needed
3. Consider reducing TTL values for more frequent updates
4. Check if updates are going through `/api/submit` endpoint