component decomposition is done

This commit is contained in:
Oleksandr Bezdieniezhnykh
2025-11-24 14:09:23 +02:00
parent acec83018b
commit f50006d100
34 changed files with 8637 additions and 0 deletions
@@ -0,0 +1,331 @@
# Route API Client
## Interface Definition
**Interface Name**: `IRouteAPIClient`
### Interface Methods
```python
class IRouteAPIClient(ABC):
@abstractmethod
def update_route_waypoint(self, route_id: str, waypoint_id: str, waypoint: Waypoint) -> bool:
pass
@abstractmethod
def get_route_info(self, route_id: str) -> Optional[RouteInfo]:
pass
@abstractmethod
def batch_update_waypoints(self, route_id: str, waypoints: List[Waypoint]) -> BatchUpdateResult:
pass
```
## Component Description
### Responsibilities
- HTTP client for communicating with Route API
- Send per-frame GPS refinements to Route API
- Retrieve route metadata and waypoints
- Handle batch waypoint updates for trajectory refinements
- Manage connection pooling and retry logic
- Handle HTTP errors and timeouts
### Scope
- Synchronous HTTP client (requests library)
- Waypoint update operations
- Route metadata retrieval
- Error handling and retries
- Rate limiting and backpressure management
## API Methods
### `update_route_waypoint(route_id: str, waypoint_id: str, waypoint: Waypoint) -> bool`
**Description**: Updates a single waypoint in Route API. Called per-frame after GPS calculation.
**Called By**:
- G13 Result Manager (per-frame update)
**Input**:
```python
route_id: str
waypoint_id: str # Frame sequence number
waypoint: Waypoint:
lat: float
lon: float
altitude: Optional[float]
confidence: float
timestamp: datetime
refined: bool # Always True for GPS-Denied updates
```
**Output**:
```python
bool: True if updated successfully, False on failure
```
**HTTP Request**:
```
PUT /routes/{route_id}/waypoints/{waypoint_id}
Content-Type: application/json
{
"lat": 48.123456,
"lon": 37.654321,
"altitude": 800.0,
"confidence": 0.95,
"timestamp": "2025-11-24T10:30:00Z",
"refined": true
}
```
**Error Handling**:
- **Retry**: 3 attempts with exponential backoff (1s, 2s, 4s)
- **Timeout**: 5 seconds per request
- **404 Not Found**: Log warning, return False
- **429 Too Many Requests**: Backoff and retry
- **500 Server Error**: Retry with backoff
**Error Conditions**:
- Returns `False`: Update failed after retries
- Logs errors but doesn't raise exceptions (non-critical path)
**Test Cases**:
1. **Successful update**: Returns True
2. **Route API unavailable**: Retries 3 times, returns False
3. **Waypoint not found**: Returns False
4. **Network timeout**: Retries, returns False if all fail
5. **High-frequency updates**: 100 updates/sec sustained
---
### `get_route_info(route_id: str) -> Optional[RouteInfo]`
**Description**: Retrieves route metadata including rough waypoints and geofences.
**Called By**:
- G02 Flight Manager (during flight creation)
**Input**:
```python
route_id: str
```
**Output**:
```python
RouteInfo:
route_id: str
name: str
description: str
points: List[GPSPoint] # Rough waypoints
geofences: Geofences
waypoint_count: int
created_at: datetime
```
**HTTP Request**:
```
GET /routes/{route_id}
```
**Error Handling**:
- **Retry**: 3 attempts for transient errors
- **Timeout**: 10 seconds
- **404 Not Found**: Return None
- **500 Server Error**: Retry with backoff
**Error Conditions**:
- Returns `None`: Route not found or error after retries
- `RouteAPIError`: Critical error retrieving route
**Test Cases**:
1. **Existing route**: Returns complete RouteInfo
2. **Non-existent route**: Returns None
3. **Large route**: 2000+ waypoints → returns successfully
4. **Concurrent requests**: 10 simultaneous requests → all succeed
---
### `batch_update_waypoints(route_id: str, waypoints: List[Waypoint]) -> BatchUpdateResult`
**Description**: Updates multiple waypoints in a single request. Used for trajectory refinements.
**Called By**:
- G13 Result Manager (asynchronous refinement updates)
**Input**:
```python
route_id: str
waypoints: List[Waypoint] # Refined waypoints
```
**Output**:
```python
BatchUpdateResult:
success: bool
updated_count: int
failed_ids: List[str]
```
**HTTP Request**:
```
PUT /routes/{route_id}/waypoints/batch
Content-Type: application/json
{
"waypoints": [
{
"id": "AD000237",
"lat": 48.123,
"lon": 37.654,
"altitude": 800.0,
"confidence": 0.97,
"timestamp": "2025-11-24T10:30:00Z",
"refined": true
},
...
]
}
```
**Error Handling**:
- **Partial success**: Some waypoints update, some fail
- **Retry**: 3 attempts for complete batch
- **Timeout**: 30 seconds (larger batches)
- Returns updated_count and failed_ids
**Error Conditions**:
- Returns `success=False` with failed_ids list
**Test Cases**:
1. **Batch update 100 waypoints**: All succeed
2. **Partial failure**: 5 waypoints fail → returns failed_ids
3. **Empty batch**: Returns success=True, updated_count=0
4. **Large batch**: 500 waypoints → splits into sub-batches
## Integration Tests
### Test 1: Per-Frame Update Flow
1. Create flight and process 100 frames
2. update_route_waypoint() × 100 sequentially
3. Verify all updates successful via get_route_info()
4. Verify waypoints marked as refined=True
### Test 2: Refinement Batch Update
1. Process route, track 200 frames needing refinement
2. batch_update_waypoints() with 200 waypoints
3. Verify all updates applied
4. Handle partial failures gracefully
### Test 3: Error Recovery
1. Simulate Route API downtime
2. Attempt update_route_waypoint() → retries 3 times
3. Route API comes back online
4. Next update succeeds
### Test 4: High-Frequency Updates
1. Send 200 waypoint updates sequentially
2. Measure throughput and success rate
3. Verify no rate limiting issues
4. Verify all updates persisted
## Non-Functional Requirements
### Performance
- **update_route_waypoint**: < 100ms average latency (critical path)
- **get_route_info**: < 200ms
- **batch_update_waypoints**: < 2 seconds for 100 waypoints
- **Throughput**: Support 100 waypoint updates per second
### Scalability
- Connection pool: 20-50 connections
- Handle 1000+ waypoint updates per flight (2000+ frame flight)
- Support concurrent updates from multiple flights
### Reliability
- **Retry strategy**: 3 attempts with exponential backoff
- **Circuit breaker**: Temporarily stop requests after 5 consecutive failures
- **Timeout management**: Progressive timeouts (5s, 10s, 30s)
- **Graceful degradation**: Continue processing even if Route API unavailable
### Monitoring
- Track success/failure rates
- Monitor latency percentiles (p50, p95, p99)
- Alert on high failure rates
- Log all HTTP errors
## Dependencies
### Internal Components
- None (external HTTP client)
### External Dependencies
- **Route API**: External REST API service
- **requests** or **httpx**: HTTP client library
- **tenacity**: Retry library
- **urllib3**: Connection pooling
## Data Models
### RouteInfo
```python
class GPSPoint(BaseModel):
lat: float
lon: float
class Geofences(BaseModel):
polygons: List[Polygon]
class RouteInfo(BaseModel):
route_id: str
name: str
description: str
points: List[GPSPoint]
geofences: Geofences
waypoint_count: int
created_at: datetime
```
### Waypoint
```python
class Waypoint(BaseModel):
id: str
lat: float
lon: float
altitude: Optional[float]
confidence: float
timestamp: datetime
refined: bool
```
### BatchUpdateResult
```python
class BatchUpdateResult(BaseModel):
success: bool
updated_count: int
failed_ids: List[str]
errors: Optional[Dict[str, str]] # waypoint_id -> error_message
```
### HTTPConfig
```python
class HTTPConfig(BaseModel):
route_api_base_url: str # e.g., "http://localhost:8000"
timeout: int = 5 # seconds
max_retries: int = 3
retry_backoff: float = 1.0 # seconds
connection_pool_size: int = 50
max_batch_size: int = 500
```
### Retry Strategy
```python
retry_strategy = {
"stop": "stop_after_attempt(3)",
"wait": "wait_exponential(multiplier=1, min=1, max=10)",
"retry": "retry_if_exception_type((ConnectionError, Timeout, HTTPError))",
"reraise": True
}
```