From 4349dbd27b62610f7d11fb2af7bf370dd3db09c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Sep 2026 21:40:41 +0000 Subject: [PATCH 1/5] Bump Microsoft.NET.Test.Sdk from 17.14.1 to 18.9.0 --- updated-dependencies: - dependency-name: Microsoft.NET.Test.Sdk dependency-version: 18.9.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- test/Pants.Tests/packages.lock.json | 30 ++++++++++++----------------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 4de5194..53bd032 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -11,7 +11,7 @@ - + diff --git a/test/Pants.Tests/packages.lock.json b/test/Pants.Tests/packages.lock.json index 0c0b78c..eac65c5 100644 --- a/test/Pants.Tests/packages.lock.json +++ b/test/Pants.Tests/packages.lock.json @@ -29,12 +29,12 @@ }, "Microsoft.NET.Test.Sdk": { "type": "Direct", - "requested": "[17.14.1, )", - "resolved": "17.14.1", - "contentHash": "HJKqKOE+vshXra2aEHpi2TlxYX7Z9VFYkr+E5rwEvHC8eIXiyO+K9kNm8vmNom3e2rA56WqxU+/N9NJlLGXsJQ==", + "requested": "[18.9.0, )", + "resolved": "18.9.0", + "contentHash": "xIzVXa/VpKXqDWzyC/5Hw8JbFY5u9k3Jc53CpcjBiOXvkQGio484LD9FNwOiGUSMDcYL3Rcw9sNgGi5WrswlPQ==", "dependencies": { - "Microsoft.CodeCoverage": "17.14.1", - "Microsoft.TestPlatform.TestHost": "17.14.1" + "Microsoft.CodeCoverage": "18.9.0", + "Microsoft.TestPlatform.TestHost": "18.9.0" } }, "xunit": { @@ -98,8 +98,8 @@ }, "Microsoft.CodeCoverage": { "type": "Transitive", - "resolved": "17.14.1", - "contentHash": "pmTrhfFIoplzFVbhVwUquT+77CbGH+h4/3mBpdmIlYtBi9nAB+kKI6dN3A/nV4DFi3wLLx/BlHIPK+MkbQ6Tpg==" + "resolved": "18.9.0", + "contentHash": "MtegCIKGuG0r/LCdIjoR1HgzCGIUBhR3aNdbtQpts5vMXQuqBDZ2Jsd2uFKoHFM2XrQV6ZrDf3F5oLi3SLTp8w==" }, "Microsoft.Diagnostics.NETCore.Client": { "type": "Transitive", @@ -180,23 +180,17 @@ }, "Microsoft.TestPlatform.ObjectModel": { "type": "Transitive", - "resolved": "17.14.1", - "contentHash": "xTP1W6Mi6SWmuxd3a+jj9G9UoC850WGwZUps1Wah9r1ZxgXhdJfj1QqDLJkFjHDCvN42qDL2Ps5KjQYWUU0zcQ==" + "resolved": "18.9.0", + "contentHash": "Fz/qXC52VXXopzHj7v2reCKcCqSxkTDCkEDfkNAH0vni/7qK/KLMiEYtRmnUanxO2F2g2zZZ60qCpxF0AF7URA==" }, "Microsoft.TestPlatform.TestHost": { "type": "Transitive", - "resolved": "17.14.1", - "contentHash": "d78LPzGKkJwsJXAQwsbJJ7LE7D1wB+rAyhHHAaODF+RDSQ0NgMjDFkSA1Djw18VrxO76GlKAjRUhl+H8NL8Z+Q==", + "resolved": "18.9.0", + "contentHash": "Oq+Pma/J86aZL72t71bcESvDszDsTjUfl6PIsuDdPoKTHZfNMhKamCfLD5fKx51W/u0KozXtJo2/3fnt0sgPxg==", "dependencies": { - "Microsoft.TestPlatform.ObjectModel": "17.14.1", - "Newtonsoft.Json": "13.0.3" + "Microsoft.TestPlatform.ObjectModel": "18.9.0" } }, - "Newtonsoft.Json": { - "type": "Transitive", - "resolved": "13.0.3", - "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==" - }, "Perfolizer": { "type": "Transitive", "resolved": "0.6.1", From fdba9fc8e45bf51885cca192a388b3d1ca337414 Mon Sep 17 00:00:00 2001 From: Jeff Repanich Date: Fri, 4 Sep 2026 17:56:10 -0400 Subject: [PATCH 2/5] Validate physical WAL timing without disk-speed assumptions --- .github/workflows/ci.yml | 2 +- .../PantsWalDurabilityMetricsTests.cs | 6 ++---- .../WalAppendDelayFailpointHandler.cs | 15 +++++++++++++++ .../Runtime/PantsBackgroundFlushPipelineTests.cs | 4 ++-- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e4fa3d1..42adc09 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ jobs: build-and-test: name: ${{ matrix.os }} runs-on: ${{ matrix.os }} - timeout-minutes: 10 + timeout-minutes: 15 strategy: fail-fast: false matrix: diff --git a/test/Pants.Tests/Observability/PantsWalDurabilityMetricsTests.cs b/test/Pants.Tests/Observability/PantsWalDurabilityMetricsTests.cs index f5e791f..d745bf3 100644 --- a/test/Pants.Tests/Observability/PantsWalDurabilityMetricsTests.cs +++ b/test/Pants.Tests/Observability/PantsWalDurabilityMetricsTests.cs @@ -290,10 +290,8 @@ public async Task ShouldMeasureAppendAndFsyncAtSeparatePhysicalBoundaries() var metrics = await database.Diagnostics.GetRuntimeMetricsAsync(); Assert.True(metrics.WalAppendNanosecondsTotal >= 50_000_000); - Assert.True( - metrics.WalFsyncNanosecondsTotal < metrics.WalAppendNanosecondsTotal, - $"Expected fsync {metrics.WalFsyncNanosecondsTotal} ns to exclude " + - $"the delayed append {metrics.WalAppendNanosecondsTotal} ns."); + Assert.Equal(1, metrics.WalFsyncCount); + Assert.InRange(metrics.WalFsyncNanosecondsTotal, 1, failpoints.FsyncWindowNanoseconds); } static async ValueTask CommitAsync( diff --git a/test/Pants.Tests/Observability/WalAppendDelayFailpointHandler.cs b/test/Pants.Tests/Observability/WalAppendDelayFailpointHandler.cs index 4ce8d80..06942f3 100644 --- a/test/Pants.Tests/Observability/WalAppendDelayFailpointHandler.cs +++ b/test/Pants.Tests/Observability/WalAppendDelayFailpointHandler.cs @@ -1,12 +1,27 @@ +using System.Diagnostics; + namespace Cntryl.Pants.Observability; sealed class WalAppendDelayFailpointHandler(TimeSpan delay) : IFailpointHandler { + long _flushStarted; + + public long FsyncWindowNanoseconds { get; private set; } + public void Hit(Failpoint failpoint) { if (failpoint == Failpoint.MidWalAppend) { Thread.Sleep(delay); } + + if (failpoint == Failpoint.BeforeWalFlush) + { + _flushStarted = Stopwatch.GetTimestamp(); + } + else if (failpoint == Failpoint.AfterWalFlush) + { + FsyncWindowNanoseconds = checked(Stopwatch.GetElapsedTime(_flushStarted).Ticks * 100); + } } } diff --git a/test/Pants.Tests/Runtime/PantsBackgroundFlushPipelineTests.cs b/test/Pants.Tests/Runtime/PantsBackgroundFlushPipelineTests.cs index 8007a1a..9c117a2 100644 --- a/test/Pants.Tests/Runtime/PantsBackgroundFlushPipelineTests.cs +++ b/test/Pants.Tests/Runtime/PantsBackgroundFlushPipelineTests.cs @@ -2623,7 +2623,7 @@ await CommitAsync( { Assert.True(await database.Maintenance.WaitForWriteStallClearAsync( family, - AssertionTimeout)); + BackgroundWorkTimeout)); } } } @@ -2651,7 +2651,7 @@ async Task ReadLayoutAsync() // legitimately take longer than five seconds while eight 132 KiB writes are flushed // alongside repeated manifest reads. await Task.WhenAll(work).WaitAsync(BackgroundWorkTimeout); - await database.Maintenance.FlushAsync(family).AsTask().WaitAsync(AssertionTimeout); + await database.Maintenance.FlushAsync(family).AsTask().WaitAsync(BackgroundWorkTimeout); var layout = await database.Diagnostics.GetStorageLayoutAsync(); var names = layout.Levels.SelectMany(static level => level.Files) From edcc8bd48fc71beef8c8045e8919d1cd9a643e29 Mon Sep 17 00:00:00 2001 From: Jeff Repanich Date: Fri, 4 Sep 2026 18:04:06 -0400 Subject: [PATCH 3/5] Observe crash readiness again after child exit --- test/Pants.Tests/Cloud/PantsCloudCrashRecoveryTests.cs | 3 ++- test/Pants.Tests/Storage/PantsDiskResidentDifferentialTests.cs | 3 ++- .../Transactions/PantsCommitCoalescingCrashRecoveryTests.cs | 3 ++- .../Spill/PantsTransactionSpillCrashRecoveryTests.cs | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/test/Pants.Tests/Cloud/PantsCloudCrashRecoveryTests.cs b/test/Pants.Tests/Cloud/PantsCloudCrashRecoveryTests.cs index 41a52ab..b2f3cda 100644 --- a/test/Pants.Tests/Cloud/PantsCloudCrashRecoveryTests.cs +++ b/test/Pants.Tests/Cloud/PantsCloudCrashRecoveryTests.cs @@ -331,7 +331,8 @@ static async Task WaitForChildReadinessAsync(Process child, string databasePath) var readyPath = Path.Combine(databasePath, ReadyFileName); while (!File.Exists(readyPath)) { - if (child.HasExited) + // The child can publish readiness and exit between these two observations. + if (child.HasExited && !File.Exists(readyPath)) { throw new XunitException( $"Crash child exited with code {child.ExitCode} before readiness."); diff --git a/test/Pants.Tests/Storage/PantsDiskResidentDifferentialTests.cs b/test/Pants.Tests/Storage/PantsDiskResidentDifferentialTests.cs index 0af2018..ca994e8 100644 --- a/test/Pants.Tests/Storage/PantsDiskResidentDifferentialTests.cs +++ b/test/Pants.Tests/Storage/PantsDiskResidentDifferentialTests.cs @@ -312,7 +312,8 @@ static async Task WaitForCrashChildAsync(Process child, string path) var readyPath = Path.Combine(path, CrashReadyFileName); while (!File.Exists(readyPath)) { - if (child.HasExited) + // The child can publish readiness and exit between these two observations. + if (child.HasExited && !File.Exists(readyPath)) { throw new XunitException( $"Differential crash child exited with {child.ExitCode} before readiness."); diff --git a/test/Pants.Tests/Transactions/PantsCommitCoalescingCrashRecoveryTests.cs b/test/Pants.Tests/Transactions/PantsCommitCoalescingCrashRecoveryTests.cs index fa22ee2..1ea83f9 100644 --- a/test/Pants.Tests/Transactions/PantsCommitCoalescingCrashRecoveryTests.cs +++ b/test/Pants.Tests/Transactions/PantsCommitCoalescingCrashRecoveryTests.cs @@ -366,7 +366,8 @@ static async Task WaitForChildReadinessAsync(Process child, string databasePath) { while (!File.Exists(readyPath)) { - if (child.HasExited) + // The child can publish readiness and exit between these two observations. + if (child.HasExited && !File.Exists(readyPath)) { throw new XunitException( $"Coalesced-commit crash child exited with code {child.ExitCode} " + diff --git a/test/Pants.Tests/Transactions/Spill/PantsTransactionSpillCrashRecoveryTests.cs b/test/Pants.Tests/Transactions/Spill/PantsTransactionSpillCrashRecoveryTests.cs index 9ba3f8b..45b847e 100644 --- a/test/Pants.Tests/Transactions/Spill/PantsTransactionSpillCrashRecoveryTests.cs +++ b/test/Pants.Tests/Transactions/Spill/PantsTransactionSpillCrashRecoveryTests.cs @@ -177,7 +177,8 @@ static async Task WaitForChildReadinessAsync(Process child, string databasePath) { while (!File.Exists(readyPath)) { - if (child.HasExited) + // The child can publish readiness and exit between these two observations. + if (child.HasExited && !File.Exists(readyPath)) { throw new XunitException( $"Transaction spill crash child exited with code {child.ExitCode} before readiness."); From 0fa57b8e9214c67a68b050b56229686de4fb5bae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Sep 2026 21:40:14 +0000 Subject: [PATCH 4/5] Bump coverlet.collector from 6.0.4 to 10.0.1 --- updated-dependencies: - dependency-name: coverlet.collector dependency-version: 10.0.1 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- Directory.Packages.props | 2 +- test/Pants.Tests/packages.lock.json | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 53bd032..68d9f5d 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,7 +5,7 @@ - + diff --git a/test/Pants.Tests/packages.lock.json b/test/Pants.Tests/packages.lock.json index eac65c5..c5a34da 100644 --- a/test/Pants.Tests/packages.lock.json +++ b/test/Pants.Tests/packages.lock.json @@ -4,9 +4,9 @@ "net10.0": { "coverlet.collector": { "type": "Direct", - "requested": "[6.0.4, )", - "resolved": "6.0.4", - "contentHash": "lkhqpF8Pu2Y7IiN7OntbsTtdbpR1syMsm2F3IgX6ootA4ffRqWL5jF7XipHuZQTdVuWG/gVAAcf8mjk8Tz0xPg==" + "requested": "[10.0.1, )", + "resolved": "10.0.1", + "contentHash": "27jXSV/0DbVqF5jDrAxuQFZ9oaz6gmG03p8ttxAFk+X0M4woFYj7MoWDLCna5EGLb0CE6OE7X6ZH3Wt5smTtaA==" }, "Microsoft.Extensions.Configuration": { "type": "Direct", From 25cba095bf3bedc0ce58e791f6413cf052327c30 Mon Sep 17 00:00:00 2001 From: Jeff Repanich Date: Fri, 4 Sep 2026 18:05:49 -0400 Subject: [PATCH 5/5] Update System.IO.Hashing to version 10.0.11 and xunit.runner.visualstudio to version 4.0.0 --- Directory.Packages.props | 7 +++---- bench/Pants.Benches/packages.lock.json | 8 ++++---- src/Pants.Core/packages.lock.json | 6 +++--- src/Pants.DependencyInjection/packages.lock.json | 8 ++++---- test/Pants.Tests/packages.lock.json | 14 +++++++------- 5 files changed, 21 insertions(+), 22 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 68d9f5d..34d846d 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -2,7 +2,6 @@ true - @@ -12,9 +11,9 @@ - + - + - + \ No newline at end of file diff --git a/bench/Pants.Benches/packages.lock.json b/bench/Pants.Benches/packages.lock.json index 663418f..9767f85 100644 --- a/bench/Pants.Benches/packages.lock.json +++ b/bench/Pants.Benches/packages.lock.json @@ -161,7 +161,7 @@ "dependencies": { "Cntryl.Pants.Abstractions": "[1.0.0, )", "K4os.Compression.LZ4": "[1.3.8, )", - "System.IO.Hashing": "[10.0.0, )", + "System.IO.Hashing": "[10.0.11, )", "ZstdSharp.Port": "[0.8.8, )" } }, @@ -188,9 +188,9 @@ }, "System.IO.Hashing": { "type": "CentralTransitive", - "requested": "[10.0.0, )", - "resolved": "10.0.0", - "contentHash": "MqSp5IfX9RdWVwTED0WSRL1kZDNB7GlFj64O/NAJs4uO1beBHWEAFLlC7j8Fw/PkI+SUzooLVNvAe4aEkSwsRg==" + "requested": "[10.0.11, )", + "resolved": "10.0.11", + "contentHash": "OzKDcIRkeNJeC8qAsbn8yJXnfTLP1dtkWILe+T56Gf/z+IkAASi7sMqLqJQat08j5z/mRN5xVtoAwbkMNMoBUQ==" }, "ZstdSharp.Port": { "type": "CentralTransitive", diff --git a/src/Pants.Core/packages.lock.json b/src/Pants.Core/packages.lock.json index 985c6d4..5f031e4 100644 --- a/src/Pants.Core/packages.lock.json +++ b/src/Pants.Core/packages.lock.json @@ -10,9 +10,9 @@ }, "System.IO.Hashing": { "type": "Direct", - "requested": "[10.0.0, )", - "resolved": "10.0.0", - "contentHash": "MqSp5IfX9RdWVwTED0WSRL1kZDNB7GlFj64O/NAJs4uO1beBHWEAFLlC7j8Fw/PkI+SUzooLVNvAe4aEkSwsRg==" + "requested": "[10.0.11, )", + "resolved": "10.0.11", + "contentHash": "OzKDcIRkeNJeC8qAsbn8yJXnfTLP1dtkWILe+T56Gf/z+IkAASi7sMqLqJQat08j5z/mRN5xVtoAwbkMNMoBUQ==" }, "ZstdSharp.Port": { "type": "Direct", diff --git a/src/Pants.DependencyInjection/packages.lock.json b/src/Pants.DependencyInjection/packages.lock.json index c14a0d7..488c4e1 100644 --- a/src/Pants.DependencyInjection/packages.lock.json +++ b/src/Pants.DependencyInjection/packages.lock.json @@ -60,7 +60,7 @@ "dependencies": { "Cntryl.Pants.Abstractions": "[1.0.0, )", "K4os.Compression.LZ4": "[1.3.8, )", - "System.IO.Hashing": "[10.0.0, )", + "System.IO.Hashing": "[10.0.11, )", "ZstdSharp.Port": "[0.8.8, )" } }, @@ -82,9 +82,9 @@ }, "System.IO.Hashing": { "type": "CentralTransitive", - "requested": "[10.0.0, )", - "resolved": "10.0.0", - "contentHash": "MqSp5IfX9RdWVwTED0WSRL1kZDNB7GlFj64O/NAJs4uO1beBHWEAFLlC7j8Fw/PkI+SUzooLVNvAe4aEkSwsRg==" + "requested": "[10.0.11, )", + "resolved": "10.0.11", + "contentHash": "OzKDcIRkeNJeC8qAsbn8yJXnfTLP1dtkWILe+T56Gf/z+IkAASi7sMqLqJQat08j5z/mRN5xVtoAwbkMNMoBUQ==" }, "ZstdSharp.Port": { "type": "CentralTransitive", diff --git a/test/Pants.Tests/packages.lock.json b/test/Pants.Tests/packages.lock.json index c5a34da..6e67430 100644 --- a/test/Pants.Tests/packages.lock.json +++ b/test/Pants.Tests/packages.lock.json @@ -50,9 +50,9 @@ }, "xunit.runner.visualstudio": { "type": "Direct", - "requested": "[3.1.4, )", - "resolved": "3.1.4", - "contentHash": "5mj99LvCqrq3CNi06xYdyIAXOEh+5b33F2nErCzI5zWiDdLHXiPXEWFSUAF8zlIv0ZWqjZNCwHTQeAPYbF3pCg==" + "requested": "[4.0.0, )", + "resolved": "4.0.0", + "contentHash": "kzLFyBYUnoidpGOXvpNOfIo8C92gVgVR6X8ncHwhcrDYugiOut5rrhDkr0L3cWHd7J2pKXf6LgaeXoBBDlx1ag==" }, "BenchmarkDotNet.Annotations": { "type": "Transitive", @@ -277,7 +277,7 @@ "dependencies": { "Cntryl.Pants.Abstractions": "[1.0.0, )", "K4os.Compression.LZ4": "[1.3.8, )", - "System.IO.Hashing": "[10.0.0, )", + "System.IO.Hashing": "[10.0.11, )", "ZstdSharp.Port": "[0.8.8, )" } }, @@ -334,9 +334,9 @@ }, "System.IO.Hashing": { "type": "CentralTransitive", - "requested": "[10.0.0, )", - "resolved": "10.0.0", - "contentHash": "MqSp5IfX9RdWVwTED0WSRL1kZDNB7GlFj64O/NAJs4uO1beBHWEAFLlC7j8Fw/PkI+SUzooLVNvAe4aEkSwsRg==" + "requested": "[10.0.11, )", + "resolved": "10.0.11", + "contentHash": "OzKDcIRkeNJeC8qAsbn8yJXnfTLP1dtkWILe+T56Gf/z+IkAASi7sMqLqJQat08j5z/mRN5xVtoAwbkMNMoBUQ==" }, "ZstdSharp.Port": { "type": "CentralTransitive",