10a6a37ca5
Adds the frozen-peer / BadTimeout gate for the Sql driver — the single highest-value integration test. Mirrors the S7 R2-01 blackhole gate: docker pause a DEDICATED mssql mid-poll, assert the next read surfaces BadTimeout within the client-side operationTimeout (≈3s) and well below the server-side CommandTimeout backstop (30s), the driver degrades (Degraded + host Stopped), and docker unpause recovers to Healthy/Running. - Docker/docker-compose.yml: disposable `otopcua-sql-blackhole` mssql on :14333 (never the shared :14330 ConfigDb server) + one-shot seed. - Docker/seed.sql: the two sample tables. - SqlBlackholeTimeoutTests.cs: env-gated (SQL_BLACKHOLE_ENDPOINT); pauses ONLY the hard-coded container name; skips loudly if the endpoint is the shared port 14330; bounds its own wait so a wedged impl fails, not hangs. Offline: clean skip (no socket, no docker shell-out). Claude-Session: https://claude.ai/code/session_01GASWkNEi68FSCtvr6rLoEW
44 lines
1.7 KiB
Transact-SQL
44 lines
1.7 KiB
Transact-SQL
-- Seed for the Sql driver's blackhole / frozen-peer live gate (dedicated container only).
|
|
--
|
|
-- Applied once by the compose `mssql-seed` one-shot against the OWNED
|
|
-- `otopcua-sql-blackhole` container. The blackhole test (SqlBlackholeTimeoutTests)
|
|
-- also creates this exact shape defensively on connect, so the two are kept in
|
|
-- parity: a Good baseline poll before the pause depends on `sqlpoll.TagValues`
|
|
-- holding the one seeded row.
|
|
--
|
|
-- Two sample tables mirror the offline SqlitePollFixture / live SqlPollServerFixture
|
|
-- shapes so the gate polls something representative, not a bespoke schema.
|
|
|
|
IF DB_ID(N'SqlBlackholeFixture') IS NULL CREATE DATABASE [SqlBlackholeFixture];
|
|
GO
|
|
|
|
USE [SqlBlackholeFixture];
|
|
GO
|
|
|
|
IF SCHEMA_ID(N'sqlpoll') IS NULL EXEC(N'CREATE SCHEMA [sqlpoll]');
|
|
GO
|
|
|
|
-- Key-value (EAV) source: tag_name → num_value, with a source timestamp.
|
|
DROP TABLE IF EXISTS [sqlpoll].[TagValues];
|
|
CREATE TABLE [sqlpoll].[TagValues] (
|
|
[tag_name] nvarchar(128) NOT NULL,
|
|
[num_value] float NULL,
|
|
[sample_ts] datetime2(3) NOT NULL
|
|
);
|
|
INSERT INTO [sqlpoll].[TagValues] ([tag_name], [num_value], [sample_ts])
|
|
VALUES (N'Line1.Speed', 42.0, '2026-07-24T10:00:00'),
|
|
(N'Line1.Pressure', 3.5, '2026-07-24T10:00:01');
|
|
GO
|
|
|
|
-- Wide-row source: one row per station, several value columns.
|
|
DROP TABLE IF EXISTS [sqlpoll].[LatestStatus];
|
|
CREATE TABLE [sqlpoll].[LatestStatus] (
|
|
[station_id] int NOT NULL,
|
|
[oven_temp] float NULL,
|
|
[pressure] float NULL,
|
|
[sample_ts] datetime2(3) NOT NULL
|
|
);
|
|
INSERT INTO [sqlpoll].[LatestStatus] ([station_id], [oven_temp], [pressure], [sample_ts])
|
|
VALUES (7, 180.5, 1.2, '2026-07-24T10:00:00');
|
|
GO
|