[AZ-357] Refactor C06: drop tile Version concept; cumulative review batches 7-9
ci/woodpecker/push/01-test Pipeline was successful
ci/woodpecker/push/02-build-push Pipeline was successful

AZ-357 — eliminate year-based tile cache expiry (LF-1):
- Migration 012: drop 5-col unique index, dedupe by (lat,lon,zoom,
  size) keeping max(updated_at), add new 4-col unique index, make
  version column nullable + drop default. Column itself preserved
  per coderule (column drops require explicit confirmation; tracked
  in AZ-373 / C20).
- TileEntity.Version, TileMetadata.Version, DownloadTileResponse.
  Version: int -> int? (HTTP shape preserved; field still in JSON).
- TileService.DownloadAndStoreTilesAsync: drop currentVersion year
  computation and the .Where(t => t.Version == currentVersion)
  cache filter. BuildTileEntity: drop year arg; write Version=null.
- TileRepository: ON CONFLICT now 4-col; lookup queries
  ORDER BY updated_at DESC instead of version DESC.
- Tests: replace inverted BT02b with positive AZ357_AC1
  (prior-year cached tile is reused). Add BuildTileEntity_
  DoesNotPopulateVersion_AZ357 to enforce the no-write contract.
- 69 unit + 5 smoke + 3 stub-contract integration tests pass.

Cumulative code review (batches 7-9, 7 tasks): VERDICT=PASS.
Report at _docs/03_implementation/reviews/batch_09_review.md.
Zero Critical/High/Medium/Low findings. Architecture baseline
remains clean.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-05-11 00:20:47 +03:00
parent 5a28f67d33
commit 581dff206e
12 changed files with 306 additions and 41 deletions
@@ -33,40 +33,38 @@ public class TileService : ITileService
}
public async Task<List<TileMetadata>> DownloadAndStoreTilesAsync(
double latitude,
double longitude,
double sizeMeters,
int zoomLevel,
double latitude,
double longitude,
double sizeMeters,
int zoomLevel,
CancellationToken cancellationToken = default)
{
var currentVersion = DateTime.UtcNow.Year;
var existingTiles = await _tileRepository.GetTilesByRegionAsync(latitude, longitude, sizeMeters, zoomLevel);
var existingTilesList = existingTiles.Where(t => t.Version == currentVersion).ToList();
var existingTilesList = existingTiles.ToList();
var centerPoint = new GeoPoint(latitude, longitude);
var existingTileInfos = existingTilesList
.Select(t => new ExistingTileInfo(t.Latitude, t.Longitude, t.TileZoom))
.ToList();
var downloadedTiles = await _downloader.GetTilesWithMetadataAsync(
centerPoint,
sizeMeters / 2,
zoomLevel,
centerPoint,
sizeMeters / 2,
zoomLevel,
existingTileInfos,
cancellationToken);
var result = new List<TileMetadata>();
foreach (var existingTile in existingTilesList)
{
result.Add(MapToMetadata(existingTile));
}
foreach (var downloadedTile in downloadedTiles)
{
var tileEntity = BuildTileEntity(downloadedTile, currentVersion);
var tileEntity = BuildTileEntity(downloadedTile);
await _tileRepository.InsertAsync(tileEntity);
result.Add(MapToMetadata(tileEntity));
}
@@ -110,7 +108,7 @@ public class TileService : ITileService
{
var tileCenter = GeoUtils.TileToWorldPos(x, y, z);
var downloaded = await _downloader.DownloadSingleTileAsync(tileCenter.Lat, tileCenter.Lon, z, cancellationToken);
var entity = BuildTileEntity(downloaded, DateTime.UtcNow.Year);
var entity = BuildTileEntity(downloaded);
await _tileRepository.InsertAsync(entity);
filePath = entity.FilePath;
}
@@ -132,12 +130,12 @@ public class TileService : ITileService
CancellationToken cancellationToken = default)
{
var downloaded = await _downloader.DownloadSingleTileAsync(latitude, longitude, zoomLevel, cancellationToken);
var entity = BuildTileEntity(downloaded, DateTime.UtcNow.Year);
var entity = BuildTileEntity(downloaded);
await _tileRepository.InsertAsync(entity);
return MapToMetadata(entity);
}
private static TileEntity BuildTileEntity(DownloadedTileInfoV2 downloaded, int currentVersion)
private static TileEntity BuildTileEntity(DownloadedTileInfoV2 downloaded)
{
var now = DateTime.UtcNow;
return new TileEntity
@@ -152,7 +150,7 @@ public class TileService : ITileService
TileSizePixels = 256,
ImageType = "jpg",
MapsVersion = $"downloaded_{now:yyyy-MM-dd}",
Version = currentVersion,
Version = null,
FilePath = downloaded.FilePath,
CreatedAt = now,
UpdatedAt = now