docs: within-timestamp tie-cluster paging + AbCip/TwinCAT UDT member discovery

This commit is contained in:
Joseph Doherty
2026-06-17 20:35:34 -04:00
parent 4a7b0fde7b
commit 163f57b6bc
3 changed files with 106 additions and 11 deletions
+27 -11
View File
@@ -64,7 +64,8 @@ and all HistoryRead calls on historized nodes return `GoodNoData` (empty, not an
"Port": 32569,
"UseTls": false,
"ServerCertThumbprint": "",
"SharedSecret": ""
"SharedSecret": "",
"MaxTieClusterOverfetch": 65536
}
}
```
@@ -77,6 +78,7 @@ and all HistoryRead calls on historized nodes return `GoodNoData` (empty, not an
| `UseTls` | bool | `false` | Wrap the TCP connection in TLS. |
| `ServerCertThumbprint` | string | — | Optional SHA-1 thumbprint to pin the sidecar's TLS certificate. Leave empty for CA-chain validation. |
| `SharedSecret` | string | — | Shared secret token the sidecar expects on every connection. Required when `Enabled`. |
| `MaxTieClusterOverfetch` | int | `65536` | Maximum samples the server will fetch in one shot to page through a tie cluster (multiple samples sharing one `SourceTimestamp`). A cluster larger than this ceiling fails `BadHistoryOperationUnsupported`. Raise to handle abnormally large tie clusters; the default covers all normal-data cases. |
> **Do not commit `SharedSecret` to `appsettings.json`.** Set it via an environment variable,
> a secrets store, or a deployment-time overlay. The checked-in default is always empty.
@@ -141,16 +143,30 @@ paging time-based:
SourceTimestamp *inclusive* and drops the boundary samples already emitted, so samples sharing
the boundary timestamp are neither duplicated nor skipped.
> **Paging limitation — oversized tie clusters.** The tie-safe cursor is a `(timestamp, skip)`
> pair, and the single-shot backend only accepts `(start, end, cap)` — it cannot skip. So if **more
> samples share one `SourceTimestamp` than `NumValuesPerNode`** (a tie cluster larger than the page
> cap), the cursor cannot advance past that timestamp: every resume re-reads the same first `cap`
> ties. Rather than silently truncate the read to `GoodNoData` (which would permanently drop the
> un-emitted ties), the resume read fails that node **loudly** with
> `BadHistoryOperationUnsupported` and logs the tag + timestamp + cap. The operator's remedy is to
> re-issue the read with a larger `NumValuesPerNode`. For a single tag's raw history this is a data
> anomaly (raw samples normally carry strictly increasing distinct timestamps); a fully cursor-based
> fix that pages *within* a single timestamp is a possible follow-up.
> **Oversized tie clusters — within-timestamp paging.** When more samples share one
> `SourceTimestamp` than the current page cap, the server detects that the cursor has stalled on
> a tie cluster (the last returned timestamp equals the resume timestamp). It then **over-fetches
> the entire cluster** at that single timestamp up to a bounded ceiling controlled by
> `ServerHistorian:MaxTieClusterOverfetch` (default **65 536**), then serves the cluster
> `NumValuesPerNode` samples at a time across successive pages, advancing the cursor one tick past
> the timestamp once the cluster is fully drained.
>
> **Short pages within a cluster still carry a continuation point.** A within-cluster page that
> returns fewer than `NumValuesPerNode` samples (because the cluster happened to be smaller than
> the cap, or is the final partial batch) is not the last page if the cluster itself has not been
> fully emitted — the server retains the continuation point so the client can drain the remainder.
> Only when the cluster is exhausted and the cursor has advanced past the timestamp does the
> short-page rule apply.
>
> **Cluster larger than `MaxTieClusterOverfetch`.** If the over-fetch itself reaches the ceiling
> without spanning the full cluster, the node fails **loudly** with
> `BadHistoryOperationUnsupported` and the tag + timestamp + ceiling are logged. Remedies: raise
> `MaxTieClusterOverfetch` (or `NumValuesPerNode`) to cover the full cluster, or investigate the
> data anomaly (raw samples normally carry strictly increasing distinct timestamps).
>
> For a single tag's raw history a tie cluster larger than the default 65 536 is a severe data
> anomaly. The ceiling exists to bound server-side memory on pathological data, not to cap normal
> operation.
Continuation points are bound to the OPC UA session (the SDK's
`ServerConfiguration.MaxHistoryContinuationPoints` cap, default 100, with oldest-eviction; points