5.7 KiB
5.7 KiB
Logical Components — Unit 1: master-backend
Full Component Wiring Diagram
graph TD
subgraph ServiceLayer["Service Layer"]
CmsService["CmsInstanceService"]
Deps["MasterServiceDependencies\n(constructor record)"]
Repo["ICmsInstanceRepository"]
SlaveClientIface["ISlaveApiClient"]
ApiKeyProt["IApiKeyProtector"]
HttpCtxAcc["IHttpContextAccessor"]
Logger["ILogger"]
Opts["MasterModuleOptions\n(via IOptions)"]
end
subgraph SecurityLayer["Security Layer"]
ApiKeyProtImpl["ApiKeyProtector"]
DataProt["IDataProtectionProvider\n(ASP.NET Core)"]
Purpose["Purpose string\nSlpModularCms.Master.ApiKey"]
end
subgraph HttpLayer["HTTP + Resilience Layer"]
SlaveClientImpl["SlaveApiClient"]
PollyPipeline["Polly ResiliencePipeline\nRetry x2 + Timeout"]
HttpClientInst["HttpClient\n(IHttpClientFactory)"]
end
subgraph BackgroundLayer["Background Service"]
BgSvc["IntegrityCheckBackgroundService"]
ScopeFactory["IServiceScopeFactory"]
Scope["IServiceScope\n(per tick)"]
PeriodicT["PeriodicTimer\n(IntegrityCheckIntervalMinutes)"]
end
subgraph DataLayer["Data Layer"]
RepoImpl["CmsInstanceRepository"]
DbCtx["MasterDbContext"]
Table["CmsInstances table"]
end
CmsService --> Deps
Deps --> Repo
Deps --> SlaveClientIface
Deps --> ApiKeyProt
Deps --> HttpCtxAcc
Deps --> Logger
Deps --> Opts
ApiKeyProt --> ApiKeyProtImpl
ApiKeyProtImpl --> DataProt
DataProt --> Purpose
SlaveClientIface --> SlaveClientImpl
SlaveClientImpl --> PollyPipeline
PollyPipeline --> HttpClientInst
Repo --> RepoImpl
RepoImpl --> DbCtx
DbCtx --> Table
BgSvc --> PeriodicT
BgSvc --> ScopeFactory
ScopeFactory --> Scope
Scope --> CmsService
classDef service fill:#9ae6b4,stroke:#2f855a,stroke-width:2px,color:#000
classDef security fill:#FC8181,stroke:#C53030,stroke-width:1px,color:#000
classDef http fill:#63b3ed,stroke:#2b6cb0,stroke-width:1px,color:#000
classDef background fill:#CE93D8,stroke:#6A1B9A,stroke-width:1px,color:#000
classDef data fill:#FFC107,stroke:#F57F17,stroke-width:1px,color:#000
classDef record fill:#B0BEC5,stroke:#546E7A,stroke-width:1px,color:#000
class CmsService,Repo,SlaveClientIface,ApiKeyProt service
class Deps record
class ApiKeyProtImpl,DataProt,Purpose security
class SlaveClientImpl,PollyPipeline,HttpClientInst,HttpCtxAcc http
class BgSvc,ScopeFactory,Scope,PeriodicT background
class RepoImpl,DbCtx,Table,Logger,Opts data
Text alternative: CmsInstanceService receives all dependencies via MasterServiceDependencies record; IApiKeyProtector wraps Data Protection; ISlaveApiClient wraps SlaveApiClient backed by Polly pipeline; ICmsInstanceRepository wraps MasterDbContext; IntegrityCheckBackgroundService creates a new IServiceScope per PeriodicTimer tick to resolve CmsInstanceService.
Component Responsibility Summary
| Component | Type | NFR Pattern |
|---|---|---|
MasterServiceDependencies |
Record | Constructor aggregation (reduces constructor arity) |
IApiKeyProtector / ApiKeyProtector |
Interface + Singleton | Security — Data Protection wrapper; mock-friendly |
SlaveApiClient |
Typed HTTP client | Resilience — Polly retry + timeout applied via AddResilienceHandler |
IntegrityCheckBackgroundService |
Singleton BackgroundService |
Reliability — per-tick IServiceScope; exception isolation per slave |
MasterDbContext |
EF Core DbContext | Maintainability — per-module migrations; own connection |
CmsInstanceService |
Scoped service | Orchestration — resolved via IServiceScope by background service |
DI Registration Order (in MasterModule.RegisterServices)
1. services.AddDataProtection()
2. services.AddSingleton<IApiKeyProtector, ApiKeyProtector>()
3. services.Configure<MasterModuleOptions>(config.GetSection("MasterModule"))
4. services.AddDbContext<MasterDbContext>(...)
5. services.AddScoped<ICmsInstanceRepository, CmsInstanceRepository>()
6. services.AddScoped<MasterServiceDependencies>()
7. services.AddScoped<ICmsInstanceService, CmsInstanceService>()
8. services.AddHttpClient<ISlaveApiClient, SlaveApiClient>()
.AddResilienceHandler("slave-resilience", ...)
9. services.AddHostedService<IntegrityCheckBackgroundService>()
10. services.AddHttpContextAccessor() (if not already registered by host)
NFR Coverage Traceability
| NFR | Pattern Applied | Component |
|---|---|---|
| Fail-open (NFR-MASTER-01) | SlaveApiClient catches failures, returns false; service continues |
SlaveApiClient, CmsInstanceService |
| API key security (NFR-MASTER-03) | IApiKeyProtector wraps Data Protection; never returns key in DTO |
ApiKeyProtector, CmsInstanceDto mapping |
| Configurable interval (NFR-MASTER-04) | PeriodicTimer reads MasterModuleOptions.IntegrityCheckIntervalMinutes |
IntegrityCheckBackgroundService |
| ≥80% test coverage (NFR-MASTER-05) | All service/repository/client classes have interfaces; MasterServiceDependencies simplifies test setup |
All interfaces |
| Per-module migrations (NFR-MASTER-06) | MasterDbContext with own migration assembly; applied in UseModule |
MasterDbContext, MasterModule |
| Retry resilience (Q2) | Polly exponential backoff on IHttpClientBuilder |
SlaveApiClient registration |
| Timeout (Q1) | Polly AddTimeout per attempt, driven by HttpTimeoutSeconds |
SlaveApiClient registration |
| Logging levels (Q5) | Error for status push failures; Warning for integrity check failures |
CmsInstanceService, IntegrityCheckBackgroundService |