Phase A baseline outputs from /autodev (Steps 1-5): - Problem & solution docs (_docs/00_problem, _docs/01_solution) - Codebase documentation (_docs/02_document) incl. architecture, module-layout, glossary, system-flows, baseline compliance scan - Test specs (blackbox, performance, resilience, security, resource, traceability matrix) - Test task decomposition (_docs/02_tasks/todo): AZ-285..AZ-290 - Testability refactor (_docs/04_refactoring/01-testability-refactoring): - TC-01 Move DownloadedTileInfoV2 + new ExistingTileInfo to Common.DTO - TC-02 Replace dead ISatelliteDownloader API with real signatures - TC-03 GoogleMapsDownloaderV2 implements ISatelliteDownloader - TC-04 TileService depends on ISatelliteDownloader (mockable) - TC-05 DI + endpoints use ISatelliteDownloader - Test runner scripts (scripts/run-tests.sh, run-performance-tests.sh) - Autodev state pointer (_docs/_autodev_state.md) Prepares the codebase for AZ-285..AZ-290 unit/integration test work. Co-authored-by: Cursor <cursoragent@cursor.com>
3.2 KiB
RegionProcessing
1. High-Level Overview
Purpose: Manages the lifecycle of geographic region tile requests — from API submission through a bounded queue to background processing that downloads tiles, generates CSV/summary files, and optionally stitches tiles into composite images.
Architectural Pattern: Producer-Consumer with Background Workers
Upstream dependencies: Common (DTOs, interfaces, configs, GeoUtils), DataAccess (RegionRepository), TileDownloader (ITileService)
Downstream consumers: RouteManagement (creates regions for route points and geofences), WebApi (RequestRegion/GetRegionStatus endpoints)
2. Internal Interfaces
Service: RegionService (implements IRegionService)
See Common component for interface definition. Key implementation details:
RequestRegionAsync: creates DB record, enqueues to bounded channelProcessRegionAsync: 5-minute timeout, comprehensive error handling, generates CSV + summary + optional stitched image
BackgroundService: RegionProcessingService
ExecuteAsync: spawns N parallel workers (configurable viaMaxConcurrentRegions) with staggered startup
Queue: RegionRequestQueue (implements IRegionRequestQueue)
- Bounded
Channel<RegionRequest>withBoundedChannelFullMode.Wait
4. Data Access Patterns
Queries
| Query | Frequency | Hot Path | Index Needed |
|---|---|---|---|
| Region GetByIdAsync | Very High (per processing) | Yes | PK |
| Region UpdateAsync (status transitions) | High | Yes | PK |
| Region InsertAsync | Medium | No | — |
5. Implementation Details
State Management: Region status tracked in database (queued → processing → completed/failed). Queue state is in-memory (Channel).
Key Dependencies:
| Library | Version | Purpose |
|---|---|---|
| SixLabors.ImageSharp | 3.1.11 | Tile stitching into composite JPEG |
| System.Threading.Channels | built-in | Bounded async queue |
Error Handling:
- 5-minute processing timeout per region
- Separate catch blocks for: timeout, external cancellation, rate limiting, HTTP errors, generic errors
- All failures produce a summary file with error details and set status to "failed"
7. Caveats & Edge Cases
- Queue is in-memory: pending requests are lost on process restart (no persistence)
- 5-minute timeout is hardcoded, not configurable
- Stitching crosshair is drawn with a fixed 10-pixel arm length (±5 pixels)
- Region status "queued" in code vs "pending" mentioned in some API documentation
RegionProcessingServiceworkers have random startup delay (100–500ms) to avoid thundering herd on queue
8. Dependency Graph
Must be implemented after: Common, DataAccess, TileDownloader Can be implemented in parallel with: nothing at this layer Blocks: RouteManagement (uses IRegionService to create regions)
9. Logging Strategy
| Log Level | When | Example |
|---|---|---|
| ERROR | Processing failure | Failed to process region {RegionId} |
| ERROR | Rate limit exceeded | Rate limit exceeded for region {RegionId} |
| WARN | Region not found, missing tile file | Region {RegionId} not found in database |
| INFO | Service start/stop, queue creation | Region Processing Service started with {N} workers |