# Module: Services/RegionService + RegionProcessingService + RegionRequestQueue ## Purpose End-to-end region processing pipeline: API request handling → queue → background worker → tile download → output file generation. Three closely coupled classes form the region processing subsystem. ## Public Interface ### RegionService (implements IRegionService) - `RequestRegionAsync(...)`: creates `RegionEntity` with status "queued", enqueues a `RegionRequest`, returns `RegionStatus` - `GetRegionStatusAsync(Guid id)`: reads region record and maps to `RegionStatus` - `ProcessRegionAsync(Guid id, CancellationToken)`: the main processing pipeline — see Internal Logic ### RegionProcessingService (BackgroundService) - `ExecuteAsync(CancellationToken)`: spawns `MaxConcurrentRegions` parallel worker tasks, each in an infinite dequeue loop ### RegionRequestQueue (implements IRegionRequestQueue) - `EnqueueAsync(RegionRequest, CancellationToken)`: writes to a bounded `Channel` - `DequeueAsync(CancellationToken)`: reads from the channel (blocks until available) - `Count`: current queue depth ## Internal Logic ### RegionService.ProcessRegionAsync 1. Sets region status to "processing" 2. Creates a 5-minute timeout `CancellationTokenSource` 3. Queries existing tiles in the region 4. Calls `TileService.DownloadAndStoreTilesAsync` to fetch missing tiles 5. Counts downloaded vs reused tiles 6. Generates CSV file (`region_{id}_ready.csv`) listing tile coordinates + paths 7. Optionally stitches tiles into a single JPEG image (if `StitchTiles` is true) 8. Generates summary file (`region_{id}_summary.txt`) 9. Updates region status to "completed" 10. On any error: sets status to "failed", generates error summary ### Tile Stitching Uses ImageSharp to: 1. Compute a tile grid from tile coordinates 2. Create a new image of `(gridWidth × 256) × (gridHeight × 256)` pixels 3. Place each tile image at its grid position 4. Draw a red crosshair at the center coordinates 5. Save as JPEG ### Error Handling Comprehensive catch blocks for: - `TaskCanceledException` (timeout vs external cancellation) - `OperationCanceledException` - `RateLimitException` (Google rate limiting) - `HttpRequestException` (with status code) - Generic `Exception` Each sets status to "failed" and writes an error summary file. ### RegionProcessingService - Spawns `MaxConcurrentRegions` worker tasks with staggered startup (100–500ms random delay) - Each worker loops: dequeue → `ProcessRegionAsync` → repeat - Graceful shutdown on cancellation ### RegionRequestQueue - Uses `System.Threading.Channels.Channel.CreateBounded` with `BoundedChannelFullMode.Wait` - Tracks `_totalEnqueued` and `_totalDequeued` counters ## Dependencies - `ITileService`, `IRegionRepository`, `IRegionRequestQueue` - `StorageConfig`, `ProcessingConfig` - `SixLabors.ImageSharp` — tile stitching - `SatelliteProvider.Common.Utils.GeoUtils` — coordinate conversion for stitching ## Consumers - `Program.cs` API endpoints — `RequestRegionAsync`, `GetRegionStatusAsync` - `RouteService` — `RequestRegionAsync` (for geofence regions) - `RouteProcessingService` — `RequestRegionAsync` (for route-point regions) ## Data Models - Input: `RegionRequest` (queue message) - Output: `RegionStatus` (API response), CSV files, summary files, stitched images - Persistence: `RegionEntity` ## Configuration - `StorageConfig.ReadyDirectory` — output file location - `ProcessingConfig.MaxConcurrentRegions` — worker count - `ProcessingConfig.QueueCapacity` — bounded channel size ## External Integrations - PostgreSQL (via repositories) - File system (CSV, summary, stitched images in `./ready/`) - Google Maps (indirectly via TileService → GoogleMapsDownloaderV2) ## Security None. ## Tests Integration tests in `RegionTests.cs` cover the request → poll → complete flow.