73 lines
2.8 KiB
Markdown
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`
|