diff --git a/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Configurations/AuditLogEntityTypeConfiguration.cs b/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Configurations/AuditLogEntityTypeConfiguration.cs index 217686ad..221418f2 100644 --- a/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Configurations/AuditLogEntityTypeConfiguration.cs +++ b/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Configurations/AuditLogEntityTypeConfiguration.cs @@ -8,8 +8,11 @@ namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Configurations; /// /// Maps the C5 (Task 2.5) persistence shape to the central /// dbo.AuditLog table: the 10 canonical ZB.MOM.WW.Audit.AuditEvent columns -/// (writable) plus six read-only, server-side persisted computed columns derived -/// from DetailsJson via JSON_VALUE. The computed-column SQL and the index +/// (writable) plus six read-only, server-side computed columns derived from +/// DetailsJson via JSON_VALUE — five PERSISTED (Kind/Status/ +/// SourceSiteId/ExecutionId/ParentExecutionId) plus IngestedAtUtc +/// which is computed but NOT persisted (SQL Server forbids PERSISTED on its non-deterministic +/// SWITCHOFFSET cast). The computed-column SQL and the index /// set here mirror the CollapseAuditLogToCanonical migration's /// dbo.AuditLog_v2 DDL byte-for-byte — keep them in sync. /// diff --git a/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Migrations/20260602174346_CollapseAuditLogToCanonical.cs b/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Migrations/20260602174346_CollapseAuditLogToCanonical.cs index d1ecac0e..2478e243 100644 --- a/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Migrations/20260602174346_CollapseAuditLogToCanonical.cs +++ b/src/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase/Migrations/20260602174346_CollapseAuditLogToCanonical.cs @@ -46,8 +46,8 @@ namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Migrations protected override void Up(MigrationBuilder migrationBuilder) { // 1) Create dbo.AuditLog_v2 on the PRESERVED partition scheme. Ten - // canonical columns first (ordinal-stable), then the six persisted - // computed columns. The clustered PK is composite {EventId, + // canonical columns first (ordinal-stable), then the six computed + // columns (five PERSISTED + IngestedAtUtc non-persisted). The clustered PK is composite {EventId, // OccurredAtUtc} (partition-aligned). The computed-column expressions // here are the single source of truth that AuditLogEntityTypeConfiguration // and SwitchOutPartitionAsync's staging table must mirror exactly. diff --git a/tests/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests/Migrations/CollapseAuditLogToCanonicalMigrationTests.cs b/tests/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests/Migrations/CollapseAuditLogToCanonicalMigrationTests.cs index 36d07b5a..03302319 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests/Migrations/CollapseAuditLogToCanonicalMigrationTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests/Migrations/CollapseAuditLogToCanonicalMigrationTests.cs @@ -6,7 +6,7 @@ namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests.Migrations; /// /// C7 (Task 2.5) data-projection tests for the CollapseAuditLogToCanonical -/// migration. Verifies that the canonical column layout and six persisted computed +/// migration. Verifies that the canonical column layout and the five persisted computed /// columns are correct after the migration has been applied: /// /// Action = "{Channel}.{Kind}" per . @@ -17,9 +17,10 @@ namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests.Migrations; /// else → Success. /// Empty Actor maps to NULL. /// DetailsJson produced by round-trips -/// correctly and the six persisted computed columns (Kind, Status, +/// correctly and the five persisted computed columns (Kind, Status, /// SourceSiteId, ExecutionId, ParentExecutionId) resolve to -/// the expected values via JSON_VALUE. +/// the expected values via JSON_VALUE (IngestedAtUtc is computed but +/// non-persisted, so not asserted here). /// /// /// @@ -30,7 +31,7 @@ namespace ZB.MOM.WW.ScadaBridge.ConfigurationDatabase.Tests.Migrations; /// seed, apply C5), the tests insert rows directly into the canonical table using /// — the same codec the migration's /// FOR JSON PATH, WITHOUT_ARRAY_WRAPPER projection is designed to match — -/// and verify that all six computed columns resolve correctly from DetailsJson. +/// and verify that the five persisted computed columns resolve correctly from DetailsJson. /// This validates the computed-column SQL expressions that are the source of truth /// for both the live table and SwitchOutPartitionAsync's staging table. /// diff --git a/tests/ZB.MOM.WW.ScadaBridge.PerformanceTests/AuditLog/HotPathLatencyTests.cs b/tests/ZB.MOM.WW.ScadaBridge.PerformanceTests/AuditLog/HotPathLatencyTests.cs index 70458f43..f033e9fa 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.PerformanceTests/AuditLog/HotPathLatencyTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.PerformanceTests/AuditLog/HotPathLatencyTests.cs @@ -29,8 +29,8 @@ namespace ZB.MOM.WW.ScadaBridge.PerformanceTests.AuditLog; /// C7 re-baseline rationale. The canonical /// works on a single DetailsJson bag (one JSON parse + one re-serialize per /// call) whereas the former typed-field approach touched many individual -/// fields. Empirical measurements on Apple M-series (2026-06-02, Release build, -/// 5 000 iterations after 500 warm-ups): +/// fields. Empirical calibration measurements on Apple M-series (2026-06-02, Release build; +/// the CI test itself runs MeasureIterations=2 000 after WarmupIterations=200): /// /// 4 KB body (2 body-regex matches + truncation): p50 ≈ 13 µs, p95 ≈ 14 µs. /// Small DetailsJson, no redactors (JSON parse + rewrite only): p50 ≈ 1.5 µs, p95 ≈ 2 µs.