fix(historian): #668 review follow-ups (explicit modified source time, paging tests, ACL test, QuestDB orphan warning, docs)
- HistoryModifiedValue gains explicit SourceTimeUtc (SqlServer + QuestDB populate it); the node manager's resume cursor uses it instead of the prior value's nullable source timestamp (MinValue for inserts). - ACL test now uses a trail-returning data source and asserts Good + data on the allow leg. - Node-manager tests: end-only backward open-ended paging, reverse resume cursor, null-prior cursor. - QuestDB updater logs a Warning (tag + time range) when a sample write fails after its trail rows landed. - docs/Historian.md: rolling-upgrade window, IDENTITY-vs-commit ordering, QuestDB cross-node ModifiedId clock ordering.
This commit is contained in:
@@ -673,6 +673,17 @@ modification time and the Part 11 `HistoryUpdateType`. A HistoryReadRaw with `Is
|
||||
so a change and its trail row commit or roll back together. QuestDB has no multi-table transaction, so the trail row is written **before**
|
||||
the change: a crash (or failed sample INSERT) in between leaves an **orphan trail row** describing a change that never landed — never a
|
||||
change without its trail row. Treat a QuestDB trail entry whose sample still shows the prior value as such an orphan.
|
||||
A failed sample write after its trail rows landed logs a **Warning** naming the tag, the row count and the time range, so the orphan
|
||||
can be found.
|
||||
- **Rolling upgrade (SqlServer).** The v2 schema is applied by the first node that upgrades. Until its peer is upgraded too, that
|
||||
not-yet-upgraded node still runs the old build, whose HistoryUpdates write **no trail rows** — silent gaps in the audit trail. Upgrade both
|
||||
nodes of a pair together (stop, upgrade, start both); modifications made by an old-build node in the window are never recorded.
|
||||
- **Paging vs a concurrent HistoryUpdate (SqlServer).** `ModifiedId` is an `IDENTITY`, which orders by allocation, not by commit. A modified
|
||||
read paging at the same moment a HistoryUpdate commits a modification of the **same source timestamp** can have already passed that
|
||||
row's id and so never see it on this pass (a fresh read does). The cursor is exact for a quiescent trail, not a snapshot guarantee.
|
||||
- **QuestDB `ModifiedId` across nodes.** Ids are UTC ticks bumped past the last one issued by that process, so a pair's ids interleave by
|
||||
each node's **wall clock**. Same-source-time modifications made on two nodes order by their clocks (clock skew can reorder them);
|
||||
within one node the order is strict.
|
||||
- **Retention.** The trail ages out on the same **source-time** cutoff as the samples it describes: `SqlServer` purges `hist.SampleModified`
|
||||
per tag alongside `hist.Sample`; QuestDB puts the same TTL on `{p}sample_modified`.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user