Files
satellite-provider/_docs/02_document/modules/services_google_maps_downloader.md
T
Oleksandr Bezdieniezhnykh 6b373082c8 [AZ-315] Sync architecture docs after coupling refactor
Phase C of architecture coupling refactor (epic AZ-309). Closes the
last baseline finding (F5 — DataAccess incorrectly documented as
importing Common) and synchronizes the rest of _docs/02_document/
with the post-split project layout from AZ-312/313/314:

- module-layout.md: per-component sections for the three new csprojs
  with explicit ProjectReferences and the no-cross-sibling-reference
  invariant the split enforces.
- architecture.md: components and internal-communication tables
  updated to show calls flow through Common interfaces.
- architecture_compliance_baseline.md: F1..F5 marked Resolved with
  task IDs and commit refs; baseline summary now 0 findings.
- diagrams/components.md, components/03_tile_downloader/description.md,
  modules/{common_interfaces,services_tile_service,
  services_google_maps_downloader,tests_unit}.md updated for the
  split, RateLimitException relocation, and new ITileService methods.

Documentation-only batch — no code, no tests, no build changes.
Epic AZ-309 complete (6 tasks across 3 batches).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-10 07:25:21 +03:00

4.2 KiB
Raw Blame History

Module: Services/GoogleMapsDownloaderV2

Purpose

Downloads satellite imagery tiles from Google Maps. Handles session token management, concurrent download throttling, retry logic with exponential backoff, and tile deduplication.

csproj: SatelliteProvider.Services.TileDownloader/GoogleMapsDownloaderV2.cs

Public Interface

GoogleMapsDownloaderV2

  • Constructor: GoogleMapsDownloaderV2(ILogger, IOptions<MapConfig>, IOptions<StorageConfig>, IOptions<ProcessingConfig>, IHttpClientFactory)
  • DownloadSingleTileAsync(double lat, double lon, int zoomLevel, CancellationToken) → Task<DownloadedTileInfoV2>: downloads one tile at specified coordinates. Validates zoom level, creates session token, downloads image, saves to disk.
  • GetTilesWithMetadataAsync(GeoPoint center, double radiusM, int zoomLevel, IEnumerable<TileEntity> existingTiles, CancellationToken) → Task<List<DownloadedTileInfoV2>>: downloads all tiles in a bounding box, skipping those already present in existingTiles. Manages session token rotation.

DownloadedTileInfoV2 (record)

  • X, Y (int), ZoomLevel (int), CenterLatitude, CenterLongitude (double), FilePath (string), TileSizeMeters (double)

RateLimitException (exception)

Lives in SatelliteProvider.Common.Exceptions (relocated from this module in epic AZ-309 so RegionProcessing can catch it without acquiring a ProjectReference to TileDownloader). Thrown when Google Maps returns 429 Too Many Requests and retries are exhausted.

Internal Logic

  • Allowed zoom levels: 15, 16, 17, 18, 19 — throws ArgumentException for others
  • URL template: https://mt{server}.google.com/vt/lyrs=s&x={x}&y={y}&z={z}&token={token}
  • Session tokens: obtained via https://tile.googleapis.com/v1/createSession?key={apiKey}, rotated every SessionTokenReuseCount tiles (default: 100)
  • Concurrency control: SemaphoreSlim limits parallel downloads to MaxConcurrentDownloads (default: 4)
  • Deduplication: ConcurrentDictionary<string, Task<DownloadedTileInfoV2>> (_activeDownloads) prevents duplicate concurrent downloads of the same tile
  • Retry logic: exponential backoff (1s base, 30s max, 5 retries) for 429 and 5xx errors. Cancellation and auth errors (401, 403) propagate immediately.
  • Server selection: (x + y) % 4 distributes requests across mt0mt3; single-tile downloads always use mt0
  • Delay between requests: configurable via ProcessingConfig.DelayBetweenRequestsMs
  • Tile size calculation: CalculateTileSizeInMeters uses Earth circumference × cos(latitude) / (2^zoom × 256)

Dependencies

  • SatelliteProvider.Common.Configs — MapConfig, StorageConfig, ProcessingConfig
  • SatelliteProvider.Common.DTO — GeoPoint
  • SatelliteProvider.Common.Exceptions — RateLimitException
  • SatelliteProvider.Common.Utils — GeoUtils
  • SatelliteProvider.DataAccess.Models — TileEntity (for existingTiles parameter)
  • NuGet: Newtonsoft.Json, Microsoft.Extensions.Http, Microsoft.Extensions.Options

Consumers

  • TileServiceGetTilesWithMetadataAsync and DownloadSingleTileAsync (the API endpoints reach this class only through ITileService post AZ-310 / AZ-311)

Data Models

Produces DownloadedTileInfoV2 records; accepts TileEntity for cache checks.

Configuration

Config Key Used For
MapConfig ApiKey Session token requests
StorageConfig TilesDirectory File save paths
ProcessingConfig MaxConcurrentDownloads SemaphoreSlim capacity
ProcessingConfig DelayBetweenRequestsMs Throttle delay
ProcessingConfig SessionTokenReuseCount Token rotation threshold

External Integrations

Integration Protocol Details
Google Maps Tile API HTTPS mt*.google.com/vt/lyrs=s for tiles
Google Maps Session API HTTPS tile.googleapis.com/v1/createSession
File system Local FS Writes JPEG tiles to StorageConfig.TilesDirectory

Security

  • API key transmitted over HTTPS to Google endpoints
  • User-Agent spoofs a Chrome browser to match expected Google Maps client

Tests

No dedicated unit tests (the test file GoogleMapsDownloaderTests.cs contains only a dummy test).