docs(historian): backend capability matrix; warn on Gateway continuous historization (lmxopcua#746)

The Gateway backend's gaps against SqlServer/QuestDb were documented
piecemeal. The backend-selection table in docs/Historian.md now also covers
the aggregate set (and the native time-weighted opt-in), emulated reverse
and end-only reads, the client-side events cap, retention and the health
probe.

Continuous historization on Gateway silently loses sample quality (stored
Good), comms-loss outage markers and non-numeric values. Building its live
writer, which only happens when ContinuousHistorization is enabled, now
logs one startup Warning that names the gaps and the alternatives.

The review asked for the matrix in the AdminUI backend picker, but no such
picker exists: the backend is configuration-only. Filed as a follow-up.

Rebased from the unpushed remed/lane-H2 branch (originally authored 2026-10-22
in session_01Ub9hGmYLQvn9XETzw7CMsT) onto current master.

Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
Joseph Doherty
2026-10-22 17:36:04 -04:00
parent 64269573e7
commit 096a3d5b3c
3 changed files with 78 additions and 1 deletions
@@ -35,15 +35,26 @@ public sealed class GatewayHistorianProvider : IHistorianBackendProvider
public IHistorianDataSource CreateDataSource(IServiceProvider sp) => GatewayHistorian.CreateDataSource(_options, sp);
/// <inheritdoc />
// Built only when continuous historization is enabled on this backend, so this is where its startup Warning lives:
// the gaps are silent at run time (the gateway accepts a quality it then discards).
public IHistorianValueWriter CreateValueWriter(IServiceProvider sp)
{
ArgumentNullException.ThrowIfNull(sp);
var loggerFactory = sp.GetService<ILoggerFactory>() ?? NullLoggerFactory.Instance;
var logger = sp.GetService<ILogger<GatewayHistorianValueWriter>>()
?? NullLogger<GatewayHistorianValueWriter>.Instance;
logger.LogWarning(ContinuousHistorizationWarning);
return new GatewayHistorianValueWriter(HistorianGatewayClientAdapter.Create(_options, loggerFactory), logger);
}
/// <summary>The startup Warning for continuous historization on this backend (see docs/Historian.md, the capability matrix).</summary>
internal const string ContinuousHistorizationWarning =
"Continuous historization is enabled on the Gateway historian backend, which stores less than the SQL backends: " +
"the gateway discards each sample's quality (AVEVA stores every recorded value Good, so a driver's Bad or Uncertain " +
"publish is historized as Good), comms-loss outage markers are dropped (reads interpolate across an outage), and " +
"non-numeric values (String, DateTime) are not recorded. Use the SqlServer or QuestDb backend where stored status, " +
"outage markers or non-numeric history matter.";
/// <inheritdoc />
public IAlarmHistorianWriter CreateAlarmWriter(IServiceProvider sp) => GatewayHistorian.CreateAlarmWriter(_options, sp);