fix(host,auditlog): close Host.Tests env-var race + harden hosted-service shutdown (#15) #19
Reference in New Issue
Block a user
Delete Branch "fix/host-tests-env-race-15"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Fixes #15.
What
Closes the
Host.Testsenv-var race from #15, and fixes a real product defect that verifying it surfaced.Test harness (#15)
CentralDbTestEnvironmentsets five process-wide environment variables, andProgram'sAddEnvironmentVariables()reads them at an unpredictable point during host boot. With xUnit collection parallelization on, one fixture's teardown could clear a var mid-boot for a sibling — and since the secrets adoption (G-4) three of those keys are${secret:...}references that fail closed, turning a previously benign empty value into a hardSecretNotFoundException.HostBootCollectionserializes every fixture that boots a real host while depending on that shared state; the narrowerActorSystemcollection is folded into it.Configuration.Sources.Clear(), dropping the env-var provider, so they can't race.CentralDbTestEnvironmentnow fails fast if two instances are ever live at once, making a future regression deterministic rather than intermittent, and fixture teardown istry/finallyso a throwing host teardown can't strand the vars.Product fix (surfaced while verifying)
The fail-fast guard immediately caught a latent bug: four hosted services (
AuditLogPartitionMaintenanceService,SiteAuditBacklogReporter,SiteAuditRetentionService,SiteEventLogFailureCountReporter) shared a copy-pasted lifecycle with two disposed-CTS races —StopAsynccancelling an already-disposed CTS, andStartAsyncreading_cts.Tokenlazily inside theTask.Runlambda. Either faults the task the host awaits during shutdown, which inHost.Testsskipped the fixture's env-var restore and contaminated the rest of the run. All four now capture the token eagerly, tolerate a disposed CTS, and cancel-before-dispose;SiteAuditBacklogReporteralso gains the outerOperationCanceledExceptionguard its sibling already had.Verification
Host.Tests: 5 consecutive full runs, 279/279 green, zero occurrences of either exception (was ~1-in-3 red before).AuditLog.Tests(354) /HealthMonitoring.Tests(97) green; each of the 5 new regression tests proven red against the unfixed code, then green.Trade-off
Host.Testsruntime goes from ~2m30s to ~4m10s — serializing the six Central-boot classes is most of the assembly's parallelism. Inherent to the fix; flagged for reviewer awareness.Note
Also carries one orthogonal housekeeping commit (
docs: sister-repo index + working notes): a CLAUDE.md sister-repo update plus working-note files, unrelated to the fix.ScadaBridge-docs-issues.mdis a large generated report — drop that commit before merge if it shouldn't live in the repo.CentralDbTestEnvironment sets five process-wide environment variables, and Program's AddEnvironmentVariables() reads them at an unpredictable point during host boot. With xUnit collection parallelization on, one fixture's teardown could clear a var mid-boot for a sibling. Since the secrets adoption (G-4) three of those keys are ${secret:...} references that fail closed, turning a previously benign empty value into a SecretNotFoundException that aborts the boot — an intermittent CI failure. Adds a HostBootCollection that serializes every fixture booting a real host while depending on that shared state, folding in the narrower "ActorSystem" collection so its members stay serialized with each other as before. Site-role fixtures stay parallel: they call Configuration.Sources.Clear(), dropping the env-var provider, so they cannot participate in the race. CentralDbTestEnvironment now also fails fast if two instances are ever live at once, making a regression (a fixture added outside the collection) deterministic rather than intermittent — this is what surfaced the disposed-CTS defect fixed in the previous commit. Fixture teardown is try/finally so a throwing host teardown can no longer strand the vars for the rest of the run. Cost: Host.Tests runs ~2m30s -> ~4m10s; the serialized Central-boot classes are most of the assembly's parallelism. Fixes: Gitea #15