Files
satellite-provider/_docs/02_document/modules/services_route.md
T
Oleksandr Bezdieniezhnykh b0fffa6d42 [AZ-284] Autodev baseline + testability refactor
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>
2026-05-10 04:44:08 +03:00

4.6 KiB
Raw Blame History

Module: Services/RouteService + RouteProcessingService

Purpose

Route management and asynchronous map generation. RouteService handles route creation with intermediate point interpolation and geofencing. RouteProcessingService is a background service that polls for routes needing map generation and produces stitched images, CSVs, summaries, and ZIP archives.

Public Interface

RouteService (implements IRouteService)

  • CreateRouteAsync(CreateRouteRequest) → Task<RouteResponse>: validates input, computes intermediate points, persists route + points, creates geofence regions if specified
  • GetRouteAsync(Guid id) → Task<RouteResponse?>: retrieves route with all points

RouteProcessingService (BackgroundService)

  • ExecuteAsync(CancellationToken): polls every 5 seconds for routes with request_maps = true AND maps_ready = false, then processes each sequentially

Internal Logic

RouteService.CreateRouteAsync

  1. Validation: minimum 2 points, region size 10010000m, name required
  2. Point interpolation: for each segment between consecutive input points:
    • First point typed as "start", last as "end", middle as "action"
    • Calls GeoUtils.CalculateIntermediatePoints(start, end, 200m) to generate intermediate points
    • Each intermediate point gets PointType = "intermediate"
    • Distance from previous point is computed via GeoUtils.CalculateDistance
  3. Persistence: inserts RouteEntity + bulk inserts RoutePointEntity via repository
  4. Geofencing (if Geofences.Polygons provided):
    • Validates each polygon: non-null corners, non-zero coordinates, valid lat/lon ranges, NW lat > SE lat
    • Calls CreateGeofenceRegionGrid to divide the polygon bounding box into a grid of region centers
    • For each grid point, calls RegionService.RequestRegionAsync and links to route as geofence region
  5. Returns RouteResponse with all computed points

CreateGeofenceRegionGrid

Divides a bounding box (NW → SE) into a regular grid where each cell is regionSizeMeters wide. Uses lat/lon step sizes derived from physical distance calculations. Returns a list of center points.

RouteProcessingService.ProcessRouteSequentiallyAsync

  1. Checks route needs processing (RequestMaps && !MapsReady)
  2. Loads route points and linked region IDs (both regular and geofence)
  3. If no regions linked yet: creates region requests for each route point
  4. Checks completion status of all linked regions
  5. When enough regions complete: generates consolidated outputs
  6. Retries failed regions by creating new region requests

GenerateRouteMapsAsync

  1. Collects all tile data from completed region CSVs, deduplicating by coordinates
  2. Generates consolidated route CSV
  3. If RequestMaps: stitches all tiles into a single image with:
    • Geofence polygon borders (yellow rectangles)
    • Route point markers (red crosses, 50px arms, 10px thickness)
  4. If CreateTilesZip: creates ZIP archive of all tile files with directory structure preserved
  5. Generates route summary text file
  6. Updates route record (MapsReady = true, file paths)
  7. Cleans up individual region CSV/summary/stitched files

Tile Stitching (route-level)

  • Extracts tile X/Y from filenames (tile_{z}_{x}_{y}_{ts}.jpg)
  • Creates grid-sized image, places tiles, draws geofence borders and route points
  • Background color: black (for missing tiles)

TileInfo (helper class)

Simple data holder: Latitude, Longitude, FilePath.

Dependencies

  • IRouteRepository, IRegionRepository, IRegionService
  • SatelliteProvider.Common.DTO — GeoPoint, RoutePointDto, CreateRouteRequest, RouteResponse, GeofencePolygon
  • SatelliteProvider.Common.Utils.GeoUtils
  • SatelliteProvider.DataAccess.Models — RouteEntity, RoutePointEntity, RegionEntity
  • SixLabors.ImageSharp — tile stitching
  • System.IO.Compression — ZIP creation
  • IServiceProvider — creates scoped IRegionService instances

Consumers

  • Program.cs API endpoints — CreateRouteAsync, GetRouteAsync

Data Models

  • Input: CreateRouteRequest, RoutePoint, GeofencePolygon
  • Output: RouteResponse, RoutePointDto, CSV/summary/stitched/zip files
  • Persistence: RouteEntity, RoutePointEntity, route_regions junction

Configuration

  • StorageConfig.ReadyDirectory — output directory
  • StorageConfig.TilesDirectory — used for ZIP relative paths

External Integrations

  • PostgreSQL (via repositories)
  • File system (CSV, summary, stitched image, ZIP in ./ready/)
  • Region processing pipeline (for tile downloading)

Security

None.

Tests

Integration tests in BasicRouteTests.cs, ComplexRouteTests.cs, ExtendedRouteTests.cs.