merge(agent-c): row 82 — cross-process create+migrate throttle (sp_getapplock counting semaphore), honest command timeouts, deterministic actor stops in the two leaking AuditLog test classes
This commit is contained in:
@@ -26,6 +26,40 @@ The test database uses Microsoft SQL Server 2022 Developer Edition running in Do
|
||||
|
||||
Both databases are created by `infra/mssql/setup.sql`. EF Core migrations populate the `ScadaBridgeConfig` schema. The `ScadaBridgeMachineData` database is seeded with sample tables and stored procedures by `infra/mssql/machinedata_seed.sql`.
|
||||
|
||||
### Ephemeral per-test-class databases
|
||||
|
||||
`MsSqlMigrationFixture` (`tests/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests/Migrations/`) creates a
|
||||
throwaway `ScadaBridgeAuditMigTest_<guid>` database per test class, applies the full EF migration chain
|
||||
to it, and drops it on teardown. Both `ConfigurationDatabase.Tests` and `AuditLog.Tests` use it — the
|
||||
latter by project reference, so there is one fixture implementation, not a copy. Seeing a handful of
|
||||
these databases come and go while tests run is normal; seeing them survive a run is not (see below).
|
||||
|
||||
Three behaviours are worth knowing when you look at this server during a test run:
|
||||
|
||||
- **Concurrent create+migrate is throttled machine-wide.** Fixtures take a slot from a counting
|
||||
semaphore built on `sp_getapplock` in `master` (resources `ScadaBridgeTestMigrate/0..N-1`) and hold it
|
||||
across `CREATE DATABASE` + the migration chain. The default is 4 slots; override with
|
||||
`SCADABRIDGE_MSSQL_TEST_MIGRATE_SLOTS`. An xunit collection attribute cannot do this job — a
|
||||
solution-level `dotnet test` runs several MSSQL-backed test *processes* at once, so the throttle has
|
||||
to live on the shared server. Without it, dozens of simultaneous fresh-database migrations saturated
|
||||
the container and individual DDL statements blew past EF's default 30-second command timeout,
|
||||
failing whole test classes at fixture construction (deferred-work register row 82).
|
||||
- **Migration commands use a 300s timeout**, and CREATE/DROP DATABASE use 120s. Under a bounded queue
|
||||
the server is busy but progressing, so the correct response to a slow statement is to wait.
|
||||
- **Strays are swept.** Each test process drops, once at start and best-effort, any
|
||||
`ScadaBridgeAuditMigTest_*` database older than 2 hours, so a run killed before teardown does not
|
||||
leave databases accumulating. To clear them by hand:
|
||||
|
||||
```bash
|
||||
docker exec -i scadabridge-mssql /opt/mssql-tools18/bin/sqlcmd \
|
||||
-S localhost -U sa -P 'ScadaBridge_Dev1#' -C \
|
||||
-Q "SELECT name, create_date FROM sys.databases WHERE name LIKE 'ScadaBridgeAuditMigTest_%'"
|
||||
```
|
||||
|
||||
Overriding the server the fixture targets (CI, a non-default port) is done with
|
||||
`SCADABRIDGE_MSSQL_TEST_CONN`. When no server answers, the fixture reports `Available = false` and the
|
||||
tests report as **Skipped**, not passed.
|
||||
|
||||
## Data Persistence
|
||||
|
||||
SQL data is stored in the named Docker volume `scadabridge-mssql-data`. Data survives container restarts and `docker compose down`. To reset the database completely:
|
||||
|
||||
Reference in New Issue
Block a user