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
45 changes: 31 additions & 14 deletions Darling/Darling.Tests/RawGatePerSlotSourceFloorLiveTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,38 @@ public sealed class RawGatePerSlotSourceFloorLiveTests
"Set DARLING_TEST_PG to a Postgres connection string (with TimescaleDB installed) to run the live #4300 per-slot floor pins.");

var scratch = await ScratchPostgres.CreateAsync(baseConnectionString!, default);

var connectionString = new NpgsqlConnectionStringBuilder(scratch.ConnectionString) { MaxAutoPrepare = 0 }.ConnectionString;
var connection = new NpgsqlConnection(connectionString);
await connection.OpenAsync();
await PgMigrations.MigrateAsync(connection, default);

var enabled = await TimescaleSupport.TryEnableAsync(connection, null, default);
Assert.SkipWhen(!enabled, "The live #4300 per-slot floor pins need TimescaleDB.");
await TimescaleSupport.ConvertToHypertablesAsync(connection, null, default);
await TimescaleSupport.EnsureContinuousAggregatesAsync(connection, null, default);

await using (var stop = new NpgsqlCommand("SELECT _timescaledb_functions.stop_background_workers()", connection) { CommandTimeout = SetupTimeoutSeconds })
NpgsqlConnection? connection = null;
/* A skip (no TimescaleDB) or a failed setup throws before the caller owns the store, so the opener drops it
here. Left alone it would survive to the process-exit drain, which the test runner waits only 10 s for. */
try
{
await stop.ExecuteNonQueryAsync();
var connectionString = new NpgsqlConnectionStringBuilder(scratch.ConnectionString) { MaxAutoPrepare = 0 }.ConnectionString;
connection = new NpgsqlConnection(connectionString);
await connection.OpenAsync();
await PgMigrations.MigrateAsync(connection, default);

var enabled = await TimescaleSupport.TryEnableAsync(connection, null, default);
Assert.SkipWhen(!enabled, "The live #4300 per-slot floor pins need TimescaleDB.");
await TimescaleSupport.ConvertToHypertablesAsync(connection, null, default);
await TimescaleSupport.EnsureContinuousAggregatesAsync(connection, null, default);

await using (var stop = new NpgsqlCommand("SELECT _timescaledb_functions.stop_background_workers()", connection) { CommandTimeout = SetupTimeoutSeconds })
{
await stop.ExecuteNonQueryAsync();
}

return (connection, scratch);
}
catch
{
if (connection is not null)
{
await connection.DisposeAsync();
}

return (connection, scratch);
await scratch.DisposeAsync();
throw;
}
}

/// <summary>Hour 0 (the raw floor) holds ONLY CPU-unknown rows: <c>delta_worker_time = NULL</c>,
Expand Down Expand Up @@ -139,6 +154,7 @@ public async Task FloorCase_DbSlotOwnFloorSkipsCpuUnknownHour_Covered()
{
await LiveStoreCleanup.RunAsync(scratch.ConnectionString, bodySucceeded, (_, _) => Task.CompletedTask);
await connection.DisposeAsync();
await scratch.DisposeAsync();
}
}

Expand Down Expand Up @@ -177,6 +193,7 @@ public async Task QueryGrainCase_HoleAtOwnFloor_ShortThenCovered()
{
await LiveStoreCleanup.RunAsync(scratch.ConnectionString, bodySucceeded, (_, _) => Task.CompletedTask);
await connection.DisposeAsync();
await scratch.DisposeAsync();
}
}
}
42 changes: 30 additions & 12 deletions Darling/Darling.Tests/RawPurgeConvergeLiveTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,38 @@ public sealed class RawPurgeConvergeLiveTests
"Set DARLING_TEST_PG to a Postgres connection string (with TimescaleDB installed) to run the live #4391 converge pins.");

var scratch = await ScratchPostgres.CreateAsync(baseConnectionString!, default);
NpgsqlConnection? connection = null;
/* A skip (no TimescaleDB) or a failed setup throws before the caller owns the store, so the opener drops it
here. Left alone it would survive to the process-exit drain, which the test runner waits only 10 s for. */
try
{
var connectionString = new NpgsqlConnectionStringBuilder(scratch.ConnectionString) { MaxAutoPrepare = 0 }.ConnectionString;
connection = new NpgsqlConnection(connectionString);
await connection.OpenAsync();
await PgMigrations.MigrateAsync(connection, default);

var connectionString = new NpgsqlConnectionStringBuilder(scratch.ConnectionString) { MaxAutoPrepare = 0 }.ConnectionString;
var connection = new NpgsqlConnection(connectionString);
await connection.OpenAsync();
await PgMigrations.MigrateAsync(connection, default);
var enabled = await TimescaleSupport.TryEnableAsync(connection, null, default);
Assert.SkipWhen(!enabled, "The live #4391 converge pins need TimescaleDB.");
await TimescaleSupport.ConvertToHypertablesAsync(connection, null, default);
await TimescaleSupport.EnsureContinuousAggregatesAsync(connection, null, default);

var enabled = await TimescaleSupport.TryEnableAsync(connection, null, default);
Assert.SkipWhen(!enabled, "The live #4391 converge pins need TimescaleDB.");
await TimescaleSupport.ConvertToHypertablesAsync(connection, null, default);
await TimescaleSupport.EnsureContinuousAggregatesAsync(connection, null, default);
await using (var stop = new NpgsqlCommand("SELECT _timescaledb_functions.stop_background_workers()", connection) { CommandTimeout = SetupTimeoutSeconds })
{
await stop.ExecuteNonQueryAsync();
}

await using (var stop = new NpgsqlCommand("SELECT _timescaledb_functions.stop_background_workers()", connection) { CommandTimeout = SetupTimeoutSeconds })
{
await stop.ExecuteNonQueryAsync();
return (connection, scratch);
}
catch
{
if (connection is not null)
{
await connection.DisposeAsync();
}

return (connection, scratch);
await scratch.DisposeAsync();
throw;
}
}

private static async Task ArmRawJobAsync(NpgsqlConnection connection, string relation)
Expand Down Expand Up @@ -195,6 +210,7 @@ await LiveStoreCleanup.RunAsync(scratch.ConnectionString, bodySucceeded, async (
await batch.RemoveRetentionPolicyAsync(Raw, cleanupCt);
});
await connection.DisposeAsync();
await scratch.DisposeAsync();
}
}

Expand Down Expand Up @@ -253,6 +269,7 @@ await LiveStoreCleanup.RunAsync(scratch.ConnectionString, bodySucceeded, async (
await batch.RemoveRetentionPolicyAsync(Raw, cleanupCt);
});
await connection.DisposeAsync();
await scratch.DisposeAsync();
}
}

Expand Down Expand Up @@ -336,6 +353,7 @@ await LiveStoreCleanup.RunAsync(scratch.ConnectionString, bodySucceeded, async (
await batch.RemoveRetentionPolicyAsync(Raw, cleanupCt);
});
await connection.DisposeAsync();
await scratch.DisposeAsync();
}
}

Expand Down
50 changes: 33 additions & 17 deletions Darling/Darling.Tests/RawPurgeTriggerGateErrorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,26 +60,41 @@ public void RepairEpochStampAllowed_TrueOnlyWithZeroFailures()
"Set DARLING_TEST_PG to a Postgres connection string (with TimescaleDB installed) to run the live #4391 gate_error pin.");

var scratch = await ScratchPostgres.CreateAsync(baseConnectionString!, default);

/* Max Auto Prepare=0: RunRetentionPurgeJobSql is a multi-statement string run through NpgsqlCommand,
and this rig's connection reruns other multi-statement SQL enough times over its life that
Npgsql's default auto-prepare threshold can trigger on it — same reasoning as RawPurgeTriggerLiveTests. */
var connectionString = new NpgsqlConnectionStringBuilder(scratch.ConnectionString) { MaxAutoPrepare = 0 }.ConnectionString;
var connection = new NpgsqlConnection(connectionString);
await connection.OpenAsync();
await PgMigrations.MigrateAsync(connection, default);

var enabled = await TimescaleSupport.TryEnableAsync(connection, null, default);
Assert.SkipWhen(!enabled, "The live #4391 gate_error pin needs TimescaleDB.");
await TimescaleSupport.ConvertToHypertablesAsync(connection, null, default);
await TimescaleSupport.EnsureContinuousAggregatesAsync(connection, null, default);

await using (var stop = new NpgsqlCommand("SELECT _timescaledb_functions.stop_background_workers()", connection) { CommandTimeout = SetupTimeoutSeconds })
NpgsqlConnection? connection = null;
/* A skip (no TimescaleDB) or a failed setup throws before the caller owns the store, so the opener drops it
here. Left alone it would survive to the process-exit drain, which the test runner waits only 10 s for. */
try
{
await stop.ExecuteNonQueryAsync();
/* Max Auto Prepare=0: RunRetentionPurgeJobSql is a multi-statement string run through NpgsqlCommand,
and this rig's connection reruns other multi-statement SQL enough times over its life that
Npgsql's default auto-prepare threshold can trigger on it — same reasoning as RawPurgeTriggerLiveTests. */
var connectionString = new NpgsqlConnectionStringBuilder(scratch.ConnectionString) { MaxAutoPrepare = 0 }.ConnectionString;
connection = new NpgsqlConnection(connectionString);
await connection.OpenAsync();
await PgMigrations.MigrateAsync(connection, default);

var enabled = await TimescaleSupport.TryEnableAsync(connection, null, default);
Assert.SkipWhen(!enabled, "The live #4391 gate_error pin needs TimescaleDB.");
await TimescaleSupport.ConvertToHypertablesAsync(connection, null, default);
await TimescaleSupport.EnsureContinuousAggregatesAsync(connection, null, default);

await using (var stop = new NpgsqlCommand("SELECT _timescaledb_functions.stop_background_workers()", connection) { CommandTimeout = SetupTimeoutSeconds })
{
await stop.ExecuteNonQueryAsync();
}

return (connection, scratch);
}
catch
{
if (connection is not null)
{
await connection.DisposeAsync();
}

return (connection, scratch);
await scratch.DisposeAsync();
throw;
}
}

private static async Task<long> ReadPostmasterEpochAsync(NpgsqlConnection connection)
Expand Down Expand Up @@ -246,6 +261,7 @@ await LiveStoreCleanup.RunAsync(scratch.ConnectionString, bodySucceeded, async (
await batch.RemoveRetentionPolicyAsync(Raw, cleanupCt);
});
await connection.DisposeAsync();
await scratch.DisposeAsync();
}
}
}
62 changes: 43 additions & 19 deletions Darling/Darling.Tests/RawPurgeTriggerLiveTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,28 +40,43 @@ public sealed class RawPurgeTriggerLiveTests
"Set DARLING_TEST_PG to a Postgres connection string (with TimescaleDB installed) to run the live #4299 trigger pins.");

var scratch = await ScratchPostgres.CreateAsync(baseConnectionString!, default);

/* Max Auto Prepare=0: RunRetentionPurgeJobSql is a multi-statement string (BEGIN; ...; COMMIT;) run
through NpgsqlCommand, and this rig's connection reruns other multi-statement SQL enough times over
its life that Npgsql's default auto-prepare threshold can trigger on it, which Npgsql rejects with
42601 ("cannot insert multiple commands into a prepared statement") — a client-side caching
artifact of this test's connection reuse, not a product behavior. */
var connectionString = new NpgsqlConnectionStringBuilder(scratch.ConnectionString) { MaxAutoPrepare = 0 }.ConnectionString;
var connection = new NpgsqlConnection(connectionString);
await connection.OpenAsync();
await PgMigrations.MigrateAsync(connection, default);

var enabled = await TimescaleSupport.TryEnableAsync(connection, null, default);
Assert.SkipWhen(!enabled, "The live #4299 trigger pins need TimescaleDB.");
await TimescaleSupport.ConvertToHypertablesAsync(connection, null, default);
await TimescaleSupport.EnsureContinuousAggregatesAsync(connection, null, default);

await using (var stop = new NpgsqlCommand("SELECT _timescaledb_functions.stop_background_workers()", connection) { CommandTimeout = SetupTimeoutSeconds })
NpgsqlConnection? connection = null;
/* A skip (no TimescaleDB) or a failed setup throws before the caller owns the store, so the opener drops it
here. Left alone it would survive to the process-exit drain, which the test runner waits only 10 s for. */
try
{
await stop.ExecuteNonQueryAsync();
/* Max Auto Prepare=0: RunRetentionPurgeJobSql is a multi-statement string (BEGIN; ...; COMMIT;) run
through NpgsqlCommand, and this rig's connection reruns other multi-statement SQL enough times over
its life that Npgsql's default auto-prepare threshold can trigger on it, which Npgsql rejects with
42601 ("cannot insert multiple commands into a prepared statement") — a client-side caching
artifact of this test's connection reuse, not a product behavior. */
var connectionString = new NpgsqlConnectionStringBuilder(scratch.ConnectionString) { MaxAutoPrepare = 0 }.ConnectionString;
connection = new NpgsqlConnection(connectionString);
await connection.OpenAsync();
await PgMigrations.MigrateAsync(connection, default);

var enabled = await TimescaleSupport.TryEnableAsync(connection, null, default);
Assert.SkipWhen(!enabled, "The live #4299 trigger pins need TimescaleDB.");
await TimescaleSupport.ConvertToHypertablesAsync(connection, null, default);
await TimescaleSupport.EnsureContinuousAggregatesAsync(connection, null, default);

await using (var stop = new NpgsqlCommand("SELECT _timescaledb_functions.stop_background_workers()", connection) { CommandTimeout = SetupTimeoutSeconds })
{
await stop.ExecuteNonQueryAsync();
}

return (connection, scratch);
}
catch
{
if (connection is not null)
{
await connection.DisposeAsync();
}

return (connection, scratch);
await scratch.DisposeAsync();
throw;
}
}

private static async Task<long> ReadPostmasterEpochAsync(NpgsqlConnection connection)
Expand Down Expand Up @@ -190,6 +205,7 @@ await LiveStoreCleanup.RunAsync(scratch.ConnectionString, bodySucceeded, async (
await batch.RemoveRetentionPolicyAsync(Raw, cleanupCt);
});
await connection.DisposeAsync();
await scratch.DisposeAsync();
}
}

Expand Down Expand Up @@ -245,6 +261,7 @@ await LiveStoreCleanup.RunAsync(scratch.ConnectionString, bodySucceeded, async (
await batch.RemoveRetentionPolicyAsync(Raw, cleanupCt);
});
await connection.DisposeAsync();
await scratch.DisposeAsync();
}
}

Expand Down Expand Up @@ -296,6 +313,7 @@ await LiveStoreCleanup.RunAsync(scratch.ConnectionString, bodySucceeded, async (
await batch.RemoveRetentionPolicyAsync(Raw, cleanupCt);
});
await connection.DisposeAsync();
await scratch.DisposeAsync();
}
}

Expand Down Expand Up @@ -355,6 +373,7 @@ await LiveStoreCleanup.RunAsync(scratch.ConnectionString, bodySucceeded, async (
await batch.RemoveRetentionPolicyAsync(Raw, cleanupCt);
});
await connection.DisposeAsync();
await scratch.DisposeAsync();
}
}

Expand Down Expand Up @@ -420,6 +439,7 @@ await LiveStoreCleanup.RunAsync(scratch.ConnectionString, bodySucceeded, async (
await batch.RemoveRetentionPolicyAsync(Raw, cleanupCt);
});
await connection.DisposeAsync();
await scratch.DisposeAsync();
}
}

Expand Down Expand Up @@ -472,6 +492,7 @@ await LiveStoreCleanup.RunAsync(scratch.ConnectionString, bodySucceeded, async (
await batch.RemoveRetentionPolicyAsync(Raw, cleanupCt);
});
await connection.DisposeAsync();
await scratch.DisposeAsync();
}
}

Expand Down Expand Up @@ -559,6 +580,7 @@ await LiveStoreCleanup.RunAsync(scratch.ConnectionString, bodySucceeded, async (
await batch.RemoveRetentionPolicyAsync(Raw, cleanupCt);
});
await connection.DisposeAsync();
await scratch.DisposeAsync();
}
}

Expand Down Expand Up @@ -640,6 +662,7 @@ await LiveStoreCleanup.RunAsync(scratch.ConnectionString, bodySucceeded, async (
await batch.RemoveRetentionPolicyAsync(Raw, cleanupCt);
});
await connection.DisposeAsync();
await scratch.DisposeAsync();
}
}

Expand Down Expand Up @@ -783,6 +806,7 @@ await LiveStoreCleanup.RunAsync(scratch.ConnectionString, bodySucceeded, async (
var batch = new LiveCleanupBatch(cleanup);
await batch.RemoveRetentionPolicyAsync(Raw, cleanupCt);
});
await scratch.DisposeAsync();
}
}
}
Loading
Loading