test: replace final fixed-delay oracles

This commit is contained in:
Erik 2026-08-18 13:12:26 +02:00
parent ad7ebe9425
commit 79a4489e03
6 changed files with 101 additions and 21 deletions

View file

@ -15,7 +15,8 @@ internal static class BakePublicationGuardContract
internal static async ValueTask<PublicationLease> AcquireAsync(
string outputPath,
CancellationToken cancellationToken = default)
CancellationToken cancellationToken = default,
Action? contentionObserved = null)
{
string lockPath = BakePublicationGuardPaths.GetPublishLockPath(
outputPath);
@ -39,6 +40,7 @@ internal static class BakePublicationGuardContract
}
catch (IOException)
{
contentionObserved?.Invoke();
await Task.Delay(RetryDelay, cancellationToken)
.ConfigureAwait(false);
}

View file

@ -22,7 +22,8 @@ internal sealed class InstallerTransactionLease : IAsyncDisposable
internal static async ValueTask<InstallerTransactionLease> AcquireAsync(
string dataDirectory,
CancellationToken cancellationToken = default)
CancellationToken cancellationToken = default,
Action? contentionObserved = null)
{
string lockPath = GetLockPath(dataDirectory);
Directory.CreateDirectory(
@ -46,6 +47,7 @@ internal sealed class InstallerTransactionLease : IAsyncDisposable
}
catch (IOException)
{
contentionObserved?.Invoke();
await Task.Delay(RetryDelay, cancellationToken)
.ConfigureAwait(false);
}

View file

@ -80,6 +80,11 @@ public sealed class LauncherInstaller : ILauncherInstaller
private LauncherInstallRecord? _verifiedRecord;
/// <summary>Test-only observation points for cross-process lease
/// contention. Production leaves both callbacks unset.</summary>
internal Action? TransactionLeaseContentionObservedForTest { get; set; }
internal Action? PublicationLeaseContentionObservedForTest { get; set; }
public LauncherInstaller(
ApplicationPathSet paths,
string bakeExecutablePath,
@ -118,7 +123,8 @@ public sealed class LauncherInstaller : ILauncherInstaller
await using InstallerTransactionLease lease =
await InstallerTransactionLease.AcquireAsync(
_recordStore.DataDirectory,
cancellationToken)
cancellationToken,
TransactionLeaseContentionObservedForTest)
.ConfigureAwait(false);
InstallRecordVerification verification =
await RecoverExistingUnderPublicationGuardAsync(
@ -152,7 +158,8 @@ public sealed class LauncherInstaller : ILauncherInstaller
await using InstallerTransactionLease lease =
await InstallerTransactionLease.AcquireAsync(
_recordStore.DataDirectory,
cancellationToken)
cancellationToken,
TransactionLeaseContentionObservedForTest)
.ConfigureAwait(false);
return await InstallCoreAsync(
datDirectory,
@ -440,7 +447,8 @@ public sealed class LauncherInstaller : ILauncherInstaller
await using BakePublicationGuardContract.PublicationLease publication =
await BakePublicationGuardContract.AcquireAsync(
outputPath,
cancellationToken)
cancellationToken,
PublicationLeaseContentionObservedForTest)
.ConfigureAwait(false);
// Any child whose parent died before it acquired this lock is now
// irrevocably stale. A child already holding the lock must finish its