mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-06-22 06:31:14 +00:00
[AZ-351][AZ-352][AZ-363] Refactor 03 batch 1: critical defensive fixes
AZ-351: Resolve ILogger<DatabaseMigrator> directly from DI in Program.cs instead of casting ILogger<Program> (which always returned null). Migrator now logs through Serilog at startup. AZ-352: Drop empty catch in RouteProcessingService.ExtractTileCoordinatesFromFilename. Convert the method from private static to internal instance so it can use the existing _logger (per coderule: side-effecting code must not be static). Add typed null-guard via ArgumentNullException.ThrowIfNull so unexpected exceptions propagate. Adds InternalsVisibleTo on the RouteManagement csproj for SatelliteProvider.Tests, plus 4 unit tests in RouteProcessingServiceTests.cs covering AC-1 (valid / malformed / non-numeric) and AC-2 (null path propagation). AZ-363: Delete _totalEnqueued / _totalDequeued fields and the two non-atomic ++ writes in RegionRequestQueue. Fields were write-only dead code and a thread-safety hazard. Tests: 44/44 unit + 5/5 smoke (scripts/run-tests.sh --smoke). Code review verdict: PASS, 0 findings, 0 auto-fix attempts. Batch report: _docs/03_implementation/batch_07_report.md. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,55 +0,0 @@
|
||||
# Refactor: fix null ILogger passed to DatabaseMigrator at startup
|
||||
|
||||
**Task**: AZ-351_refactor_fix_null_logger_migrator
|
||||
**Name**: Fix null logger to DatabaseMigrator
|
||||
**Description**: Resolve `ILogger<DatabaseMigrator>` directly from DI instead of casting `ILogger<Program>`, which always returns null.
|
||||
**Complexity**: 2 points
|
||||
**Dependencies**: None
|
||||
**Component**: Api
|
||||
**Tracker**: AZ-351
|
||||
**Epic**: AZ-350
|
||||
|
||||
## Problem
|
||||
|
||||
`SatelliteProvider.Api/Program.cs:82-83` does `app.Services.GetRequiredService<ILogger<Program>>() as ILogger<DatabaseMigrator>`. The cast between unrelated generic instantiations always returns null. `DatabaseMigrator` runs with a null logger, so any migration failure path that depends on logging is silent.
|
||||
|
||||
## Outcome
|
||||
|
||||
- `DatabaseMigrator` receives a real `ILogger<DatabaseMigrator>` instance from DI.
|
||||
- Migration log entries appear in startup output and persist to log sinks.
|
||||
- 37 unit + 5 smoke tests stay green.
|
||||
|
||||
## Scope
|
||||
|
||||
### Included
|
||||
- Replace the `as` cast with `app.Services.GetRequiredService<ILogger<DatabaseMigrator>>()`.
|
||||
- Confirm `DatabaseMigrator`'s constructor logs at least one entry on success and one on failure (already present, just verify).
|
||||
|
||||
### Excluded
|
||||
- Changing `DatabaseMigrator`'s logging strategy or log levels.
|
||||
- Adding migration-related metrics or observability beyond what already exists.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
**AC-1: Migrator receives a real logger**
|
||||
Given the post-refactor `Program.cs`
|
||||
When the host starts
|
||||
Then `DatabaseMigrator` is constructed with a non-null `ILogger<DatabaseMigrator>` (verifiable by a unit test or by inspecting startup logs).
|
||||
|
||||
**AC-2: Tests stay green**
|
||||
Given the post-refactor build
|
||||
When `scripts/run-tests.sh --smoke` runs
|
||||
Then all 37 unit + 5 smoke scenarios pass.
|
||||
|
||||
## Constraints
|
||||
|
||||
- No DI graph reorder.
|
||||
- No public API change.
|
||||
|
||||
## Risks & Mitigation
|
||||
|
||||
**Risk 1: hidden assumption that logger may be null**
|
||||
- *Risk*: `DatabaseMigrator` may have a defensive null-check that masked the bug.
|
||||
- *Mitigation*: keep the null-check during this change; remove it in a follow-up only after we confirm via tests that the live logger is always provided.
|
||||
|
||||
Full change entry: `_docs/04_refactoring/03-code-quality-refactoring/list-of-changes.md` (C01).
|
||||
@@ -1,60 +0,0 @@
|
||||
# Refactor: replace empty catch in ExtractTileCoordinatesFromFilename
|
||||
|
||||
**Task**: AZ-352_refactor_replace_empty_catch_extract_tile_coords
|
||||
**Name**: Remove silent empty catch in tile-coord parser
|
||||
**Description**: Replace the empty `catch { }` in `RouteProcessingService.ExtractTileCoordinatesFromFilename` with a typed catch + warning log.
|
||||
**Complexity**: 2 points
|
||||
**Dependencies**: None
|
||||
**Component**: Services.RouteManagement
|
||||
**Tracker**: AZ-352
|
||||
**Epic**: AZ-350
|
||||
|
||||
## Problem
|
||||
|
||||
`SatelliteProvider.Services.RouteManagement/RouteProcessingService.cs:610-630` swallows every parse/IO exception with `catch { }` and returns `(-1, -1)`. Callers treat this as "tile not stitchable" — the tile silently disappears from the route map. Direct violation of `coderule.mdc` ("Never suppress errors silently").
|
||||
|
||||
## Outcome
|
||||
|
||||
- Malformed filenames produce a visible warning log entry.
|
||||
- Unexpected exception types propagate up the call stack instead of being swallowed.
|
||||
- 37 unit + 5 smoke tests stay green.
|
||||
|
||||
## Scope
|
||||
|
||||
### Included
|
||||
- Replace `catch { }` with `catch (FormatException) { ... } catch (ArgumentException) { ... }` plus warning log via the existing `_logger`.
|
||||
- Let any other exception propagate.
|
||||
- Add a unit test that feeds a malformed filename and asserts on the warning log entry.
|
||||
|
||||
### Excluded
|
||||
- Changing the filename format or the writer side (`StorageConfig.GetTileFilePath`).
|
||||
- Changing the `(-1, -1)` sentinel — that lives until C13 reorganizes the parser/writer pairing.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
**AC-1: Malformed filename logs a warning**
|
||||
Given a file that does not match the `tile_{ts}_{x}_{y}.jpg` pattern
|
||||
When `ExtractTileCoordinatesFromFilename` is called on it
|
||||
Then the function returns `(-1, -1)` AND a warning log entry is emitted naming the file.
|
||||
|
||||
**AC-2: Unexpected exception propagates**
|
||||
Given a hypothetical unrelated exception (e.g., `IOException`) raised inside the parser
|
||||
When `ExtractTileCoordinatesFromFilename` is called
|
||||
Then the exception is not swallowed and propagates to the caller.
|
||||
|
||||
**AC-3: Tests stay green**
|
||||
Given the post-refactor build
|
||||
When `scripts/run-tests.sh --smoke` runs
|
||||
Then all 37 unit + 5 smoke scenarios pass.
|
||||
|
||||
## Constraints
|
||||
|
||||
- Behavior for valid filenames must be byte-identical.
|
||||
|
||||
## Risks & Mitigation
|
||||
|
||||
**Risk 1: existing callers may rely on the swallow-all behavior**
|
||||
- *Risk*: another path in `RouteProcessingService` may pass arbitrary file lists where IO errors are expected.
|
||||
- *Mitigation*: grep all callers; if any expects swallow-all, add explicit handling at that call site.
|
||||
|
||||
Full change entry: `_docs/04_refactoring/03-code-quality-refactoring/list-of-changes.md` (C02).
|
||||
@@ -1,52 +0,0 @@
|
||||
# Refactor: delete write-only counters in RegionRequestQueue
|
||||
|
||||
**Task**: AZ-363_refactor_delete_writeonly_counters
|
||||
**Name**: Remove non-atomic write-only counters
|
||||
**Description**: Delete `_totalEnqueued` and `_totalDequeued` fields plus the two `++` lines in `RegionRequestQueue`.
|
||||
**Complexity**: 1 point
|
||||
**Dependencies**: None
|
||||
**Component**: Services.RegionProcessing
|
||||
**Tracker**: AZ-363
|
||||
**Epic**: AZ-350
|
||||
|
||||
## Problem
|
||||
|
||||
`SatelliteProvider.Services.RegionProcessing/RegionRequestQueue.cs:12-13, 28, 38` uses `_totalEnqueued++` and `_totalDequeued++` on `int` fields. The increments are not atomic under concurrent producers/consumers, and the fields are never read anywhere in the codebase. Telemetry-via-`++` is both a thread-safety bug and dead code.
|
||||
|
||||
## Outcome
|
||||
|
||||
- The two fields and the two `++` lines are removed.
|
||||
- 37 unit + 5 smoke tests stay green.
|
||||
|
||||
## Scope
|
||||
|
||||
### Included
|
||||
- Delete the field declarations.
|
||||
- Delete the `++` lines from `Enqueue` / `Dequeue`.
|
||||
|
||||
### Excluded
|
||||
- Adding proper `Meter`/`Counter<long>` telemetry (deferred to a future observability ticket).
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
**AC-1: Fields and increments removed**
|
||||
Given the post-refactor `RegionRequestQueue.cs`
|
||||
When grepped for `_totalEnqueued` or `_totalDequeued`
|
||||
Then zero matches.
|
||||
|
||||
**AC-2: Tests stay green**
|
||||
Given the post-refactor build
|
||||
When `scripts/run-tests.sh --smoke` runs
|
||||
Then all 37 unit + 5 smoke scenarios pass.
|
||||
|
||||
## Constraints
|
||||
|
||||
- No public API change (fields are private).
|
||||
|
||||
## Risks & Mitigation
|
||||
|
||||
**Risk 1: future telemetry need**
|
||||
- *Risk*: someone may want enqueue/dequeue counts later.
|
||||
- *Mitigation*: that's a separate, properly-implemented (atomic, read-out) ticket.
|
||||
|
||||
Full change entry: `_docs/04_refactoring/03-code-quality-refactoring/list-of-changes.md` (C10).
|
||||
Reference in New Issue
Block a user