|
| 1 | +--- |
| 2 | +status: complete |
| 3 | +created: 2025-09-30 |
| 4 | +tags: [task-system] |
| 5 | +priority: medium |
| 6 | +--- |
| 7 | + |
| 8 | +# Task Reconciliation Improvements |
| 9 | + |
| 10 | +## Overview |
| 11 | + |
| 12 | +This document describes the improvements made to task reconciliation in Crawlab to handle node disconnection scenarios more reliably by leveraging worker-side status caching. |
| 13 | + |
| 14 | +## Problem Statement |
| 15 | + |
| 16 | +Previously, the task reconciliation system was heavily dependent on the master node to infer task status during disconnections using heuristics. This approach had several limitations: |
| 17 | + |
| 18 | +1. **Fragile heuristics**: Status inference based on stream presence and timing could be incorrect |
| 19 | +2. **Master node dependency**: Worker nodes couldn't maintain authoritative task status during disconnections |
| 20 | +3. **Status inconsistency**: Risk of status mismatches between actual process state and database records |
| 21 | +4. **Poor handling of long-running tasks**: Network issues could cause incorrect status assumptions |
| 22 | + |
| 23 | +## Solution: Worker-Side Status Caching |
| 24 | + |
| 25 | +### Key Components |
| 26 | + |
| 27 | +#### 1. TaskStatusSnapshot Structure |
| 28 | +```go |
| 29 | +type TaskStatusSnapshot struct { |
| 30 | + TaskId primitive.ObjectID `json:"task_id"` |
| 31 | + Status string `json:"status"` |
| 32 | + Error string `json:"error,omitempty"` |
| 33 | + Pid int `json:"pid,omitempty"` |
| 34 | + Timestamp time.Time `json:"timestamp"` |
| 35 | + StartedAt *time.Time `json:"started_at,omitempty"` |
| 36 | + EndedAt *time.Time `json:"ended_at,omitempty"` |
| 37 | +} |
| 38 | +``` |
| 39 | + |
| 40 | +#### 2. TaskStatusCache |
| 41 | +- **Local persistence**: Status cache survives worker node disconnections |
| 42 | +- **File-based storage**: Cached status persists across process restarts |
| 43 | +- **Automatic cleanup**: Cache files are cleaned up when tasks complete |
| 44 | + |
| 45 | +#### 3. Enhanced Runner (`runner_status_cache.go`) |
| 46 | +- **Status caching**: Every status change is cached locally first |
| 47 | +- **Pending updates**: Status changes queue for sync when reconnected |
| 48 | +- **Persistence layer**: Status cache is saved to disk asynchronously |
| 49 | + |
| 50 | +### Workflow Improvements |
| 51 | + |
| 52 | +#### During Normal Operation |
| 53 | +1. Task status changes are cached locally on worker nodes |
| 54 | +2. Status is immediately sent to master node/database |
| 55 | +3. If database update fails, status remains cached for later sync |
| 56 | + |
| 57 | +#### During Disconnection |
| 58 | +1. Worker node continues tracking actual task/process status locally |
| 59 | +2. Status changes accumulate in pending updates queue |
| 60 | +3. Task continues running with authoritative local status |
| 61 | + |
| 62 | +#### During Reconnection |
| 63 | +1. Worker triggers sync of all pending status updates |
| 64 | +2. TaskReconciliationService prioritizes worker cache over heuristics |
| 65 | +3. Database is updated with authoritative worker-side status |
| 66 | + |
| 67 | +### Enhanced TaskReconciliationService |
| 68 | + |
| 69 | +#### Priority Order for Status Resolution |
| 70 | +1. **Worker-side status cache** (highest priority) |
| 71 | +2. **Direct process status query** |
| 72 | +3. **Heuristic detection** (fallback only) |
| 73 | + |
| 74 | +#### New Methods |
| 75 | +- `getStatusFromWorkerCache()`: Retrieves cached status from worker |
| 76 | +- `triggerWorkerStatusSync()`: Triggers sync of pending updates |
| 77 | +- Enhanced `HandleNodeReconnection()`: Leverages worker cache |
| 78 | + |
| 79 | +## Benefits |
| 80 | + |
| 81 | +### 1. Improved Reliability |
| 82 | +- **Authoritative status**: Worker nodes maintain definitive task status |
| 83 | +- **Reduced guesswork**: Less reliance on potentially incorrect heuristics |
| 84 | +- **Better consistency**: Database reflects actual process state |
| 85 | + |
| 86 | +### 2. Enhanced Resilience |
| 87 | +- **Disconnection tolerance**: Tasks continue with accurate status tracking |
| 88 | +- **Automatic recovery**: Status sync happens automatically on reconnection |
| 89 | +- **Data persistence**: Status cache survives process restarts |
| 90 | + |
| 91 | +### 3. Better Performance |
| 92 | +- **Reduced master load**: Less dependency on master node for status inference |
| 93 | +- **Faster reconciliation**: Direct access to cached status vs. complex heuristics |
| 94 | +- **Fewer database inconsistencies**: More accurate status updates |
| 95 | + |
| 96 | +## Implementation Details |
| 97 | + |
| 98 | +### File Structure |
| 99 | +``` |
| 100 | +core/task/handler/ |
| 101 | +├── runner.go # Main task runner |
| 102 | +├── runner_status_cache.go # Status caching functionality |
| 103 | +└── service_operations.go # Service methods for runner access |
| 104 | +
|
| 105 | +core/node/service/ |
| 106 | +└── task_reconciliation_service.go # Enhanced reconciliation logic |
| 107 | +``` |
| 108 | + |
| 109 | +### Configuration |
| 110 | +- Cache directory: `{workspace}/.crawlab/task_cache/` |
| 111 | +- Cache file pattern: `task_{taskId}.json` |
| 112 | +- Sync trigger: Automatic on reconnection |
| 113 | + |
| 114 | +### Error Handling |
| 115 | +- **Cache failures**: Logged but don't block task execution |
| 116 | +- **Sync failures**: Failed updates re-queued for retry |
| 117 | +- **Type mismatches**: Graceful fallback to heuristics |
| 118 | + |
| 119 | +## Usage |
| 120 | + |
| 121 | +### For Workers |
| 122 | +Status caching is automatic and transparent. No configuration required. |
| 123 | + |
| 124 | +### For Master Nodes |
| 125 | +The reconciliation service automatically detects worker-side cache availability and uses it when possible. |
| 126 | + |
| 127 | +### Monitoring |
| 128 | +- Log messages indicate when cached status is used |
| 129 | +- Failed sync attempts are logged with retry information |
| 130 | +- Cache cleanup is logged for debugging |
| 131 | + |
| 132 | +## Future Enhancements |
| 133 | + |
| 134 | +1. **Batch sync optimization**: Group multiple status updates for efficiency |
| 135 | +2. **Compression**: Compress cache files for large deployments |
| 136 | +3. **TTL support**: Automatic cache expiration for very old tasks |
| 137 | +4. **Metrics**: Expose cache hit/miss rates for monitoring |
| 138 | + |
| 139 | +## Migration |
| 140 | + |
| 141 | +This is a backward-compatible enhancement. Existing deployments will: |
| 142 | +1. Gradually benefit from improved reconciliation |
| 143 | +2. Fall back to existing heuristics when cache unavailable |
| 144 | +3. Require no configuration changes |
0 commit comments