mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-06-22 06:01:13 +00:00
[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>
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
# 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.
|
||||
|
||||
## 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)
|
||||
Custom exception 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 `mt0`–`mt3`; 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.Utils` — GeoUtils
|
||||
- `SatelliteProvider.DataAccess.Models` — TileEntity (for existingTiles parameter)
|
||||
- NuGet: `Newtonsoft.Json`, `Microsoft.Extensions.Http`, `Microsoft.Extensions.Options`
|
||||
|
||||
## Consumers
|
||||
- `TileService` — `GetTilesWithMetadataAsync`
|
||||
- `Program.cs` (ServeTile, GetTileByLatLon) — `DownloadSingleTileAsync`
|
||||
|
||||
## 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).
|
||||
Reference in New Issue
Block a user