mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-06-21 10:31:14 +00:00
[AZ-505] Tile inventory endpoint + HTTP/2 + Leaflet covering index
Production code:
- POST /api/satellite/tiles/inventory (XOR body, 5000-cap,
most-recent-per-location_hash select, present/absent shaping).
- Kestrel HttpProtocols.Http1AndHttp2 on every listener (AC-5).
- Migration 015 creates tiles_leaflet_path covering index over
(location_hash, captured_at DESC, updated_at DESC, id DESC)
INCLUDE (file_path, source); drops superseded idx_tiles_location_hash.
- TileRepository.GetByTileCoordinatesAsync rewired to filter by
location_hash (Index Only Scan via tiles_leaflet_path).
- TileRepository.GetTilesByLocationHashesAsync added with Npgsql-
direct ANY($1::uuid[]) binding (Dapper IEnumerable expansion is
incompatible with the array form).
- Uuidv5.LocationHashForTile centralises the UUIDv5(TileNamespace,
"{z}/{x}/{y}") formula — single source of truth for the cross-repo
invariant (gps-denied-onboard parity).
Contracts:
- New: contracts/api/tile-inventory.md v1.0.0.
- Bumped: contracts/data-access/tile-storage.md to v2.0.0 (joint
ownership by AZ-503-foundation + AZ-505: schema + covering index +
GetByTileCoordinatesAsync rewrite).
Tests:
- TileInventoryTests covers AC-1, AC-2 (DB-level), AC-4, AC-6.
- Http2MultiplexingTests covers AC-5 (20 concurrent multiplexed GETs
over h2c via SocketsHttpHandler + AppContext Http2Unencrypted switch).
- LeafletPathIndexOnlyTests covers AC-3 (EXPLAIN (ANALYZE, BUFFERS)
asserts Index Only Scan over tiles_leaflet_path with heap_blocks=0).
Docs:
- architecture.md, system-flows.md, data_model.md, module-layout.md,
glossary.md, modules/api_program.md, modules/dataaccess_tile_repository.md,
components/02_data_access/description.md all updated to reference the
v2.0.0 tile-storage contract + new tile-inventory contract + AC-7.
Reports:
- batch_01_cycle6_report.md, batch_01_cycle6_review.md,
implementation_completeness_cycle6_report.md (PASS),
implementation_report_tile_inventory_cycle6.md.
Task spec moved todo/ -> done/.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
# Batch Report
|
||||
|
||||
**Batch**: 01 (cycle 6)
|
||||
**Tasks**: AZ-505 — Tile inventory endpoint + HTTP/2 + Leaflet covering index
|
||||
**Date**: 2026-05-12
|
||||
|
||||
## Task Results
|
||||
|
||||
| Task | Status | Files Modified | Tests | AC Coverage | Issues |
|
||||
|------|--------|---------------|-------|-------------|--------|
|
||||
| AZ-505_tile_inventory_http2_leaflet_index | Done | 13 source + 9 doc + 1 migration | New: `TileInventoryTests.cs` (6 sub-tests), `Http2MultiplexingTests.cs`, `LeafletPathIndexOnlyTests.cs`. Wired into both smoke + full suites. | 6/6 functional ACs covered; AC-7 doc-gate satisfied | None remaining; one Medium / Maintainability auto-fix landed (consolidate `ComputeLocationHash` → `Uuidv5.LocationHashForTile`). |
|
||||
|
||||
## Changes
|
||||
|
||||
### Production code
|
||||
|
||||
- `SatelliteProvider.Common/DTO/TileInventory.cs` (new) — `TileInventoryRequest` (XOR `Tiles` / `LocationHashes`), `TileCoord`, `TileInventoryResponse`, `TileInventoryEntry`, `TileInventoryLimits.MaxEntriesPerRequest = 5000`.
|
||||
- `SatelliteProvider.Common/Utils/Uuidv5.cs` — added `LocationHashForTile(int z, int x, int y)` static. Single source-of-truth for the cross-repo `UUIDv5(TileNamespace, "{z}/{x}/{y}")` formula consumed by repository, service, and tests.
|
||||
- `SatelliteProvider.DataAccess/Repositories/ITileRepository.cs` — added `GetTilesByLocationHashesAsync(IReadOnlyList<Guid>) → Task<IReadOnlyDictionary<Guid, TileEntity>>`.
|
||||
- `SatelliteProvider.DataAccess/Repositories/TileRepository.cs` — rewrote `GetByTileCoordinatesAsync` to filter by `location_hash` (index-only-scannable against `tiles_leaflet_path`); implemented `GetTilesByLocationHashesAsync` via `NpgsqlCommand` + `NpgsqlDbType.Array | Uuid` parameter binding (Dapper's `IEnumerable` expansion is incompatible with `ANY($1::uuid[])`); removed the AZ-505 first-pass `ComputeLocationHash` helper in favour of `Uuidv5.LocationHashForTile`.
|
||||
- `SatelliteProvider.Services.TileDownloader/TileService.cs` — added `GetInventoryAsync(TileInventoryRequest, CancellationToken)` implementing the contract's ordering / present-absent / Form-A-vs-Form-B shaping rules; consolidated `locationHashName` in `BuildTileEntity` to the same helper.
|
||||
- `SatelliteProvider.Api/Program.cs` — registered `POST /api/satellite/tiles/inventory` with `.RequireAuthorization()`, `.Accepts<TileInventoryRequest>("application/json")`, `.Produces<TileInventoryResponse>(200)`, `.ProducesProblem(400)`, and OpenAPI description referencing the contract. Configured Kestrel `HttpProtocols.Http1AndHttp2` on all listener endpoints.
|
||||
- `SatelliteProvider.DataAccess/Migrations/015_AddTilesLeafletPathIndex.sql` (new) — `CREATE INDEX tiles_leaflet_path (location_hash, captured_at DESC, updated_at DESC, id DESC) INCLUDE (file_path, source)`; `DROP INDEX IF EXISTS idx_tiles_location_hash`. Forward + back-migration documented in the header; lock-window caveat captured per AZ-505 Risk 2.
|
||||
|
||||
### Tests
|
||||
|
||||
- `SatelliteProvider.IntegrationTests/TileInventoryTests.cs` (new) — AC-1 (ordering + present/absent shaping, 25-entry interleaved fixture), AC-2 (DB-level proof that the most-recent-via-location_hash selection rule survives the rewrite), AC-4 (perf budget, full-suite only), AC-6 (4 validation cases).
|
||||
- `SatelliteProvider.IntegrationTests/Http2MultiplexingTests.cs` (new) — AC-5 (20 concurrent GETs over a single H2 connection on h2c).
|
||||
- `SatelliteProvider.IntegrationTests/LeafletPathIndexOnlyTests.cs` (new) — AC-3 (EXPLAIN ANALYZE + Index Only Scan regex + Heap Fetches ≤ 1).
|
||||
- `SatelliteProvider.IntegrationTests/Program.cs` — wired the three new test entry points into both `RunSmokeSuite` and `RunFullSuite`. `Http2MultiplexingTests.RunAll` runs early in `Main` because it sets a process-wide `AppContext` switch.
|
||||
|
||||
### Documentation
|
||||
|
||||
- `_docs/02_document/contracts/api/tile-inventory.md` v1.0.0 (new) — Form A / Form B XOR validation, 5000-entry cap, 7-line invariant table, response field reference, test-case matrix, change log entry.
|
||||
- `_docs/02_document/contracts/data-access/tile-storage.md` v1.0.0 → v2.0.0 (major bump) — captures AZ-503-foundation identity columns + `idx_tiles_unique_identity` integer UPSERT + `tiles_leaflet_path` covering index + `location_hash`-keyed read rule + new `GetTilesByLocationHashesAsync` method. Added Inv-7 / Inv-8 / Inv-9. Change Log entry names both producing tasks (AZ-503-foundation + AZ-505).
|
||||
- `_docs/02_document/architecture.md`, `_docs/02_document/module-layout.md`, `_docs/02_document/glossary.md`, `_docs/02_document/data_model.md`, `_docs/02_document/modules/api_program.md`, `_docs/02_document/modules/dataaccess_tile_repository.md`, `_docs/02_document/components/02_data_access/description.md` — endpoint row, repo method row, query/index table updates, Location Hash entry promotion, migration 015 entry, AZ-505 + v2.0.0 freeze references.
|
||||
|
||||
## AC Test Coverage
|
||||
|
||||
6/6 functional ACs covered (AC-1, AC-2, AC-3, AC-4, AC-5, AC-6). AC-7 (contract artifacts) is a documentation gate verified by file presence + version-string + Change Log entry.
|
||||
|
||||
## Code Review Verdict
|
||||
|
||||
PASS — see `_docs/03_implementation/reviews/batch_01_cycle6_review.md`. One Medium / Maintainability auto-fix landed during review (consolidate `ComputeLocationHash` duplication into `Uuidv5.LocationHashForTile`). No remaining findings.
|
||||
|
||||
## Auto-Fix Attempts
|
||||
|
||||
1 — `ComputeLocationHash` duplication; resolved in a single pass.
|
||||
|
||||
## Stuck Agents
|
||||
|
||||
None.
|
||||
|
||||
## Notes
|
||||
|
||||
- **Cross-repo invariant preserved**: `Uuidv5.TileNamespace = 5b8d0c2e-7f1a-4d3b-9c5e-1f3a8e7d2b6c` unchanged; consumed by `LocationHashForTile`, which the repository / service / tests all now route through. The Python sibling (`gps-denied-onboard/components/c6_tile_cache/_uuid.py:TILE_NAMESPACE`) is not touched by this PBI per AZ-505 Constraints — sibling-repo concern.
|
||||
- **Onboard consumer feature flag**: `gps-denied-onboard` AZ-316 retains `c11.use_bulk_list_endpoint=false` default until this PBI is deployed (per AZ-505 Constraints + Risk 4). Surfaced for cross-cycle visibility; no in-repo work.
|
||||
- **Leftover replay (cycle 3 perf-harness)**: `_docs/_process_leftovers/2026-05-12_perf-cycle3-harness-execution.md` remains open. AZ-505 does NOT touch `scripts/run-performance-tests.sh` (out of scope; the open leftover names DNS pre-warmup + cloud perf rerun as the unblocking steps). No replay attempted this cycle per the leftover's "no immediate replay planned" entry.
|
||||
|
||||
## Next Batch
|
||||
|
||||
All tasks complete. Cycle 6 implementation closes here. Hand off to Step 11 (test-run) for the full integration-test gate via Docker Compose.
|
||||
Reference in New Issue
Block a user