mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-06-22 07:41:13 +00:00
[AZ-357] Refactor C06: drop tile Version concept; cumulative review batches 7-9
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:
@@ -128,13 +128,13 @@ public class TileServiceTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DownloadAndStoreTilesAsync_IgnoresStaleVersionCachedTiles_BT02b()
|
||||
public async Task DownloadAndStoreTilesAsync_TreatsCachedTileFromPriorYearAsFresh_AZ357_AC1()
|
||||
{
|
||||
// Arrange
|
||||
var downloader = new Mock<ISatelliteDownloader>();
|
||||
var tileRepo = new Mock<ITileRepository>();
|
||||
|
||||
var stale = new List<TileEntity>
|
||||
var priorYearCached = new List<TileEntity>
|
||||
{
|
||||
new()
|
||||
{
|
||||
@@ -143,13 +143,15 @@ public class TileServiceTests
|
||||
Latitude = TestCoordinates.TileLat,
|
||||
Longitude = TestCoordinates.TileLon,
|
||||
Version = DateTime.UtcNow.Year - 1,
|
||||
FilePath = "tiles/18/0/0/old.jpg",
|
||||
FilePath = "tiles/18/0/0/cached_prior_year.jpg",
|
||||
TileSizePixels = 256,
|
||||
ImageType = "jpg",
|
||||
},
|
||||
};
|
||||
tileRepo
|
||||
.Setup(r => r.GetTilesByRegionAsync(
|
||||
It.IsAny<double>(), It.IsAny<double>(), It.IsAny<double>(), It.IsAny<int>()))
|
||||
.ReturnsAsync(stale);
|
||||
.ReturnsAsync(priorYearCached);
|
||||
|
||||
IEnumerable<ExistingTileInfo>? capturedExisting = null;
|
||||
downloader
|
||||
@@ -161,10 +163,7 @@ public class TileServiceTests
|
||||
It.IsAny<CancellationToken>()))
|
||||
.Callback<GeoPoint, double, int, IEnumerable<ExistingTileInfo>, CancellationToken>(
|
||||
(_, _, _, e, _) => capturedExisting = e.ToList())
|
||||
.ReturnsAsync(new List<DownloadedTileInfoV2>
|
||||
{
|
||||
MakeDownloaded(123, 456, TestCoordinates.DefaultZoom, TestCoordinates.TileLat, TestCoordinates.TileLon),
|
||||
});
|
||||
.ReturnsAsync(new List<DownloadedTileInfoV2>());
|
||||
|
||||
var service = BuildService(downloader, tileRepo);
|
||||
|
||||
@@ -173,10 +172,38 @@ public class TileServiceTests
|
||||
TestCoordinates.TileLat, TestCoordinates.TileLon, 200, TestCoordinates.DefaultZoom);
|
||||
|
||||
// Assert
|
||||
capturedExisting.Should().BeEmpty(
|
||||
"stale-version tiles must not be passed to the downloader as 'already have it'");
|
||||
result.Should().HaveCount(1, "only the freshly-downloaded tile is in the result");
|
||||
tileRepo.Verify(r => r.InsertAsync(It.IsAny<TileEntity>()), Times.Once);
|
||||
capturedExisting.Should().NotBeNull();
|
||||
capturedExisting!.Should().ContainSingle(
|
||||
"after AZ-357 the version column no longer gates the cache; the prior-year row is reusable");
|
||||
result.Should().HaveCount(1);
|
||||
result[0].Id.Should().Be(priorYearCached[0].Id);
|
||||
tileRepo.Verify(r => r.InsertAsync(It.IsAny<TileEntity>()), Times.Never,
|
||||
"cached tile from prior year must not be re-inserted");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildTileEntity_DoesNotPopulateVersion_AZ357()
|
||||
{
|
||||
// Arrange
|
||||
var downloader = new Mock<ISatelliteDownloader>();
|
||||
var tileRepo = new Mock<ITileRepository>();
|
||||
TileEntity? captured = null;
|
||||
tileRepo
|
||||
.Setup(r => r.InsertAsync(It.IsAny<TileEntity>()))
|
||||
.Callback<TileEntity>(e => captured = e)
|
||||
.ReturnsAsync(Guid.NewGuid());
|
||||
downloader
|
||||
.Setup(d => d.DownloadSingleTileAsync(It.IsAny<double>(), It.IsAny<double>(), It.IsAny<int>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new DownloadedTileInfoV2(1, 2, 18, 47.46, 37.65, "tiles/18/1/2.jpg", 100.0));
|
||||
|
||||
var service = BuildService(downloader, tileRepo);
|
||||
|
||||
// Act
|
||||
_ = service.DownloadAndStoreSingleTileAsync(47.46, 37.65, 18).GetAwaiter().GetResult();
|
||||
|
||||
// Assert
|
||||
captured.Should().NotBeNull();
|
||||
captured!.Version.Should().BeNull("AZ-357: new code never writes the deprecated year-based version");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user