From c243ded1b48a404d1a0168dccc6a404d9324db80 Mon Sep 17 00:00:00 2001 From: Erik Darling <2136037+erikdarlingdata@users.noreply.github.com> Date: Mon, 28 Sep 2026 16:10:56 -0400 Subject: [PATCH 1/2] Pin the scratch store session to UTC in live tests (#4639) --- Darling/Darling.Tests/ScratchPostgres.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Darling/Darling.Tests/ScratchPostgres.cs b/Darling/Darling.Tests/ScratchPostgres.cs index 66a570270f..a120806444 100644 --- a/Darling/Darling.Tests/ScratchPostgres.cs +++ b/Darling/Darling.Tests/ScratchPostgres.cs @@ -48,7 +48,12 @@ public static async Task CreateAsync(string baseConnectionStrin Pooling = false, }; - return new ScratchPostgres(baseConnectionString, databaseName, builder.ConnectionString); + /* Pinned to UTC the way every product store connection is, so a cluster whose default zone is behind UTC + cannot skew timestamp round trips (a chunk's range_end read back through a ::timestamp cast). */ + return new ScratchPostgres( + baseConnectionString, + databaseName, + PerformanceMonitor.Darling.Storage.DarlingStoreConnection.PinSessionTimeZoneUtc(builder.ConnectionString)); } public async ValueTask DisposeAsync() From 860640cb520da1d1f176a3aa3cadc8faf2710806 Mon Sep 17 00:00:00 2001 From: Erik Darling <2136037+erikdarlingdata@users.noreply.github.com> Date: Mon, 28 Sep 2026 16:28:31 -0400 Subject: [PATCH 2/2] The time-zone live test reads the scratch store's own default through an unpinned string (#4645) --- Darling/Darling.Tests/ScratchPostgres.cs | 12 ++++++++++-- .../Darling.Tests/StoreSessionTimeZoneLiveTests.cs | 6 +++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Darling/Darling.Tests/ScratchPostgres.cs b/Darling/Darling.Tests/ScratchPostgres.cs index a120806444..e65d5aa72d 100644 --- a/Darling/Darling.Tests/ScratchPostgres.cs +++ b/Darling/Darling.Tests/ScratchPostgres.cs @@ -23,8 +23,15 @@ internal sealed class ScratchPostgres : IAsyncDisposable public string ConnectionString { get; } - private ScratchPostgres(string adminConnectionString, string databaseName, string connectionString) + /// + /// The same store WITHOUT the session time-zone pin, so a session opened through it reports the database's own + /// default zone. It exists for tests that must observe that default (e.g. to prove the product pin overrides it). + /// + public string UnpinnedConnectionString { get; } + + private ScratchPostgres(string adminConnectionString, string databaseName, string connectionString, string unpinnedConnectionString) { + UnpinnedConnectionString = unpinnedConnectionString; _adminConnectionString = adminConnectionString; DatabaseName = databaseName; ConnectionString = connectionString; @@ -53,7 +60,8 @@ cannot skew timestamp round trips (a chunk's range_end read back through a ::tim return new ScratchPostgres( baseConnectionString, databaseName, - PerformanceMonitor.Darling.Storage.DarlingStoreConnection.PinSessionTimeZoneUtc(builder.ConnectionString)); + PerformanceMonitor.Darling.Storage.DarlingStoreConnection.PinSessionTimeZoneUtc(builder.ConnectionString), + builder.ConnectionString); } public async ValueTask DisposeAsync() diff --git a/Darling/Darling.Tests/StoreSessionTimeZoneLiveTests.cs b/Darling/Darling.Tests/StoreSessionTimeZoneLiveTests.cs index 72e8194d4c..0f446e78b5 100644 --- a/Darling/Darling.Tests/StoreSessionTimeZoneLiveTests.cs +++ b/Darling/Darling.Tests/StoreSessionTimeZoneLiveTests.cs @@ -64,7 +64,7 @@ shares DARLING_TEST_PG's own database. */ /* ALTER DATABASE ... SET only takes effect for sessions opened AFTER it commits, so migrate through a fresh connection rather than the admin one above. */ - await using (var migrate = new NpgsqlConnection(scratch.ConnectionString)) + await using (var migrate = new NpgsqlConnection(scratch.UnpinnedConnectionString)) { await migrate.OpenAsync(ct); await PgMigrations.MigrateAsync(migrate, ct); @@ -72,14 +72,14 @@ fresh connection rather than the admin one above. */ /* The database's own default, UNPINNED — confirms the fixture set up a genuinely non-UTC store before asserting that the product's pin overrides it. */ - await using (var unpinned = new NpgsqlConnection(scratch.ConnectionString)) + await using (var unpinned = new NpgsqlConnection(scratch.UnpinnedConnectionString)) { await unpinned.OpenAsync(ct); Assert.Equal("America/New_York", await ShowTimeZoneAsync(unpinned, ct)); } /* The way the product opens a STORE connection: PinSessionTimeZoneUtc first, then the connection. */ - var pinnedConnectionString = DarlingStoreConnection.PinSessionTimeZoneUtc(scratch.ConnectionString); + var pinnedConnectionString = DarlingStoreConnection.PinSessionTimeZoneUtc(scratch.UnpinnedConnectionString); await using var connection = new NpgsqlConnection(pinnedConnectionString); await connection.OpenAsync(ct);