Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -925,8 +925,8 @@ jobs:
#
# The values are the product's own derivation from the live hypertable count
# (TimescaleSupport.HypertableCount = the 62-collector catalog + collection_log = 63):
# timescaledb.max_background_workers = HypertableCount + 2 = 72
# max_worker_processes = 3 + (HypertableCount + 2) + 8 = 83
# timescaledb.max_background_workers = HypertableCount + 2 = 73
# max_worker_processes = 3 + (HypertableCount + 2) + 8 = 84
# Hard-coded here because a workflow cannot call into the product — so
# CiClusterWorkerSizingTests parses THIS FILE and fails the build if either number stops
# matching the formula as collectors are added, and CiClusterWorkerSizingLiveTests asserts
Expand All @@ -944,8 +944,8 @@ jobs:
Add-Content -Path "$dataDir\postgresql.conf" -Value "shared_preload_libraries = 'timescaledb'"
Add-Content -Path "$dataDir\postgresql.conf" -Value "port = 5541"
Add-Content -Path "$dataDir\postgresql.conf" -Value "listen_addresses = '127.0.0.1'"
Add-Content -Path "$dataDir\postgresql.conf" -Value "timescaledb.max_background_workers = 72"
Add-Content -Path "$dataDir\postgresql.conf" -Value "max_worker_processes = 83"
Add-Content -Path "$dataDir\postgresql.conf" -Value "timescaledb.max_background_workers = 73"
Add-Content -Path "$dataDir\postgresql.conf" -Value "max_worker_processes = 84"
& "$bin\pg_ctl.exe" -D $dataDir -l $logFile -w start
if ($LASTEXITCODE -ne 0) { if (Test-Path $logFile) { Get-Content $logFile -Tail 50 }; throw "pg_ctl start failed ($LASTEXITCODE)" }
& "$bin\createdb.exe" -h 127.0.0.1 -p 5541 -U darling darling
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -437,8 +437,8 @@ jobs:
# customer runs and made scheduler-racing failures luck-of-the-slot instead of reproducible.
# Values are the product's own derivation from the live hypertable count
# (TimescaleSupport.HypertableCount = the 62-collector catalog + collection_log = 63):
# timescaledb.max_background_workers = HypertableCount + 2 = 72
# max_worker_processes = 3 + (HypertableCount + 2) + 8 = 83
# timescaledb.max_background_workers = HypertableCount + 2 = 73
# max_worker_processes = 3 + (HypertableCount + 2) + 8 = 84
# Kept honest by CiClusterWorkerSizingTests (parses this file against the formula) and
# CiClusterWorkerSizingLiveTests (asserts the running cluster serves them). Must configure
# the cluster identically to build.yml's darling-pg job: that guard parses the appended
Expand All @@ -459,8 +459,8 @@ jobs:
Add-Content -Path "$dataDir\postgresql.conf" -Value "shared_preload_libraries = 'timescaledb'"
Add-Content -Path "$dataDir\postgresql.conf" -Value "port = 5541"
Add-Content -Path "$dataDir\postgresql.conf" -Value "listen_addresses = '127.0.0.1'"
Add-Content -Path "$dataDir\postgresql.conf" -Value "timescaledb.max_background_workers = 72"
Add-Content -Path "$dataDir\postgresql.conf" -Value "max_worker_processes = 83"
Add-Content -Path "$dataDir\postgresql.conf" -Value "timescaledb.max_background_workers = 73"
Add-Content -Path "$dataDir\postgresql.conf" -Value "max_worker_processes = 84"
& "$bin\pg_ctl.exe" -D $dataDir -l $logFile -w start
if ($LASTEXITCODE -ne 0) { if (Test-Path $logFile) { Get-Content $logFile -Tail 50 }; throw "pg_ctl start failed ($LASTEXITCODE)" }
& "$bin\createdb.exe" -h 127.0.0.1 -p 5541 -U darling darling
Expand Down
6 changes: 4 additions & 2 deletions Darling/Darling.Tests/CollectionSweepCommandTimeoutTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,10 @@ private static readonly (string File, string Member)[] s_sweepMembers =
/// </summary>
private const int ExpectedSweepCommandSites = 13;

/// <summary>The four COPY writers, counted for the same reason.</summary>
private const int ExpectedCopyWriterSites = 4;
/// <summary>The five COPY writers, counted for the same reason. Five since #3601: RdsLogEventIngestor is
/// RdsDeadlockIngestor's write over the log-event definition, and it was looked at by a person — the same
/// shared start deadline, the same sweep constant on the importer, the same phase stamp.</summary>
private const int ExpectedCopyWriterSites = 5;

/// <summary>
/// Every command shape the landed pins know about, with the type name allowed to carry its namespace:
Expand Down
4 changes: 2 additions & 2 deletions Darling/Darling.Tests/CollectorMeasurementSeamTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ than in whatever order the last cycle happened to touch them. */
[Fact]
public void AnOrdinaryRunLeavesTheColumnNull_ExactlyAsBefore()
{
/* 69 collectors measure nothing. None of them may start writing a note. */
/* 70 collectors measure nothing. None of them may start writing a note. */
Assert.Null(CollectorMeasurementNote.Render(CollectorContext.NoMeasurements));
Assert.Null(CollectorMeasurementNote.Compose(null, CollectorContext.NoMeasurements));
Assert.Null(new CollectorRunResult(12, 34, 56, CollectorContext.NoMeasurements).Note);
Expand Down Expand Up @@ -435,7 +435,7 @@ An argument it CANNOT resolve FAILS rather than being skipped. That is the direc
a skip would silently exempt exactly the case a scanner cannot reason about.

WHAT THIS SCAN CANNOT SEE, stated rather than assumed. It reads PerformanceMonitor.Collectors
only - which is where every definition lives (69 concrete ones, flat, one-to-one with
only - which is where every definition lives (70 concrete ones, flat, one-to-one with
CollectorCatalog.All), but Measure is public, so a HOST could call it and this would not know.
Widening the sweep would be worse rather than better: `.Measure(` is a name this codebase uses
heavily for unrelated things - WPF's UIElement.Measure(Size), and the Compose subsystem's
Expand Down
16 changes: 9 additions & 7 deletions Darling/Darling.Tests/ConsumedTimestampFrameDisciplineTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,12 @@ private enum ClockFrame

/* Floors, so a broken walk cannot report a clean bill of health. Measured on dev at cb208f6a4:
66 Timestamp columns over 69 catalog definitions, 49 of them on SqlServer definitions and 17 on
PostgreSql ones. Pinned exactly rather than as a floor because the whole point is a closed census —
a floor would let a column vanish. */
private const int TimestampColumnCount = 66;
PostgreSql ones; #3601 added pg_log_events.occurred_at, so 67 over 70, 18 PostgreSql. Pinned exactly
rather than as a floor because the whole point is a closed census — a floor would let a column
vanish. */
private const int TimestampColumnCount = 67;
private const int SqlServerTimestampColumnCount = 49;
private const int PostgresTimestampColumnCount = 17;
private const int PostgresTimestampColumnCount = 18;

private static IReadOnlyList<(string Table, string Column, string Collector, CollectorTargetEngine Engine)>
TimestampColumns() =>
Expand All @@ -92,13 +93,14 @@ a floor would let a column vanish. */
/// The census is the catalog's own <see cref="CollectorColumnType.Timestamp"/> columns, and the engine
/// split is <see cref="ICollectorSchemaInfo.TargetEngine"/> rather than a name prefix or a hand list.
///
/// <para>The T-SQL classifier below reaches the SqlServer arm ONLY. The 17 PostgreSQL columns are a
/// <para>The T-SQL classifier below reaches the SqlServer arm ONLY. The 18 PostgreSQL columns are a
/// different provenance mechanism, not a shortfall of this one: PostgreSQL has no
/// <c>column = expression</c> alias form at all (there it is a boolean comparison), so those collectors
/// write <c>expression AS column</c>, and their timestamps arrive as <c>timestamptz</c> normalised in
/// four different spellings — <c>AT TIME ZONE 'UTC'</c> inline, the same inside an interpolated SQL
/// fragment, a bare <c>min()</c> handled in the reader, and two computed entirely in C#
/// (<c>pg_cpu_utilization.sample_time</c>, <c>pg_deadlocks.occurred_at</c>). Counting them here is what
/// fragment, a bare <c>min()</c> handled in the reader, and three computed entirely in C#
/// (<c>pg_cpu_utilization.sample_time</c>, <c>pg_deadlocks.occurred_at</c>, <c>pg_log_events.occurred_at</c>
/// — the last through the same zone check as the deadlock one, #3601). Counting them here is what
/// makes the T-SQL arm's reach a measured fact instead of an implied one.</para>
/// </summary>
[Fact]
Expand Down
4 changes: 4 additions & 0 deletions Darling/Darling.Tests/DarlingPgReadSqlParsesLiveTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ predicate spliced into CurrentLongRunningSessionsSqlTemplate by BuildCurrentLong
in the parse-checked population, so the fragment is verified where it is used. */
"DarlingPgSessionStatesReader.BackupUtilitiesFilter",
"DarlingPgTableBloatReader.StaleStatisticsChurnRatioSql",
/* #3601: the severity CASE expression, spliced into EventsSql so the read and the tool's label-to-rank
mapping share one spelling. A fragment, not a statement; the query it is spliced into IS in the
parse-checked population, so the fragment is verified where it is used. */
"DarlingPgLogEventReader.SeverityRankSql",
};

private static string? ConnectionString => Environment.GetEnvironmentVariable("DARLING_TEST_PG");
Expand Down
32 changes: 16 additions & 16 deletions Darling/Darling.Tests/DeltaFamilyIntervalCompletionRungTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,21 @@ namespace Darling.Tests;
/// over, so the calculator's (delta 0, interval 0) "no delta knowable" marker reaches the store from every
/// family, and the restart seed can rebuild the one key the store could not reproduce.
///
/// <para>This file carries the "I am the top rung" claims that moved off
/// <see cref="DeltaFamilyIntervalColumnsRungTests"/> (V127) when this rung landed, the same handoff that file
/// received from <see cref="SelfDiskWarnGbFloorRungTests"/> (V126) — a fully-migrated store must map to
/// EXACTLY this version, or the viewer's connect-time gate refuses a store that is actually current.</para>
/// <para>The "I am the top rung" claims this file carried moved to <c>PgLogEventsRungTests</c> (V129) when
/// that rung landed, the same handoff this file received from <see cref="DeltaFamilyIntervalColumnsRungTests"/>
/// (V127) and that one from <see cref="SelfDiskWarnGbFloorRungTests"/> (V126). What stays here is the
/// one-rung-behind half: a store carrying this and not V129 maps to 128, which is the honest answer for it
/// and what makes the upgrade banner correct in both directions.</para>
/// </summary>
public sealed class DeltaFamilyIntervalCompletionRungTests
{
private const int RungVersion = 128;

private const int PreviousVersion = 127;

/// <summary>This rung's sentinel ordinal in the viewer probe — the newest, so the last argument.</summary>
/// <summary>This rung's sentinel ordinal in the viewer probe. No longer the last argument — V129 appended
/// its own — so the invariant that outlives the handoff is that the ordinal is FIXED: a later rung
/// appends after it and never shifts it.</summary>
private const int ProbeOrdinal = 103;

private const string IntervalColumn = "sample_interval_seconds";
Expand All @@ -58,7 +61,9 @@ public void TheRungIsRegisteredAtTheTopOfADenseLadder()

Assert.Equal(StorageVersion.SchemaVersion, PgMigrations.Scripts[^1].Version);
Assert.Equal(StorageVersion.SchemaVersion, versions.Max());
Assert.Equal(RungVersion, StorageVersion.SchemaVersion);
/* One below the top since V129 landed; the "RungVersion == StorageVersion.SchemaVersion" half of
the top-arm claim moved to PgLogEventsRungTests with the top. */
Assert.True(RungVersion < StorageVersion.SchemaVersion, "V128 is expected to sit below the ladder's top now that V129 has landed");

Assert.Equal(versions.Distinct().OrderBy(v => v), versions);
}
Expand Down Expand Up @@ -283,7 +288,6 @@ public void TheProbeMapsAFullyMigratedStoreToThisTopRung()

var viewer = RepoFile.ReadRepoFile("Darling", "PerformanceMonitor.Darling.Viewer", "ViewerDataService.cs");
Assert.Contains($"reader.GetBoolean({ProbeOrdinal})", viewer, StringComparison.Ordinal);
Assert.DoesNotContain($"reader.GetBoolean({ProbeOrdinal + 1})", viewer, StringComparison.Ordinal);
Assert.Contains("hasDeltaFamilyIntervalCompletion", viewer, StringComparison.Ordinal);

Assert.Equal(StorageVersion.SchemaVersion, ViewerDataService.RequiredStoreSchemaVersion);
Expand All @@ -292,13 +296,9 @@ public void TheProbeMapsAFullyMigratedStoreToThisTopRung()
.GetMethod("MapProbedSchemaVersion", BindingFlags.NonPublic | BindingFlags.Static)!;
var arity = method.GetParameters().Length;

/* The top rung's sentinel IS the last argument. */
Assert.Equal(ProbeOrdinal, arity - 1);

/* Every sentinel true = a fully-migrated store, which must map to exactly this version. Built by
reflection so the arity tracks the signature. */
var all = Enumerable.Repeat((object)true, arity).ToArray();
Assert.Equal(StorageVersion.SchemaVersion, (int)method.Invoke(null, all)!);
/* This rung's sentinel sits strictly BELOW the last argument now that V129 has appended its own; the
"is the last argument" claim moved to PgLogEventsRungTests with the top. */
Assert.True(ProbeOrdinal < arity - 1, "V128's sentinel is expected to sit below the top rung's now that V129 has landed");

/* This rung's own arm answers for a store that stopped here. Expressed as "false above" rather than
as one named ordinal, so a rung landing on top of this one does not quietly turn this case into a
Expand All @@ -319,8 +319,8 @@ that method — and returns this build's version rather than a literal that coul
Assert.True(previousArm >= 0, "the previous rung's arm is gone, so this pin is comparing against nothing");
Assert.True(thisArm < previousArm, "the V128 arm sits below the previous rung's, so a current store maps one rung low");
Assert.Contains(
"return " + StorageVersion.SchemaVersion.ToString(CultureInfo.InvariantCulture) + ";",
viewer[thisArm..], StringComparison.Ordinal);
"return " + RungVersion.ToString(CultureInfo.InvariantCulture) + ";",
viewer[thisArm..previousArm], StringComparison.Ordinal);
}

/* ---- the writers ---------------------------------------------------------------------------------- */
Expand Down
Loading
Loading