# Feature: Processing State Persistence

## Description
Persistence layer for flight processing state, frame results, and heading history. Supports crash recovery by persisting processing progress and enables temporal smoothing through heading history tracking. Critical for maintaining processing continuity and data integrity during frame refinement operations.

## Component APIs Implemented
- `save_flight_state(flight_state: FlightState) -> bool`
- `load_flight_state(flight_id: str) -> Optional[FlightState]`
- `query_processing_history(filters: Dict[str, Any]) -> List[FlightState]`
- `save_frame_result(flight_id: str, frame_result: FrameResult) -> bool`
- `get_frame_results(flight_id: str) -> List[FrameResult]`
- `save_heading(flight_id: str, frame_id: int, heading: float, timestamp: datetime) -> bool`
- `get_heading_history(flight_id: str, last_n: Optional[int] = None) -> List[HeadingRecord]`
- `get_latest_heading(flight_id: str) -> Optional[float]`

## External Tools and Services
- **PostgreSQL**: Primary database
- **SQLAlchemy**: ORM and connection pooling

## Internal Methods
| Method | Purpose |
|--------|---------|
| `_build_flight_state_from_row(row)` | Map database row to FlightState object |
| `_build_frame_result_from_row(row)` | Map database row to FrameResult object |
| `_build_heading_record_from_row(row)` | Map database row to HeadingRecord object |
| `_upsert_flight_state(state)` | Insert or update flight state (single source of truth) |
| `_upsert_frame_result(flight_id, result)` | Insert or update frame result (handles refinement updates) |

## Unit Tests
1. **save_flight_state**
   - New state → created successfully
   - Update existing state → overwrites previous
   - Verify all fields persisted correctly
   - Verify heading NOT stored in flight_state (use heading_history)

2. **load_flight_state**
   - Existing state → returns FlightState object
   - Non-existent flight → returns None
   - Verify all fields deserialized correctly

3. **query_processing_history**
   - Filter by date range → returns flights in range
   - Filter by status → returns matching flights
   - Combined filters → returns intersection
   - No matches → returns empty list

4. **save_frame_result**
   - New frame → persisted successfully
   - Update on refinement → overwrites with refined=True
   - Verify GPS, altitude, heading, confidence persisted
   - Verify timestamp and updated_at set correctly

5. **get_frame_results**
   - Flight with 500 frames → returns all results ordered by frame_id
   - No results → returns empty list
   - Performance: 2000 frames returned within 100ms

6. **save_heading**
   - New heading → persisted correctly
   - Overwrite same frame_id → updates value
   - Verify timestamp persisted
   - Heading range validation (0-360)

7. **get_heading_history**
   - All headings (last_n=None) → returns complete history
   - Last 10 headings → returns 10 most recent by timestamp
   - Non-existent flight → returns empty list
   - Ordered by frame_id descending

8. **get_latest_heading**
   - Has history → returns latest heading value
   - No history → returns None
   - After multiple saves → returns most recent

## Integration Tests
1. **Processing state recovery**
   - Save state with frames_processed=250
   - Simulate crash (close connection)
   - Reconnect and load_flight_state()
   - Verify state intact, processing can resume

2. **Frame result refinement flow**
   - save_frame_result() with refined=False
   - Later, save_frame_result() with refined=True
   - get_frame_results() → shows refined=True
   - Verify GPS coordinates updated

3. **Heading history for smoothing**
   - save_heading() × 100 frames
   - get_heading_history(last_n=10)
   - Verify correct 10 headings returned for smoothing calculation
   - Verify ordering correct for temporal analysis

4. **High-frequency persistence**
   - Concurrent save_frame_result() and save_heading() calls
   - Measure throughput > 200 ops/sec
   - Verify no data loss or corruption

5. **Transactional consistency**
   - Transaction: update frame_result + update waypoint
   - Verify atomic update or complete rollback


