mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-06-21 08:41:13 +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:
@@ -8,7 +8,9 @@ WORKDIR /src
|
|||||||
COPY ["SatelliteProvider.Api/SatelliteProvider.Api.csproj", "SatelliteProvider.Api/"]
|
COPY ["SatelliteProvider.Api/SatelliteProvider.Api.csproj", "SatelliteProvider.Api/"]
|
||||||
COPY ["SatelliteProvider.Common/SatelliteProvider.Common.csproj", "SatelliteProvider.Common/"]
|
COPY ["SatelliteProvider.Common/SatelliteProvider.Common.csproj", "SatelliteProvider.Common/"]
|
||||||
COPY ["SatelliteProvider.DataAccess/SatelliteProvider.DataAccess.csproj", "SatelliteProvider.DataAccess/"]
|
COPY ["SatelliteProvider.DataAccess/SatelliteProvider.DataAccess.csproj", "SatelliteProvider.DataAccess/"]
|
||||||
COPY ["SatelliteProvider.Services/SatelliteProvider.Services.csproj", "SatelliteProvider.Services/"]
|
COPY ["SatelliteProvider.Services.TileDownloader/SatelliteProvider.Services.TileDownloader.csproj", "SatelliteProvider.Services.TileDownloader/"]
|
||||||
|
COPY ["SatelliteProvider.Services.RegionProcessing/SatelliteProvider.Services.RegionProcessing.csproj", "SatelliteProvider.Services.RegionProcessing/"]
|
||||||
|
COPY ["SatelliteProvider.Services.RouteManagement/SatelliteProvider.Services.RouteManagement.csproj", "SatelliteProvider.Services.RouteManagement/"]
|
||||||
RUN dotnet restore "SatelliteProvider.Api/SatelliteProvider.Api.csproj"
|
RUN dotnet restore "SatelliteProvider.Api/SatelliteProvider.Api.csproj"
|
||||||
COPY . .
|
COPY . .
|
||||||
WORKDIR "/src/SatelliteProvider.Api"
|
WORKDIR "/src/SatelliteProvider.Api"
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ using SatelliteProvider.DataAccess.Repositories;
|
|||||||
using SatelliteProvider.Common.Configs;
|
using SatelliteProvider.Common.Configs;
|
||||||
using SatelliteProvider.Common.DTO;
|
using SatelliteProvider.Common.DTO;
|
||||||
using SatelliteProvider.Common.Interfaces;
|
using SatelliteProvider.Common.Interfaces;
|
||||||
using SatelliteProvider.Services;
|
using SatelliteProvider.Services.RegionProcessing;
|
||||||
|
using SatelliteProvider.Services.RouteManagement;
|
||||||
|
using SatelliteProvider.Services.TileDownloader;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
@@ -27,9 +29,10 @@ builder.Services.AddSingleton<IRegionRepository>(sp => new RegionRepository(conn
|
|||||||
builder.Services.AddSingleton<IRouteRepository>(sp => new RouteRepository(connectionString, sp.GetRequiredService<ILogger<RouteRepository>>()));
|
builder.Services.AddSingleton<IRouteRepository>(sp => new RouteRepository(connectionString, sp.GetRequiredService<ILogger<RouteRepository>>()));
|
||||||
|
|
||||||
builder.Services.AddHttpClient();
|
builder.Services.AddHttpClient();
|
||||||
builder.Services.AddMemoryCache();
|
|
||||||
builder.Services.AddSingleton<ISatelliteDownloader, GoogleMapsDownloaderV2>();
|
builder.Services.AddTileDownloader();
|
||||||
builder.Services.AddSingleton<ITileService, TileService>();
|
builder.Services.AddRegionProcessing();
|
||||||
|
builder.Services.AddRouteManagement();
|
||||||
|
|
||||||
var allowedOrigins = builder.Configuration.GetSection("CorsConfig:AllowedOrigins").Get<string[]>() ?? Array.Empty<string>();
|
var allowedOrigins = builder.Configuration.GetSection("CorsConfig:AllowedOrigins").Get<string[]>() ?? Array.Empty<string>();
|
||||||
builder.Services.AddCors(options =>
|
builder.Services.AddCors(options =>
|
||||||
@@ -43,17 +46,6 @@ builder.Services.AddCors(options =>
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
var processingConfig = builder.Configuration.GetSection("ProcessingConfig").Get<ProcessingConfig>() ?? new ProcessingConfig();
|
|
||||||
builder.Services.AddSingleton<IRegionRequestQueue>(sp =>
|
|
||||||
{
|
|
||||||
var logger = sp.GetRequiredService<ILogger<RegionRequestQueue>>();
|
|
||||||
return new RegionRequestQueue(processingConfig.QueueCapacity, logger);
|
|
||||||
});
|
|
||||||
builder.Services.AddSingleton<IRegionService, RegionService>();
|
|
||||||
builder.Services.AddHostedService<RegionProcessingService>();
|
|
||||||
builder.Services.AddSingleton<IRouteService, RouteService>();
|
|
||||||
builder.Services.AddHostedService<RouteProcessingService>();
|
|
||||||
|
|
||||||
builder.Services.ConfigureHttpJsonOptions(options =>
|
builder.Services.ConfigureHttpJsonOptions(options =>
|
||||||
{
|
{
|
||||||
options.SerializerOptions.PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase;
|
options.SerializerOptions.PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase;
|
||||||
|
|||||||
@@ -18,7 +18,9 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\SatelliteProvider.Common\SatelliteProvider.Common.csproj" />
|
<ProjectReference Include="..\SatelliteProvider.Common\SatelliteProvider.Common.csproj" />
|
||||||
<ProjectReference Include="..\SatelliteProvider.DataAccess\SatelliteProvider.DataAccess.csproj" />
|
<ProjectReference Include="..\SatelliteProvider.DataAccess\SatelliteProvider.DataAccess.csproj" />
|
||||||
<ProjectReference Include="..\SatelliteProvider.Services\SatelliteProvider.Services.csproj" />
|
<ProjectReference Include="..\SatelliteProvider.Services.TileDownloader\SatelliteProvider.Services.TileDownloader.csproj" />
|
||||||
|
<ProjectReference Include="..\SatelliteProvider.Services.RegionProcessing\SatelliteProvider.Services.RegionProcessing.csproj" />
|
||||||
|
<ProjectReference Include="..\SatelliteProvider.Services.RouteManagement\SatelliteProvider.Services.RouteManagement.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace SatelliteProvider.Common.Exceptions;
|
||||||
|
|
||||||
|
public class RateLimitException : Exception
|
||||||
|
{
|
||||||
|
public RateLimitException(string message) : base(message) { }
|
||||||
|
public RateLimitException(string message, Exception innerException) : base(message, innerException) { }
|
||||||
|
}
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
COPY ["SatelliteProvider.IntegrationTests/SatelliteProvider.IntegrationTests.csproj", "SatelliteProvider.IntegrationTests/"]
|
COPY ["SatelliteProvider.IntegrationTests/SatelliteProvider.IntegrationTests.csproj", "SatelliteProvider.IntegrationTests/"]
|
||||||
COPY ["SatelliteProvider.Common/SatelliteProvider.Common.csproj", "SatelliteProvider.Common/"]
|
|
||||||
COPY ["SatelliteProvider.DataAccess/SatelliteProvider.DataAccess.csproj", "SatelliteProvider.DataAccess/"]
|
|
||||||
COPY ["SatelliteProvider.Services/SatelliteProvider.Services.csproj", "SatelliteProvider.Services/"]
|
|
||||||
RUN dotnet restore "SatelliteProvider.IntegrationTests/SatelliteProvider.IntegrationTests.csproj"
|
RUN dotnet restore "SatelliteProvider.IntegrationTests/SatelliteProvider.IntegrationTests.csproj"
|
||||||
COPY . .
|
COPY . .
|
||||||
WORKDIR "/src/SatelliteProvider.IntegrationTests"
|
WORKDIR "/src/SatelliteProvider.IntegrationTests"
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ using Microsoft.Extensions.Options;
|
|||||||
using SatelliteProvider.Common.Configs;
|
using SatelliteProvider.Common.Configs;
|
||||||
using SatelliteProvider.Common.Interfaces;
|
using SatelliteProvider.Common.Interfaces;
|
||||||
|
|
||||||
namespace SatelliteProvider.Services;
|
namespace SatelliteProvider.Services.RegionProcessing;
|
||||||
|
|
||||||
public class RegionProcessingService : BackgroundService
|
public class RegionProcessingService : BackgroundService
|
||||||
{
|
{
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using SatelliteProvider.Common.Configs;
|
||||||
|
using SatelliteProvider.Common.Interfaces;
|
||||||
|
|
||||||
|
namespace SatelliteProvider.Services.RegionProcessing;
|
||||||
|
|
||||||
|
public static class RegionProcessingServiceCollectionExtensions
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddRegionProcessing(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IRegionRequestQueue>(sp =>
|
||||||
|
{
|
||||||
|
var processingConfig = sp.GetRequiredService<IOptions<ProcessingConfig>>().Value;
|
||||||
|
var logger = sp.GetRequiredService<ILogger<RegionRequestQueue>>();
|
||||||
|
return new RegionRequestQueue(processingConfig.QueueCapacity, logger);
|
||||||
|
});
|
||||||
|
services.AddSingleton<IRegionService, RegionService>();
|
||||||
|
services.AddHostedService<RegionProcessingService>();
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -3,7 +3,7 @@ using Microsoft.Extensions.Logging;
|
|||||||
using SatelliteProvider.Common.DTO;
|
using SatelliteProvider.Common.DTO;
|
||||||
using SatelliteProvider.Common.Interfaces;
|
using SatelliteProvider.Common.Interfaces;
|
||||||
|
|
||||||
namespace SatelliteProvider.Services;
|
namespace SatelliteProvider.Services.RegionProcessing;
|
||||||
|
|
||||||
public class RegionRequestQueue : IRegionRequestQueue
|
public class RegionRequestQueue : IRegionRequestQueue
|
||||||
{
|
{
|
||||||
+2
-1
@@ -2,6 +2,7 @@ using Microsoft.Extensions.Logging;
|
|||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using SatelliteProvider.Common.Configs;
|
using SatelliteProvider.Common.Configs;
|
||||||
using SatelliteProvider.Common.DTO;
|
using SatelliteProvider.Common.DTO;
|
||||||
|
using SatelliteProvider.Common.Exceptions;
|
||||||
using SatelliteProvider.Common.Interfaces;
|
using SatelliteProvider.Common.Interfaces;
|
||||||
using SatelliteProvider.Common.Utils;
|
using SatelliteProvider.Common.Utils;
|
||||||
using SatelliteProvider.DataAccess.Models;
|
using SatelliteProvider.DataAccess.Models;
|
||||||
@@ -10,7 +11,7 @@ using SixLabors.ImageSharp;
|
|||||||
using SixLabors.ImageSharp.PixelFormats;
|
using SixLabors.ImageSharp.PixelFormats;
|
||||||
using SixLabors.ImageSharp.Processing;
|
using SixLabors.ImageSharp.Processing;
|
||||||
|
|
||||||
namespace SatelliteProvider.Services;
|
namespace SatelliteProvider.Services.RegionProcessing;
|
||||||
|
|
||||||
public class RegionService : IRegionService
|
public class RegionService : IRegionService
|
||||||
{
|
{
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.10" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.10" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.10" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.10" />
|
||||||
|
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.11" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\SatelliteProvider.Common\SatelliteProvider.Common.csproj" />
|
||||||
|
<ProjectReference Include="..\SatelliteProvider.DataAccess\SatelliteProvider.DataAccess.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using SatelliteProvider.Common.Interfaces;
|
||||||
|
|
||||||
|
namespace SatelliteProvider.Services.RouteManagement;
|
||||||
|
|
||||||
|
public static class RouteManagementServiceCollectionExtensions
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddRouteManagement(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton<IRouteService, RouteService>();
|
||||||
|
services.AddHostedService<RouteProcessingService>();
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -10,7 +10,7 @@ using SixLabors.ImageSharp;
|
|||||||
using SixLabors.ImageSharp.PixelFormats;
|
using SixLabors.ImageSharp.PixelFormats;
|
||||||
using SixLabors.ImageSharp.Processing;
|
using SixLabors.ImageSharp.Processing;
|
||||||
|
|
||||||
namespace SatelliteProvider.Services;
|
namespace SatelliteProvider.Services.RouteManagement;
|
||||||
|
|
||||||
public class RouteProcessingService : BackgroundService
|
public class RouteProcessingService : BackgroundService
|
||||||
{
|
{
|
||||||
+1
-1
@@ -5,7 +5,7 @@ using SatelliteProvider.Common.Utils;
|
|||||||
using SatelliteProvider.DataAccess.Models;
|
using SatelliteProvider.DataAccess.Models;
|
||||||
using SatelliteProvider.DataAccess.Repositories;
|
using SatelliteProvider.DataAccess.Repositories;
|
||||||
|
|
||||||
namespace SatelliteProvider.Services;
|
namespace SatelliteProvider.Services.RouteManagement;
|
||||||
|
|
||||||
public class RouteService : IRouteService
|
public class RouteService : IRouteService
|
||||||
{
|
{
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.10" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.10" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.10" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.10" />
|
||||||
|
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.11" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\SatelliteProvider.Common\SatelliteProvider.Common.csproj" />
|
||||||
|
<ProjectReference Include="..\SatelliteProvider.DataAccess\SatelliteProvider.DataAccess.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
+2
-6
@@ -5,15 +5,11 @@ using Microsoft.Extensions.Options;
|
|||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using SatelliteProvider.Common.Configs;
|
using SatelliteProvider.Common.Configs;
|
||||||
using SatelliteProvider.Common.DTO;
|
using SatelliteProvider.Common.DTO;
|
||||||
|
using SatelliteProvider.Common.Exceptions;
|
||||||
using SatelliteProvider.Common.Interfaces;
|
using SatelliteProvider.Common.Interfaces;
|
||||||
using SatelliteProvider.Common.Utils;
|
using SatelliteProvider.Common.Utils;
|
||||||
|
|
||||||
namespace SatelliteProvider.Services;
|
namespace SatelliteProvider.Services.TileDownloader;
|
||||||
|
|
||||||
public class RateLimitException : Exception
|
|
||||||
{
|
|
||||||
public RateLimitException(string message) : base(message) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class GoogleMapsDownloaderV2 : ISatelliteDownloader
|
public class GoogleMapsDownloaderV2 : ISatelliteDownloader
|
||||||
{
|
{
|
||||||
+1
-3
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
@@ -8,12 +8,10 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.10" />
|
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="9.0.10" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.10" />
|
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.10" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.10" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.10" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.10" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.10" />
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.10" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.11" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using SatelliteProvider.Common.Interfaces;
|
||||||
|
|
||||||
|
namespace SatelliteProvider.Services.TileDownloader;
|
||||||
|
|
||||||
|
public static class TileDownloaderServiceCollectionExtensions
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddTileDownloader(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddMemoryCache();
|
||||||
|
services.AddSingleton<ISatelliteDownloader, GoogleMapsDownloaderV2>();
|
||||||
|
services.AddSingleton<ITileService, TileService>();
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -6,7 +6,7 @@ using SatelliteProvider.Common.Utils;
|
|||||||
using SatelliteProvider.DataAccess.Models;
|
using SatelliteProvider.DataAccess.Models;
|
||||||
using SatelliteProvider.DataAccess.Repositories;
|
using SatelliteProvider.DataAccess.Repositories;
|
||||||
|
|
||||||
namespace SatelliteProvider.Services;
|
namespace SatelliteProvider.Services.TileDownloader;
|
||||||
|
|
||||||
public class TileService : ITileService
|
public class TileService : ITileService
|
||||||
{
|
{
|
||||||
@@ -6,7 +6,7 @@ using SatelliteProvider.Common.DTO;
|
|||||||
using SatelliteProvider.Common.Interfaces;
|
using SatelliteProvider.Common.Interfaces;
|
||||||
using SatelliteProvider.DataAccess.Models;
|
using SatelliteProvider.DataAccess.Models;
|
||||||
using SatelliteProvider.DataAccess.Repositories;
|
using SatelliteProvider.DataAccess.Repositories;
|
||||||
using SatelliteProvider.Services;
|
using SatelliteProvider.Services.TileDownloader;
|
||||||
using SatelliteProvider.Tests.Fixtures;
|
using SatelliteProvider.Tests.Fixtures;
|
||||||
|
|
||||||
namespace SatelliteProvider.Tests;
|
namespace SatelliteProvider.Tests;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Microsoft.Extensions.Logging.Abstractions;
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
using SatelliteProvider.Common.DTO;
|
using SatelliteProvider.Common.DTO;
|
||||||
using SatelliteProvider.Services;
|
using SatelliteProvider.Services.RegionProcessing;
|
||||||
|
|
||||||
namespace SatelliteProvider.Tests;
|
namespace SatelliteProvider.Tests;
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,11 @@ using Microsoft.Extensions.Options;
|
|||||||
using Moq;
|
using Moq;
|
||||||
using SatelliteProvider.Common.Configs;
|
using SatelliteProvider.Common.Configs;
|
||||||
using SatelliteProvider.Common.DTO;
|
using SatelliteProvider.Common.DTO;
|
||||||
|
using SatelliteProvider.Common.Exceptions;
|
||||||
using SatelliteProvider.Common.Interfaces;
|
using SatelliteProvider.Common.Interfaces;
|
||||||
using SatelliteProvider.DataAccess.Models;
|
using SatelliteProvider.DataAccess.Models;
|
||||||
using SatelliteProvider.DataAccess.Repositories;
|
using SatelliteProvider.DataAccess.Repositories;
|
||||||
using SatelliteProvider.Services;
|
using SatelliteProvider.Services.RegionProcessing;
|
||||||
|
|
||||||
namespace SatelliteProvider.Tests;
|
namespace SatelliteProvider.Tests;
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using SatelliteProvider.Common.Interfaces;
|
|||||||
using SatelliteProvider.Common.Utils;
|
using SatelliteProvider.Common.Utils;
|
||||||
using SatelliteProvider.DataAccess.Models;
|
using SatelliteProvider.DataAccess.Models;
|
||||||
using SatelliteProvider.DataAccess.Repositories;
|
using SatelliteProvider.DataAccess.Repositories;
|
||||||
using SatelliteProvider.Services;
|
using SatelliteProvider.Services.RouteManagement;
|
||||||
using SatelliteProvider.Tests.Fixtures;
|
using SatelliteProvider.Tests.Fixtures;
|
||||||
|
|
||||||
namespace SatelliteProvider.Tests;
|
namespace SatelliteProvider.Tests;
|
||||||
|
|||||||
@@ -36,7 +36,9 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\SatelliteProvider.Services\SatelliteProvider.Services.csproj" />
|
<ProjectReference Include="..\SatelliteProvider.Services.TileDownloader\SatelliteProvider.Services.TileDownloader.csproj" />
|
||||||
|
<ProjectReference Include="..\SatelliteProvider.Services.RegionProcessing\SatelliteProvider.Services.RegionProcessing.csproj" />
|
||||||
|
<ProjectReference Include="..\SatelliteProvider.Services.RouteManagement\SatelliteProvider.Services.RouteManagement.csproj" />
|
||||||
<ProjectReference Include="..\SatelliteProvider.Common\SatelliteProvider.Common.csproj" />
|
<ProjectReference Include="..\SatelliteProvider.Common\SatelliteProvider.Common.csproj" />
|
||||||
<ProjectReference Include="..\SatelliteProvider.DataAccess\SatelliteProvider.DataAccess.csproj" />
|
<ProjectReference Include="..\SatelliteProvider.DataAccess\SatelliteProvider.DataAccess.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ using SatelliteProvider.Common.DTO;
|
|||||||
using SatelliteProvider.Common.Interfaces;
|
using SatelliteProvider.Common.Interfaces;
|
||||||
using SatelliteProvider.DataAccess.Models;
|
using SatelliteProvider.DataAccess.Models;
|
||||||
using SatelliteProvider.DataAccess.Repositories;
|
using SatelliteProvider.DataAccess.Repositories;
|
||||||
using SatelliteProvider.Services;
|
using SatelliteProvider.Services.TileDownloader;
|
||||||
using SatelliteProvider.Tests.Fixtures;
|
using SatelliteProvider.Tests.Fixtures;
|
||||||
|
|
||||||
namespace SatelliteProvider.Tests;
|
namespace SatelliteProvider.Tests;
|
||||||
|
|||||||
+17
-5
@@ -5,7 +5,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SatelliteProvider.Api", "Sa
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SatelliteProvider.Common", "SatelliteProvider.Common\SatelliteProvider.Common.csproj", "{5499248E-F025-4091-9103-6AA02C6CB613}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SatelliteProvider.Common", "SatelliteProvider.Common\SatelliteProvider.Common.csproj", "{5499248E-F025-4091-9103-6AA02C6CB613}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SatelliteProvider.Services", "SatelliteProvider.Services\SatelliteProvider.Services.csproj", "{452166A0-28C3-429F-B2BD-39041FB7B5A5}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SatelliteProvider.Services.TileDownloader", "SatelliteProvider.Services.TileDownloader\SatelliteProvider.Services.TileDownloader.csproj", "{B7E1A001-1111-4111-9111-111111111111}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SatelliteProvider.Services.RegionProcessing", "SatelliteProvider.Services.RegionProcessing\SatelliteProvider.Services.RegionProcessing.csproj", "{B7E1A002-2222-4222-9222-222222222222}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SatelliteProvider.Services.RouteManagement", "SatelliteProvider.Services.RouteManagement\SatelliteProvider.Services.RouteManagement.csproj", "{B7E1A003-3333-4333-9333-333333333333}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SatelliteProvider.Tests", "SatelliteProvider.Tests\SatelliteProvider.Tests.csproj", "{A44A2E49-9270-4938-9D34-A31CE63E636C}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SatelliteProvider.Tests", "SatelliteProvider.Tests\SatelliteProvider.Tests.csproj", "{A44A2E49-9270-4938-9D34-A31CE63E636C}"
|
||||||
EndProject
|
EndProject
|
||||||
@@ -27,10 +31,18 @@ Global
|
|||||||
{5499248E-F025-4091-9103-6AA02C6CB613}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{5499248E-F025-4091-9103-6AA02C6CB613}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{5499248E-F025-4091-9103-6AA02C6CB613}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{5499248E-F025-4091-9103-6AA02C6CB613}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{5499248E-F025-4091-9103-6AA02C6CB613}.Release|Any CPU.Build.0 = Release|Any CPU
|
{5499248E-F025-4091-9103-6AA02C6CB613}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{452166A0-28C3-429F-B2BD-39041FB7B5A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{B7E1A001-1111-4111-9111-111111111111}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{452166A0-28C3-429F-B2BD-39041FB7B5A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{B7E1A001-1111-4111-9111-111111111111}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{452166A0-28C3-429F-B2BD-39041FB7B5A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{B7E1A001-1111-4111-9111-111111111111}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{452166A0-28C3-429F-B2BD-39041FB7B5A5}.Release|Any CPU.Build.0 = Release|Any CPU
|
{B7E1A001-1111-4111-9111-111111111111}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{B7E1A002-2222-4222-9222-222222222222}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{B7E1A002-2222-4222-9222-222222222222}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B7E1A002-2222-4222-9222-222222222222}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{B7E1A002-2222-4222-9222-222222222222}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{B7E1A003-3333-4333-9333-333333333333}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{B7E1A003-3333-4333-9333-333333333333}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B7E1A003-3333-4333-9333-333333333333}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{B7E1A003-3333-4333-9333-333333333333}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{A44A2E49-9270-4938-9D34-A31CE63E636C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{A44A2E49-9270-4938-9D34-A31CE63E636C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{A44A2E49-9270-4938-9D34-A31CE63E636C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{A44A2E49-9270-4938-9D34-A31CE63E636C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{A44A2E49-9270-4938-9D34-A31CE63E636C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{A44A2E49-9270-4938-9D34-A31CE63E636C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
# Batch Report
|
||||||
|
|
||||||
|
**Batch**: 5 (refactor 02-coupling-refactoring · Phase B)
|
||||||
|
**Tasks**: AZ-312, AZ-313, AZ-314
|
||||||
|
**Date**: 2026-05-10
|
||||||
|
|
||||||
|
## Task Results
|
||||||
|
|
||||||
|
| Task | Status | Files Modified | Tests | AC Coverage | Issues |
|
||||||
|
|------|--------|---------------|-------|-------------|--------|
|
||||||
|
| AZ-312 Split Services into 3 csprojs | Done | 3 new csprojs + 7 source moves + sln + 2 Dockerfiles | 40/40 + smoke | 4/4 ACs | None |
|
||||||
|
| AZ-313 Update consumer csprojs | Done | Api.csproj + Tests.csproj + 5 test usings | 40/40 + smoke | 3/3 ACs | None |
|
||||||
|
| AZ-314 DI extension methods | Done | 3 new ServiceCollectionExtensions + Program.cs | 40/40 + smoke | 4/4 ACs | None |
|
||||||
|
|
||||||
|
## Files Changed
|
||||||
|
|
||||||
|
New:
|
||||||
|
- `SatelliteProvider.Services.TileDownloader/SatelliteProvider.Services.TileDownloader.csproj`
|
||||||
|
- `SatelliteProvider.Services.TileDownloader/TileDownloaderServiceCollectionExtensions.cs`
|
||||||
|
- `SatelliteProvider.Services.RegionProcessing/SatelliteProvider.Services.RegionProcessing.csproj`
|
||||||
|
- `SatelliteProvider.Services.RegionProcessing/RegionProcessingServiceCollectionExtensions.cs`
|
||||||
|
- `SatelliteProvider.Services.RouteManagement/SatelliteProvider.Services.RouteManagement.csproj`
|
||||||
|
- `SatelliteProvider.Services.RouteManagement/RouteManagementServiceCollectionExtensions.cs`
|
||||||
|
- `SatelliteProvider.Common/Exceptions/RateLimitException.cs`
|
||||||
|
|
||||||
|
Moved (with namespace updates):
|
||||||
|
- `TileService.cs`, `GoogleMapsDownloaderV2.cs` → `SatelliteProvider.Services.TileDownloader/`
|
||||||
|
- `RegionService.cs`, `RegionProcessingService.cs`, `RegionRequestQueue.cs` → `SatelliteProvider.Services.RegionProcessing/`
|
||||||
|
- `RouteService.cs`, `RouteProcessingService.cs` → `SatelliteProvider.Services.RouteManagement/`
|
||||||
|
|
||||||
|
Modified:
|
||||||
|
- `SatelliteProvider.Api/Program.cs` (DI cleanup + namespace usings)
|
||||||
|
- `SatelliteProvider.Api/SatelliteProvider.Api.csproj` (3 new ProjectReferences)
|
||||||
|
- `SatelliteProvider.Api/Dockerfile` (COPY new csproj paths)
|
||||||
|
- `SatelliteProvider.IntegrationTests/Dockerfile` (drop stale COPY of old Services csproj)
|
||||||
|
- `SatelliteProvider.Tests/SatelliteProvider.Tests.csproj` (3 new ProjectReferences)
|
||||||
|
- `SatelliteProvider.Tests/InfrastructureTests.cs`, `TileServiceTests.cs`, `RegionServiceTests.cs`, `RouteServiceTests.cs`, `RegionRequestQueueTests.cs` (using updates)
|
||||||
|
- `SatelliteProvider.sln`
|
||||||
|
|
||||||
|
Deleted:
|
||||||
|
- `SatelliteProvider.Services/` directory (csproj + 7 source files moved out)
|
||||||
|
|
||||||
|
## AC Test Coverage
|
||||||
|
|
||||||
|
11 of 11 ACs across the 3 tasks covered. Build/test acceptance verified by `dotnet build` (0 warn, 0 err), 40/40 unit tests, and smoke integration suite passing end-to-end.
|
||||||
|
|
||||||
|
## Code Review Verdict
|
||||||
|
|
||||||
|
**PASS** — no findings. See `_docs/03_implementation/reviews/batch_05_review.md`.
|
||||||
|
|
||||||
|
## Auto-Fix Attempts
|
||||||
|
|
||||||
|
1 (in-batch): `RateLimitException` was originally defined in `GoogleMapsDownloaderV2.cs` (TileDownloader) and caught in `RegionService.cs` (RegionProcessing). After the split, this would have required a `RegionProcessing → TileDownloader` ProjectReference (cross-Layer-3 dependency). Resolved by relocating the exception to `SatelliteProvider.Common/Exceptions/`.
|
||||||
|
|
||||||
|
## Build / Tests
|
||||||
|
|
||||||
|
- `dotnet build SatelliteProvider.sln --configuration Release` → 0 warnings, 0 errors (47.98s)
|
||||||
|
- `dotnet test SatelliteProvider.Tests` → 40/40 passed (1.93s)
|
||||||
|
- `./scripts/run-tests.sh --smoke` → all integration tests pass end-to-end (~2 min)
|
||||||
|
|
||||||
|
## Architecture-Baseline Impact
|
||||||
|
|
||||||
|
- F4 (Medium — single Services csproj packs three components): **resolved** by project split. Compiler now enforces the layer-3 sibling boundary.
|
||||||
|
- F3 (Medium — already resolved in Batch 4): no regression.
|
||||||
|
- Documentation sync (`module-layout.md`, `architecture.md`) deferred to AZ-315 (Batch 6).
|
||||||
|
|
||||||
|
## Next Batch
|
||||||
|
|
||||||
|
AZ-315 (Phase C — documentation sync: update `architecture.md` and `module-layout.md` to reflect the split, then close epic AZ-309).
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
# Code Review Report
|
||||||
|
|
||||||
|
**Batch**: 5 (AZ-312, AZ-313, AZ-314 — coupling refactor: project split + DI extension methods)
|
||||||
|
**Date**: 2026-05-10
|
||||||
|
**Verdict**: PASS
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
Structural refactoring (architecture baseline finding F4): split monolithic `SatelliteProvider.Services` into three per-component csprojs, rewire consumers, and extract DI registrations into per-component extension methods.
|
||||||
|
|
||||||
|
Tasks reviewed:
|
||||||
|
- **AZ-312** — split Services into TileDownloader + RegionProcessing + RouteManagement csprojs
|
||||||
|
- **AZ-313** — update consumer csprojs (Api, Tests, IntegrationTests) + `using` directives
|
||||||
|
- **AZ-314** — DI extension methods per csproj + Program.cs cleanup
|
||||||
|
|
||||||
|
## Changed files
|
||||||
|
|
||||||
|
- New csprojs:
|
||||||
|
- `SatelliteProvider.Services.TileDownloader/SatelliteProvider.Services.TileDownloader.csproj`
|
||||||
|
- `SatelliteProvider.Services.RegionProcessing/SatelliteProvider.Services.RegionProcessing.csproj`
|
||||||
|
- `SatelliteProvider.Services.RouteManagement/SatelliteProvider.Services.RouteManagement.csproj`
|
||||||
|
- New DI extension files:
|
||||||
|
- `SatelliteProvider.Services.TileDownloader/TileDownloaderServiceCollectionExtensions.cs`
|
||||||
|
- `SatelliteProvider.Services.RegionProcessing/RegionProcessingServiceCollectionExtensions.cs`
|
||||||
|
- `SatelliteProvider.Services.RouteManagement/RouteManagementServiceCollectionExtensions.cs`
|
||||||
|
- Moved (with namespace updates): `TileService.cs`, `GoogleMapsDownloaderV2.cs`, `RegionService.cs`, `RegionProcessingService.cs`, `RegionRequestQueue.cs`, `RouteService.cs`, `RouteProcessingService.cs`
|
||||||
|
- New common exception: `SatelliteProvider.Common/Exceptions/RateLimitException.cs`
|
||||||
|
- Modified: `SatelliteProvider.Api/Program.cs`, `SatelliteProvider.Api/SatelliteProvider.Api.csproj`, `SatelliteProvider.Tests/SatelliteProvider.Tests.csproj`, all 5 `*Tests.cs` files (`using` updates), `SatelliteProvider.sln`, both `Dockerfile`s
|
||||||
|
- Deleted: `SatelliteProvider.Services/` directory and `SatelliteProvider.Services.csproj`
|
||||||
|
|
||||||
|
## Findings
|
||||||
|
|
||||||
|
| # | Severity | Category | File:Line | Title |
|
||||||
|
|---|----------|----------|-----------|-------|
|
||||||
|
|
||||||
|
No findings.
|
||||||
|
|
||||||
|
## Phase results
|
||||||
|
|
||||||
|
### Phase 2 — Spec compliance
|
||||||
|
|
||||||
|
**AZ-312 (project split)**
|
||||||
|
|
||||||
|
- AC-1 ✓ — Three new csprojs exist with the seven moved source files distributed correctly (verified by `ls`).
|
||||||
|
- AC-2 ✓ — Old `SatelliteProvider.Services/` directory and csproj deleted; `SatelliteProvider.sln` updated.
|
||||||
|
- AC-3 ✓ — `dotnet build SatelliteProvider.sln` succeeds with 0 warnings, 0 errors.
|
||||||
|
- AC-4 ✓ — None of the three new csprojs reference each other. All three reference only `SatelliteProvider.Common` + `SatelliteProvider.DataAccess`.
|
||||||
|
|
||||||
|
**AZ-313 (consumer rewire)**
|
||||||
|
|
||||||
|
- AC-1 ✓ — Solution builds clean (47.98s, 0 warnings).
|
||||||
|
- AC-2 ✓ — All 40 unit tests pass (1.93s).
|
||||||
|
- AC-3 ✓ — Grep for `using SatelliteProvider.Services;` (no `.<Component>` suffix) returns zero source-file matches.
|
||||||
|
|
||||||
|
**AZ-314 (DI extension methods)**
|
||||||
|
|
||||||
|
- AC-1 ✓ — Each `*ServiceCollectionExtensions.cs` registers exactly the services owned by its csproj:
|
||||||
|
- `AddTileDownloader`: `IMemoryCache`, `ISatelliteDownloader`, `ITileService`
|
||||||
|
- `AddRegionProcessing`: `IRegionRequestQueue` (factory), `IRegionService`, `RegionProcessingService` (hosted)
|
||||||
|
- `AddRouteManagement`: `IRouteService`, `RouteProcessingService` (hosted)
|
||||||
|
- AC-2 ✓ — `Program.cs:33-35` calls the three extension methods; previously inlined registrations are gone.
|
||||||
|
- AC-3 ✓ — Smoke integration suite passes end-to-end (region processing, route processing, tile ZIP, security tests). Every required service resolves at runtime.
|
||||||
|
- AC-4 ✓ — No old service-registration code remains in `Program.cs`.
|
||||||
|
|
||||||
|
### Phase 3 — Code quality
|
||||||
|
|
||||||
|
- SOLID (SRP/DIP) **improved** — components now have a compiler-enforced boundary; cross-component coupling can no longer be introduced silently.
|
||||||
|
- Lifetimes preserved — `Singleton` stayed `Singleton`, hosted services stayed hosted services.
|
||||||
|
- Hosted-service registration order preserved (`RegionProcessingService` before `RouteProcessingService`, matching pre-refactor order in Program.cs).
|
||||||
|
- No new dead code; no scope creep.
|
||||||
|
|
||||||
|
### Phase 4 — Security quick-scan
|
||||||
|
|
||||||
|
Refactor is structural; no new input handling, query construction, or deserialization paths. Smoke security tests (SEC-01 SQL injection, SEC-02 path traversal, SEC-03 oversized region, SEC-04 malformed JSON) all pass post-refactor.
|
||||||
|
|
||||||
|
### Phase 5 — Performance scan
|
||||||
|
|
||||||
|
No hot-path changes. No new allocations in the moved code (only namespace and project boundary changes).
|
||||||
|
|
||||||
|
### Phase 6 — Cross-task consistency
|
||||||
|
|
||||||
|
- All three new extension methods follow the same `Add<Component>(this IServiceCollection)` naming convention.
|
||||||
|
- All three new csprojs share identical TFM (`net8.0`), `ImplicitUsings`, and `Nullable` settings.
|
||||||
|
- Package versions consistent (`9.0.10` for `Microsoft.Extensions.*`, `13.0.4` for `Newtonsoft.Json`, `3.1.11` for `SixLabors.ImageSharp`).
|
||||||
|
|
||||||
|
### Phase 7 — Architecture compliance
|
||||||
|
|
||||||
|
- **Layer direction** ✓ — TileDownloader (Layer 2) imports only Common + DataAccess (Layer 1). RegionProcessing and RouteManagement (Layer 3) import only Common + DataAccess (no cross-Layer-3 references after the refactor — even better than the pre-refactor baseline allowed).
|
||||||
|
- **Public API respect** ✓ — All cross-component imports use interfaces from `SatelliteProvider.Common.Interfaces`, never concrete types from sibling components.
|
||||||
|
- **No new cyclic dependencies** ✓ — Graph is a clean DAG: Common ← {DataAccess} ← {TileDownloader, RegionProcessing, RouteManagement} ← WebApi.
|
||||||
|
- **Architecture baseline F4** — **RESOLVED**. The single `SatelliteProvider.Services.csproj` packing three components is replaced by three csprojs with compiler-enforced boundaries.
|
||||||
|
- **Architecture baseline F3** — already resolved in Batch 4 (AZ-310 + AZ-311); this batch did not regress it (`Program.cs` tile endpoints still route through `ITileService`).
|
||||||
|
- **`RateLimitException` placement** — moved to `SatelliteProvider.Common/Exceptions/` rather than allowing a `RegionProcessing → TileDownloader` ProjectReference. This is the cleanest of the three options considered (move to Common / add reference / catch general `Exception`) and preserves layer 3 components as siblings rather than coupling them.
|
||||||
|
|
||||||
|
## Baseline Delta
|
||||||
|
|
||||||
|
| Status | Finding | Severity | Notes |
|
||||||
|
|--------|---------|----------|-------|
|
||||||
|
| Resolved | F4 — `SatelliteProvider.Services.csproj` packs three logical components | Medium | Split into three csprojs |
|
||||||
|
| Carried over | (none for this batch) | — | — |
|
||||||
|
| Newly introduced | (none) | — | — |
|
||||||
|
|
||||||
|
`module-layout.md` and `architecture.md` still describe the pre-split layout (single `SatelliteProvider.Services/` project). This is **expected** — documentation sync is task **AZ-315** (Batch 3 of this refactor run). Not a finding.
|
||||||
|
|
||||||
|
## Verdict
|
||||||
|
|
||||||
|
**PASS** — all 12 ACs across 3 tasks satisfied. Build clean. Unit tests 40/40. Smoke integration green. Architecture baseline F4 resolved with no new findings.
|
||||||
Reference in New Issue
Block a user