Files
slp-modular-cms/aidlc-docs/features/master-cms-module/construction/plans/slave-availability-extension-nfr-design-plan.md

73 lines
2.8 KiB
Markdown

# NFR Design Plan — Unit 2: slave-availability-extension
## Unit Context
**Unit**: `slave-availability-extension`
**Inputs**: nfr-requirements.md, tech-stack-decisions.md (Unit 2)
**Already decided**: `IMasterApiKeyProtector` wrapper (mirrors Unit 1 `IApiKeyProtector`); `volatile` static cache fields; structured logging table; `AvailabilityDbContext` + `IMasterRegistrationRepository`
**Key design decisions remaining**: middleware extension pattern, `IMasterAvailabilityService` interface shape, service constructor
---
## Questions
Answer each question by filling in your choice after the `[Answer]:` tag.
---
### Q1 — Middleware: How does `AvailabilityMiddleware` read the master gate status?
The master gate needs to read `_masterIsAvailable` (volatile bool) on every request. Two approaches:
A) **InvokeAsync injection** — add `IMasterAvailabilityService` as a third parameter to `InvokeAsync`. The service exposes a synchronous `GetMasterStatus()` method that returns the volatile fields. Pattern:
```csharp
public async Task InvokeAsync(HttpContext context,
IAvailabilityService localSvc,
IMasterAvailabilityService masterSvc)
{
if (!masterSvc.GetMasterStatus().IsAvailable) { /* 503 */ }
...
}
```
Fully testable via NSubstitute substitute on `IMasterAvailabilityService`. Consistent with how `IAvailabilityService` is already injected.
B) **Direct static read**`AvailabilityMiddleware` reads `MasterAvailabilityService._masterIsAvailable` directly via `internal static volatile` fields (with `InternalsVisibleTo` for the test project). No extra injection; no interface method for status read; slightly faster on hot path.
C) Other
[Answer]: A
---
### Q2 — `MasterAvailabilityService` constructor: Direct injection or deps record?
`MasterAvailabilityService` needs 3 dependencies: `IMasterRegistrationRepository`, `IMasterApiKeyProtector`, `ILogger<MasterAvailabilityService>`.
A) **Direct injection** — pass all 3 as constructor parameters. Simple; idiomatic for a small number of deps. No wrapper record needed.
```csharp
public MasterAvailabilityService(
IMasterRegistrationRepository repository,
IMasterApiKeyProtector keyProtector,
ILogger<MasterAvailabilityService> logger)
```
B) **Dependencies record** — wrap in `MasterAvailabilityServiceDependencies` record (consistent with Unit 1's `MasterServiceDependencies`). Useful if deps may grow or for visual consistency.
C) Other
[Answer]: B
---
## Execution Steps
- [x] **Step 1** — Analyze answers; flag ambiguities
- [x] **Step 2** — Generate `nfr-design-patterns.md`
- [x] **Step 3** — Generate `logical-components.md`
- [ ] **Step 4** — Update `aidlc-state.md`
- [ ] **Step 5** — Present completion message for approval
---
*Artifact path*: `aidlc-docs/features/master-cms-module/construction/plans/slave-availability-extension-nfr-design-plan.md`