Files
satellite-provider/_docs/02_document/components/02_data_access/description.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

5.2 KiB
Raw Blame History

DataAccess (Persistence)

1. High-Level Overview

Purpose: Database persistence layer providing Dapper-based repositories for tiles, regions, routes, and route points, plus DbUp-driven schema migrations.

Architectural Pattern: Repository pattern with raw SQL (Dapper)

Upstream dependencies: None at project level (uses Microsoft.Extensions abstractions from NuGet)

Downstream consumers: TileDownloader (TileRepository), RegionProcessing (RegionRepository), RouteManagement (RouteRepository, RegionRepository), WebApi (TileRepository for ServeTile)

2. Internal Interfaces

Interface: ITileRepository

Method Input Output Async Error Types
GetByIdAsync Guid TileEntity? Yes NpgsqlException
GetByTileCoordinatesAsync zoom, x, y TileEntity? Yes NpgsqlException
FindExistingTileAsync lat, lon, tileSizeM, zoom, version TileEntity? Yes NpgsqlException
GetTilesByRegionAsync lat, lon, sizeM, zoom IEnumerable<TileEntity> Yes NpgsqlException
InsertAsync TileEntity Guid Yes NpgsqlException
UpdateAsync TileEntity int Yes NpgsqlException
DeleteAsync Guid int Yes NpgsqlException

Interface: IRegionRepository

Method Input Output Async Error Types
GetByIdAsync Guid RegionEntity? Yes NpgsqlException
GetByStatusAsync string IEnumerable<RegionEntity> Yes NpgsqlException
InsertAsync RegionEntity Guid Yes NpgsqlException
UpdateAsync RegionEntity int Yes NpgsqlException
DeleteAsync Guid int Yes NpgsqlException

Interface: IRouteRepository

Method Input Output Async Error Types
GetByIdAsync Guid RouteEntity? Yes NpgsqlException
GetRoutePointsAsync Guid routeId IEnumerable<RoutePointEntity> Yes NpgsqlException
InsertRouteAsync RouteEntity Guid Yes NpgsqlException
InsertRoutePointsAsync IEnumerable<RoutePointEntity> void Yes NpgsqlException
UpdateRouteAsync RouteEntity int Yes NpgsqlException
LinkRouteToRegionAsync routeId, regionId, isGeofence, polygonIndex void Yes NpgsqlException
GetRegionIdsByRouteAsync Guid routeId IEnumerable<Guid> Yes NpgsqlException
GetGeofenceRegionIdsByRouteAsync Guid routeId IEnumerable<Guid> Yes NpgsqlException
GetGeofenceRegionsByPolygonAsync Guid routeId Dictionary<int, List<Guid>> Yes NpgsqlException
GetRoutesWithPendingMapsAsync IEnumerable<RouteEntity> Yes NpgsqlException

Class: DatabaseMigrator

Method Input Output Async Error Types
RunMigrations bool No Exception

4. Data Access Patterns

Queries

Query Frequency Hot Path Index Needed
GetByTileCoordinatesAsync (tile lookup) Very High Yes (tile_zoom, tile_x, tile_y)
GetTilesByRegionAsync (spatial) High Yes (latitude, longitude, tile_zoom)
InsertAsync (tile upsert) High Yes Composite unique on (lat, lon, zoom, size, version)
GetByStatusAsync (region polling) Medium No (status)
GetRoutesWithPendingMapsAsync Low No (request_maps, maps_ready)

Storage Estimates

Table Est. Row Count (1yr) Row Size Growth Rate
tiles ~100K1M (depends on usage) ~200B Variable
regions ~10K50K ~150B Proportional to tile requests
routes ~1K5K ~200B Low
route_points ~50K500K ~100B Proportional to routes
route_regions ~10K100K ~50B Proportional to routes

5. Implementation Details

State Management: Stateless — each repository creates a new Npgsql connection per method call. Npgsql handles internal connection pooling.

Key Dependencies:

Library Version Purpose
Dapper 2.1.35 Micro-ORM for SQL queries
Npgsql 9.0.2 PostgreSQL ADO.NET driver
dbup-postgresql 6.0.3 Schema migration runner

Error Handling: Exceptions propagate to callers. No retry logic at the repository level.

7. Caveats & Edge Cases

  • Repository interfaces are defined in this project (not in Common), creating a dependency from Services to DataAccess
  • Column mapping uses SQL aliases (tile_zoom as TileZoom) rather than Dapper attribute mapping
  • TileRepository.InsertAsync uses an upsert pattern; concurrent inserts of the same tile won't conflict
  • No soft-delete; DeleteAsync is a hard delete

8. Dependency Graph

Must be implemented after: nothing (parallel with Common) Can be implemented in parallel with: Common Blocks: TileDownloader, RegionProcessing, RouteManagement, WebApi

9. Logging Strategy

Log Level When Example
INFO Migration start/complete Starting database migrations...
ERROR Migration failure Database migration failed

Structured logging via ILogger<T>. Logger injected but rarely used in repositories.