Skip to content

Darling's get_pvs_stats trend drew an unmeasured pass as 0 MB: the point is now null with pvs_measured beside it, the same two keys Lite's twin has carried since #3666, and a measured zero is still a zero (#3653) - #3682

Merged
erikdarlingdata merged 1 commit into
devfrom
fix/3653-pvs-trend-null
Sep 19, 2026

Conversation

@erikdarlingdata

Copy link
Copy Markdown
Owner

Part of #3653 (the "PvsTrendPoint.PvsSizeMb coerces NULL to 0 on the top-5 trend series (both SKUs, rare)" clause under the viewer-calendar item; #3666 landed Lite's half and the Darling Viewer's chart, this is the Darling MCP half). Does not close it.

The lie

get_pvs_stats with trend_hours_back > 0 returns the top-5 databases' PVS size series. On Darling the reader behind it (DarlingPvsReader.GetPvsTrendAsync) read persistent_version_store_size_mb as a bare double with reader.IsDBNull(2) ? 0 : …. A collection on which sys.dm_tran_persistent_version_store_stats reported no size for a database — the collector ran, the row exists, the size is NULL — was published as pvs_size_mb: 0: a real zero, the healthy fully-cleaned state, drawn into a series that had a gap. Beside a neighbouring 912 MB point that reads as a cliff, and the tool's own description sends a caller here "when ADR cleanup looks stuck" — a fabricated drop to zero is the worst possible artefact on that question.

The latest-snapshot rows were already right (#3541 A12 made PvsStatsRow.PvsSizeMb nullable with a pvs_measured flag and a pct_of_database_reason); the trend arm was the one place the NULL still became a number. Lite's shared reader and tool got the fix in #3666 (double? PvsSizeMb, pvs_measured per point, the FinOps chart skipping unmeasured points); the Darling Viewer's chart reader also landed there (it skips the NULL row at read time). The Darling service reader — the one the MCP tool and the web read through — did not.

The fix

DarlingPvsReader.PvsTrendPoint.PvsSizeMb becomes double? and the trend read keeps a NULL as null. The tool's trend point gains pvs_measured = p.PvsSizeMb.HasValue beside pvs_size_mb — the same two keys, spelled identically, that Lite's McpPvsTools.cs has carried since #3666, so the cross-SKU payload shape holds. A measured 0 MB still travels as 0 with pvs_measured: true; pct_of_database for an unmeasured point was already null (the SQL's CASE divides a NULL numerator to NULL) and stays so.

The tool description is untouched: it is byte-identical to Lite's and already says "pvs_measured says whether the DMV reported a size for that database at all".

What it does NOT do

Tests

McpZeroIsAMeasurementTests (§5, PVS):

  • ThePvsShare_DividesAnyMeasuredSize_AndSaysWhyWhenItCannot (Theory over both SKUs' tool files) now also asserts pvs_measured = p.PvsSizeMb.HasValue, in the trend arm — Lite already had it, Darling now does.
  • TheDarlingPvsTrendReader_CarriesAnUnmeasuredPointAsNull_NeverZero — the record signature is double? PvsSizeMb, and the trend read is IsDBNull(2) ? null, never ? 0 (the same two shapes ViewerTrendRoutingPortTests.PvsTrend_BothSkus_NeverPlotAnUnmeasuredPointAsZero pins on Lite's shared reader).
  • BothSkusPvsDescriptions_StayByteIdentical_AndTeachPvsMeasured — the two get_pvs_stats descriptions are equal and teach the flag.
  • McpZeroIsAMeasurementLivePostgresTests.AMeasuredZeroPvs_IsAMeasurement_AndAnUnmeasuredOneSaysSo — extended: an EARLIER pass is seeded on which BusyDb was unmeasured; trend_hours_back: 24 must return BusyDb as [null/unmeasured, 912.82/measured], CleanDb as two measured zeros with pct_of_database 0.00, UnreadDb as two nulls.

Executed on this Mac via the mactest harness against timescale/timescaledb:2.28.1-pg18: McpZeroIsAMeasurementTests + McpZeroIsAMeasurementLivePostgresTests (24 tests) plus the harness's other classes — 83 total, 0 failed, 0 skipped. Positive control: with the reader reverted to IsDBNull(2) ? 0 both the source pin and the live test fail (Expected: Null, Actual: Number on the earlier BusyDb point). Service and Darling.Tests build -c Release -p:EnableWindowsTargeting=true with 0 warnings.

…lingPvsReader read persistent_version_store_size_mb as a bare double with IsDBNull ? 0, so a collection on which the DMV reported no size for a database became a real zero in the top-5 series — a cliff in a series that had none. The point is now null with a pvs_measured flag beside it, the same two keys Lite's twin has carried since #3666, and a measured 0 MB still travels as 0 (#3653)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant