[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>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-05-10 07:25:21 +03:00
parent 8b0ddae075
commit 6b373082c8
14 changed files with 290 additions and 89 deletions
@@ -1,7 +1,7 @@
# Module: Common/Interfaces
## Purpose
Service contracts defining the application's core operations. Implementations live in `SatelliteProvider.Services`.
Service contracts defining the application's core operations. Implementations live in the per-component service projects (`SatelliteProvider.Services.TileDownloader`, `SatelliteProvider.Services.RegionProcessing`, `SatelliteProvider.Services.RouteManagement`). Cross-component runtime calls between Layer-3 components flow exclusively through these interfaces — there are no compile-time `ProjectReference` entries between the three sibling service projects.
## Public Interface
@@ -9,6 +9,8 @@ Service contracts defining the application's core operations. Implementations li
- `DownloadAndStoreTilesAsync(double lat, double lon, double sizeMeters, int zoomLevel, CancellationToken) → Task<List<TileMetadata>>`: downloads missing tiles for a region and returns all tile metadata (existing + new)
- `GetTileAsync(Guid id) → Task<TileMetadata?>`: retrieve a single tile by ID
- `GetTilesByRegionAsync(double lat, double lon, double sizeMeters, int zoomLevel) → Task<IEnumerable<TileMetadata>>`: query tiles within a geographic region
- `GetOrDownloadTileAsync(int z, int x, int y, CancellationToken) → Task<TileBytes>`: serve a tile by Z/X/Y, hitting cache, then repository, then downloader (added in AZ-310)
- `DownloadAndStoreSingleTileAsync(double latitude, double longitude, int zoomLevel, CancellationToken) → Task<TileMetadata>`: download one tile by lat/lon and persist (added in AZ-311)
### IRegionService
- `RequestRegionAsync(Guid id, double lat, double lon, double sizeMeters, int zoomLevel, bool stitchTiles) → Task<RegionStatus>`: creates a region record and enqueues for async processing
@@ -3,6 +3,8 @@
## 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
@@ -14,7 +16,7 @@ Downloads satellite imagery tiles from Google Maps. Handles session token manage
- `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.
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
@@ -30,13 +32,13 @@ Custom exception thrown when Google Maps returns 429 Too Many Requests and retri
## 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
- `TileService``GetTilesWithMetadataAsync`
- `Program.cs` (ServeTile, GetTileByLatLon) — `DownloadSingleTileAsync`
- `TileService``GetTilesWithMetadataAsync` 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.
@@ -1,29 +1,35 @@
# Module: Services/TileService
## Purpose
Orchestrates tile downloading and persistence. Bridges the downloader (Google Maps) with the tile repository (PostgreSQL), handling cache checks, entity creation, and metadata mapping.
Orchestrates tile downloading and persistence. Bridges the downloader (Google Maps) with the tile repository (PostgreSQL), handling in-memory caching, entity creation, and metadata mapping. Single ownership point for all tile read/write business logic — both region-batch and single-tile API endpoints route through this service.
**csproj**: `SatelliteProvider.Services.TileDownloader/TileService.cs`
## Public Interface
### TileService (implements ITileService)
- `DownloadAndStoreTilesAsync(double lat, double lon, double sizeMeters, int zoomLevel, CancellationToken) → Task<List<TileMetadata>>`:
1. Queries existing tiles in the region from the repository (filtered to current year's version)
2. Calls `GoogleMapsDownloaderV2.GetTilesWithMetadataAsync` with existing tiles to skip
2. Calls `ISatelliteDownloader.GetTilesWithMetadataAsync` with existing tiles to skip
3. Creates `TileEntity` for each newly downloaded tile and inserts via repository (upsert)
4. Returns combined list of existing + new tile metadata
- `GetTileAsync(Guid id) → Task<TileMetadata?>`: single tile lookup
- `GetTilesByRegionAsync(double lat, double lon, double sizeMeters, int zoomLevel) → Task<IEnumerable<TileMetadata>>`: query tiles in a region
- `GetOrDownloadTileAsync(int z, int x, int y, CancellationToken) → Task<TileBytes>` (AZ-310): cache → repository → downloader fallback for single Z/X/Y serving
- `DownloadAndStoreSingleTileAsync(double latitude, double longitude, int zoomLevel, CancellationToken) → Task<TileMetadata>` (AZ-311): download one tile by lat/lon, persist, return metadata
## Internal Logic
- Version is `DateTime.UtcNow.Year` — tiles are considered fresh for the current calendar year
- `MapToMetadata(TileEntity) → TileMetadata`: entity-to-DTO mapping (static helper)
- Tile size hardcoded to 256 pixels, image type "jpg"
- `MapsVersion` formatted as `"downloaded_{date}"`
- `IMemoryCache` keyed by `(z, x, y)` with 1h absolute / 30min sliding expiration; populated on first hit and on downloader fallback
## Dependencies
- `GoogleMapsDownloaderV2` (concrete class, not interface)
- `ISatelliteDownloader` (resolved via DI; concrete is `GoogleMapsDownloaderV2`)
- `ITileRepository`
- `SatelliteProvider.Common.DTO` — GeoPoint, TileMetadata
- `IMemoryCache` (registered by `AddTileDownloader()`)
- `SatelliteProvider.Common.DTO` — GeoPoint, TileMetadata, TileBytes
- `SatelliteProvider.DataAccess.Models` — TileEntity
## Consumers
+2 -2
View File
@@ -12,8 +12,8 @@ Unit test project. Currently contains only a single dummy test as a placeholder.
No meaningful test logic.
## Dependencies
- Project references: `SatelliteProvider.Services`, `SatelliteProvider.Common`
- NuGet: xUnit (2.5.3), Moq (4.20.72), FluentAssertions (8.8.0), coverlet.collector (6.0.0), Microsoft.NET.Test.Sdk (17.8.0), Microsoft.Extensions.* (Configuration, DI, Logging, Options, Http)
- Project references: `SatelliteProvider.Services.TileDownloader`, `SatelliteProvider.Services.RegionProcessing`, `SatelliteProvider.Services.RouteManagement`, `SatelliteProvider.Common`, `SatelliteProvider.DataAccess`
- NuGet: xUnit (2.5.3), Moq (4.20.72), FluentAssertions (8.8.0), coverlet.collector (6.0.0), Microsoft.NET.Test.Sdk (17.8.0), Microsoft.Extensions.* (Caching.Memory, Configuration, DI, Logging, Options, Http)
- Has `appsettings.json` copied to output (empty config for potential future test setups)
## Consumers