mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-06-22 09:41:14 +00:00
[AZ-312] [AZ-313] [AZ-314] Split Services into per-component csprojs
Phase B of architecture coupling refactor (epic AZ-309). Replaces the monolithic SatelliteProvider.Services with three per-component csprojs to add a compiler-enforced module boundary (resolves F4): - SatelliteProvider.Services.TileDownloader - SatelliteProvider.Services.RegionProcessing - SatelliteProvider.Services.RouteManagement DI registrations relocated into per-component AddTileDownloader / AddRegionProcessing / AddRouteManagement extension methods called from Program.cs. RateLimitException moved to Common/Exceptions/ to keep the three new csprojs as siblings (no Region->TileDownloader ProjectReference). Dockerfiles and consumer csprojs (Api, Tests) rewired to the new project paths. No DI lifetime or hosted-service order changes. Build: 0 warn, 0 err. Unit tests: 40/40. Smoke integration: green. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,82 +0,0 @@
|
||||
# Refactor: split SatelliteProvider.Services into per-component csprojs
|
||||
|
||||
**Task**: AZ-312_refactor_split_services_csprojs
|
||||
**Name**: Split Services into TileDownloader + RegionProcessing + RouteManagement
|
||||
**Description**: Replace the single `SatelliteProvider.Services` csproj with three per-component csprojs to add a compiler-enforced module boundary.
|
||||
**Complexity**: 5 points
|
||||
**Dependencies**: AZ-311
|
||||
**Component**: All Services components
|
||||
**Tracker**: AZ-312
|
||||
**Epic**: AZ-309
|
||||
|
||||
## Problem
|
||||
|
||||
`SatelliteProvider.Services.csproj` packs three logical components (TileDownloader, RegionProcessing, RouteManagement) into one project. No compiler-enforced boundary prevents accidental cross-component coupling. This is architecture baseline finding F4 (Medium).
|
||||
|
||||
## Outcome
|
||||
|
||||
- Three new csprojs exist:
|
||||
- `SatelliteProvider.Services.TileDownloader/SatelliteProvider.Services.TileDownloader.csproj`
|
||||
- `SatelliteProvider.Services.RegionProcessing/SatelliteProvider.Services.RegionProcessing.csproj`
|
||||
- `SatelliteProvider.Services.RouteManagement/SatelliteProvider.Services.RouteManagement.csproj`
|
||||
- Seven source files moved into the matching project.
|
||||
- `SatelliteProvider.Services.csproj` deleted.
|
||||
- Each new csproj `ProjectReference`s only what it needs.
|
||||
- Solution file `SatelliteProvider.sln` updated.
|
||||
|
||||
## Scope
|
||||
|
||||
### Included
|
||||
- File moves:
|
||||
- `TileService.cs`, `GoogleMapsDownloaderV2.cs` → `SatelliteProvider.Services.TileDownloader/`
|
||||
- `RegionService.cs`, `RegionProcessingService.cs`, `RegionRequestQueue.cs` → `SatelliteProvider.Services.RegionProcessing/`
|
||||
- `RouteService.cs`, `RouteProcessingService.cs` → `SatelliteProvider.Services.RouteManagement/`
|
||||
- Namespace changes:
|
||||
- `SatelliteProvider.Services` → `SatelliteProvider.Services.TileDownloader` (in TileService, GoogleMapsDownloaderV2)
|
||||
- `SatelliteProvider.Services` → `SatelliteProvider.Services.RegionProcessing` (in three Region* files)
|
||||
- `SatelliteProvider.Services` → `SatelliteProvider.Services.RouteManagement` (in two Route* files)
|
||||
- Add `ProjectReference` entries in each new csproj as required by its members.
|
||||
- Delete `SatelliteProvider.Services/` directory once empty.
|
||||
- Update `SatelliteProvider.sln` (add new projects, remove old).
|
||||
|
||||
### Excluded
|
||||
- Updating consumers (Tests, IntegrationTests, Api csprojs and their `using` directives) — those go in AZ-313 and AZ-314.
|
||||
- Any logic change inside the moved files.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
**AC-1: Three new csprojs exist with correct contents**
|
||||
Given the post-refactor tree
|
||||
When listing the new csproj directories
|
||||
Then each contains only the files listed in the `Included` section, plus its csproj file.
|
||||
|
||||
**AC-2: Old project deleted**
|
||||
Given the post-refactor tree
|
||||
When searching for `SatelliteProvider.Services.csproj` or `SatelliteProvider.Services/` directory
|
||||
Then neither exists.
|
||||
|
||||
**AC-3: Solution-level build succeeds with the new csprojs unreferenced**
|
||||
Given the new csprojs exist but no consumer has been updated yet
|
||||
When `dotnet build SatelliteProvider.sln` is run
|
||||
Then build fails ONLY for the unreferenced consumers (Api, Tests, IntegrationTests). The three new csprojs themselves compile clean.
|
||||
|
||||
**AC-4: No cross-component reference between the three new csprojs**
|
||||
Given the three new csproj files
|
||||
When inspecting their `ProjectReference` entries
|
||||
Then none of TileDownloader, RegionProcessing, or RouteManagement references another of the three. They all reference only `SatelliteProvider.Common` and (where needed) `SatelliteProvider.DataAccess`.
|
||||
|
||||
## Constraints
|
||||
|
||||
- No code logic changes inside the moved files.
|
||||
- Namespaces follow `SatelliteProvider.Services.<Component>` pattern.
|
||||
- Existing public API of `ITileService`, `IRegionService`, `IRouteService`, `IRegionRequestQueue` (in Common) unchanged.
|
||||
|
||||
## Risks & Mitigation
|
||||
|
||||
**Risk 1: Hidden cross-component coupling**
|
||||
- *Risk*: A move reveals that a Region* class actually `using SatelliteProvider.Services` for a TileDownloader-only type.
|
||||
- *Mitigation*: If found, the cleanest fix is to lift the shared type into `SatelliteProvider.Common` (extend in this task) or add a `ProjectReference` (last resort, document why). Stop and ask if this surfaces.
|
||||
|
||||
**Risk 2: SatelliteProvider.sln drift**
|
||||
- *Risk*: Forgetting to update the solution file leaves the new csprojs invisible to Docker/CI.
|
||||
- *Mitigation*: Use `dotnet sln add` and `dotnet sln remove` exactly once for each project; assert via `dotnet sln list`.
|
||||
@@ -1,64 +0,0 @@
|
||||
# Refactor: update consumers (Api, Tests, IntegrationTests) for split
|
||||
|
||||
**Task**: AZ-313_refactor_update_consumers
|
||||
**Name**: Update consumer csprojs and using directives after Services split
|
||||
**Description**: Re-wire `SatelliteProvider.Api`, `SatelliteProvider.Tests`, and `SatelliteProvider.IntegrationTests` to reference the three new per-component csprojs.
|
||||
**Complexity**: 3 points
|
||||
**Dependencies**: AZ-312
|
||||
**Component**: API + Tests
|
||||
**Tracker**: AZ-313
|
||||
**Epic**: AZ-309
|
||||
|
||||
## Problem
|
||||
|
||||
After AZ-312 splits `SatelliteProvider.Services` into three csprojs, every consumer of the old project breaks (compile errors). This task fixes the consumers without changing any test logic or DI behavior.
|
||||
|
||||
## Outcome
|
||||
|
||||
- `SatelliteProvider.Api.csproj` references all three new Services projects.
|
||||
- `SatelliteProvider.Tests.csproj` references whichever Services projects its current tests depend on (typically all three; verify per file).
|
||||
- `SatelliteProvider.IntegrationTests.csproj` references whichever Services projects its current tests depend on.
|
||||
- All `using SatelliteProvider.Services;` directives across consumers replaced with the correct `using SatelliteProvider.Services.<Component>;` directive.
|
||||
- `dotnet build SatelliteProvider.sln` succeeds.
|
||||
- All previously-green unit tests remain green.
|
||||
|
||||
## Scope
|
||||
|
||||
### Included
|
||||
- Edit `.csproj` files of Api, Tests, IntegrationTests: add new `ProjectReference` entries, remove the old `SatelliteProvider.Services` reference.
|
||||
- Update all `using` directives in `.cs` files under those three projects.
|
||||
- Run `dotnet build` to confirm zero errors.
|
||||
- Run unit test suite (`SatelliteProvider.Tests`) to confirm zero regressions vs. Step 6 baseline.
|
||||
|
||||
### Excluded
|
||||
- DI container registration changes — those happen in AZ-314.
|
||||
- Re-running integration suite — that happens in AZ-315.
|
||||
- Changing any test assertion or test data.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
**AC-1: Solution builds clean**
|
||||
Given the post-refactor consumer csprojs
|
||||
When `dotnet build SatelliteProvider.sln` is run
|
||||
Then build succeeds with zero errors and zero new warnings vs. the pre-refactor baseline.
|
||||
|
||||
**AC-2: Unit tests green**
|
||||
Given the post-refactor consumer csprojs
|
||||
When `dotnet test SatelliteProvider.Tests` is run
|
||||
Then all 35 (or current baseline count) unit tests pass.
|
||||
|
||||
**AC-3: No stale `using SatelliteProvider.Services;`**
|
||||
Given the post-refactor source tree
|
||||
When grepping for `using SatelliteProvider.Services;` (without a `.<Component>` suffix)
|
||||
Then zero matches outside intentional comments.
|
||||
|
||||
## Constraints
|
||||
|
||||
- No DI registration changes in this task.
|
||||
- No test logic, fixture, or assertion changes.
|
||||
|
||||
## Risks & Mitigation
|
||||
|
||||
**Risk 1: Shadowed types if a single file references types from two of the new components**
|
||||
- *Risk*: A test that exercises both `RegionService` and `RouteService` needs both `using` statements.
|
||||
- *Mitigation*: Add both. Compiler will tell us which.
|
||||
@@ -1,69 +0,0 @@
|
||||
# Refactor: split DI registration to per-component extension methods
|
||||
|
||||
**Task**: AZ-314_refactor_di_registration_split
|
||||
**Name**: Per-component AddXxxServices() extension methods in Program.cs
|
||||
**Description**: Replace ad-hoc DI registrations in `Program.cs` with three extension methods, one per new csproj, matching the module boundary.
|
||||
**Complexity**: 2 points
|
||||
**Dependencies**: AZ-313
|
||||
**Component**: API
|
||||
**Tracker**: AZ-314
|
||||
**Epic**: AZ-309
|
||||
|
||||
## Problem
|
||||
|
||||
`Program.cs` currently registers all services inline and ungrouped. After the split, the three Services csprojs have logically distinct registrations; co-locating each set with its csproj clarifies ownership and makes adding a new component easier.
|
||||
|
||||
## Outcome
|
||||
|
||||
- New extension methods in each new Services csproj:
|
||||
- `SatelliteProvider.Services.TileDownloader.TileDownloaderServiceCollectionExtensions.AddTileDownloader(this IServiceCollection)`
|
||||
- `SatelliteProvider.Services.RegionProcessing.RegionProcessingServiceCollectionExtensions.AddRegionProcessing(this IServiceCollection)`
|
||||
- `SatelliteProvider.Services.RouteManagement.RouteManagementServiceCollectionExtensions.AddRouteManagement(this IServiceCollection)`
|
||||
- Each method registers exactly the services its csproj owns (concrete types + `IHostedService` registrations).
|
||||
- `Program.cs` calls the three methods and removes the duplicated lines.
|
||||
- DI container behavior is byte-equivalent (same lifetimes, same concrete types, same hosted services).
|
||||
|
||||
## Scope
|
||||
|
||||
### Included
|
||||
- Three new `*ServiceCollectionExtensions.cs` files (one per csproj).
|
||||
- Edit `Program.cs` to call them.
|
||||
- Verify via integration smoke run that DI resolves end-to-end.
|
||||
|
||||
### Excluded
|
||||
- Changing service lifetimes or replacing concrete types.
|
||||
- Adding `IOptions<>` bindings that aren't already there.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
**AC-1: Each extension method exists and registers the expected services**
|
||||
Given the post-refactor source
|
||||
When inspecting each `*ServiceCollectionExtensions.cs`
|
||||
Then it registers all services owned by its csproj and nothing else.
|
||||
|
||||
**AC-2: Program.cs uses extension methods**
|
||||
Given `Program.cs` after refactor
|
||||
When inspecting service registration block
|
||||
Then `services.AddTileDownloader();`, `services.AddRegionProcessing();`, `services.AddRouteManagement();` appear and the previously-inlined registrations are gone.
|
||||
|
||||
**AC-3: DI graph unchanged**
|
||||
Given the running app
|
||||
When the smoke integration test profile is executed
|
||||
Then it passes end-to-end (proving every required service still resolves).
|
||||
|
||||
**AC-4: Consumers updated**
|
||||
Given the post-refactor source
|
||||
When grepping consumers
|
||||
Then all references to old service-registration code are removed.
|
||||
|
||||
## Constraints
|
||||
|
||||
- No service lifetime changes (Singleton stays Singleton, Scoped stays Scoped).
|
||||
- Hosted services stay hosted services.
|
||||
- DI registration order preserved where ordering matters.
|
||||
|
||||
## Risks & Mitigation
|
||||
|
||||
**Risk 1: Hosted-service registration order regression**
|
||||
- *Risk*: `IHostedService` execution order is registration-order; an accidental reorder could change startup behavior.
|
||||
- *Mitigation*: Inspect Program.cs Git diff carefully; keep the same call-site order in the three extension methods as in the original file.
|
||||
Reference in New Issue
Block a user