mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-06-22 03:21:15 +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:
@@ -0,0 +1,77 @@
|
||||
# Refactor: drop tile Version concept; latest row wins; new migration
|
||||
|
||||
**Task**: AZ-357_refactor_drop_tile_version
|
||||
**Name**: Eliminate year-based tile versioning; cache by (lat, lon, zoom, tile_size)
|
||||
**Description**: Remove the `Version` filter from tile-cache logic, change repository upsert semantics to (lat, lon, zoom, tile_size), and ship a migration that drops the 5-column unique constraint, replaces it with a 4-column one, and dedupes pre-existing duplicates.
|
||||
**Complexity**: 5 points
|
||||
**Dependencies**: None (C20 follows from this change)
|
||||
**Component**: Services.TileDownloader + DataAccess
|
||||
**Tracker**: AZ-357
|
||||
**Epic**: AZ-350
|
||||
|
||||
## Problem
|
||||
|
||||
`SatelliteProvider.Services.TileDownloader/TileService.cs` uses `var currentVersion = DateTime.UtcNow.Year` and filters cached tiles via `existingTiles.Where(t => t.Version == currentVersion)`. On every Jan 1 UTC the year flips and the cache effectively expires (LF-1 in `discovery/logical_flow_analysis.md`). The `version` concept is unused as a real cache lever.
|
||||
|
||||
## Outcome
|
||||
|
||||
- Tile cache survives year boundaries (cached tiles from prior years remain valid).
|
||||
- Repository lookups return the most recently updated row for each `(lat, lon, zoom, tile_size_meters)` cell.
|
||||
- New rows are upserted on conflict by the 4-column key.
|
||||
- DB unique constraint matches the new key; pre-existing duplicates are deduped (keeping highest `updated_at`).
|
||||
- The `version` column itself is preserved (per `coderule.mdc` — no rename/drop without explicit confirmation).
|
||||
- 37 unit + 5 smoke tests stay green; `migration_test_step1.md` (or equivalent) covers the migration.
|
||||
|
||||
## Scope
|
||||
|
||||
### Included
|
||||
- Delete `t.Version == currentVersion` filter in `TileService.DownloadAndStoreTilesAsync`.
|
||||
- Stop writing `currentVersion` into `TileEntity.Version` in `BuildTileEntity`.
|
||||
- Update `TileRepository.GetTilesByRegionAsync` and `GetByTileCoordinatesAsync` to deduplicate on the 4-column key, returning the latest row per cell.
|
||||
- Change `TileRepository.InsertAsync`'s `ON CONFLICT` clause to the 4-column key.
|
||||
- Add a new migration SQL file (next number) that drops the 5-column unique constraint, dedupes pre-existing rows, then adds a new 4-column unique constraint.
|
||||
- Add a unit/integration test that fakes `UtcNow` across a year boundary and verifies cache hit.
|
||||
|
||||
### Excluded
|
||||
- Dropping the `version` column from `tiles` (deferred; per `coderule.mdc` no column drops without explicit confirmation).
|
||||
- Touching `MapsVersion` (separate task: AZ-373 / C20).
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
**AC-1: Cache survives year boundary**
|
||||
Given a row in `tiles` with `version = 2025`
|
||||
When the system queries the same `(lat, lon, zoom, tile_size_meters)` cell with the clock advanced into 2026
|
||||
Then the cached row is returned (not re-downloaded).
|
||||
|
||||
**AC-2: Migration runs cleanly on populated tile data**
|
||||
Given a `tiles` table containing duplicates by the new 4-column key (across different `version` values)
|
||||
When the new migration runs
|
||||
Then duplicates are collapsed to the row with the highest `updated_at`, and the new 4-column unique constraint exists.
|
||||
|
||||
**AC-3: Upsert behaves on the new key**
|
||||
Given two `InsertAsync` calls with identical `(lat, lon, zoom, tile_size_meters)` and different `version` values
|
||||
When both run
|
||||
Then the table contains exactly one row for that cell (the second call updated the first).
|
||||
|
||||
**AC-4: Tests stay green**
|
||||
Given the post-refactor build
|
||||
When `scripts/run-tests.sh --smoke` runs
|
||||
Then all 37 unit + 5 smoke scenarios pass.
|
||||
|
||||
## Constraints
|
||||
|
||||
- DB column `version` is preserved (left nullable; new code does not write to it).
|
||||
- HTTP shape of `DownloadTileResponse` preserved (`Version` field still present in the JSON).
|
||||
- No rename of any column.
|
||||
|
||||
## Risks & Mitigation
|
||||
|
||||
**Risk 1: production tile table contains duplicates that resolve ambiguously**
|
||||
- *Risk*: if multiple rows share the new 4-column key with the same `updated_at`, the dedupe could pick the wrong row.
|
||||
- *Mitigation*: tie-break on `id` (largest wins) within the dedupe SQL.
|
||||
|
||||
**Risk 2: rollback is hard once the migration runs**
|
||||
- *Risk*: dropped duplicates are gone.
|
||||
- *Mitigation*: migration SQL must be reviewable and tested against a populated copy before prod rollout. Capture pre-migration row counts in the migration log.
|
||||
|
||||
Full change entry: `_docs/04_refactoring/03-code-quality-refactoring/list-of-changes.md` (C06).
|
||||
Reference in New Issue
Block a user