Public Access
ci: validate macOS managed behavior on Ubuntu and stabilize shutdown
This commit is contained in:
@@ -3,11 +3,92 @@ using MeetingAssistant.LaunchProfiles;
|
||||
using MeetingAssistant.Transcription;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Runtime.ExceptionServices;
|
||||
|
||||
namespace MeetingAssistant.Tests;
|
||||
|
||||
public sealed class PyannoteDiarizationWarmupHostedServiceTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task HostedServiceStopsSafelyWhenShutdownRequestsOverlap()
|
||||
{
|
||||
const int iterations = 64;
|
||||
const int shutdownCallers = 8;
|
||||
using var applicationLifetime = new CancellationTokenSource();
|
||||
var finalizer = new PyannoteTranscriptFinalizer(
|
||||
new BlockingCommandRunner(),
|
||||
Options.Create(new MeetingAssistantOptions()),
|
||||
NullLogger<PyannoteTranscriptFinalizer>.Instance);
|
||||
using var callersReady = new Barrier(shutdownCallers + 1);
|
||||
var shutdownErrors = new ConcurrentQueue<ExceptionDispatchInfo>();
|
||||
PyannoteDiarizationWarmupHostedService? service = null;
|
||||
var shutdownTasks = Enumerable.Range(0, shutdownCallers)
|
||||
.Select(_ => Task.Factory.StartNew(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
for (var iteration = 0; iteration < iterations; iteration++)
|
||||
{
|
||||
WaitForShutdownCallers();
|
||||
try
|
||||
{
|
||||
service!.StopAsync(CancellationToken.None)
|
||||
.WaitAsync(TimeSpan.FromSeconds(5)).GetAwaiter().GetResult();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
shutdownErrors.Enqueue(ExceptionDispatchInfo.Capture(exception));
|
||||
}
|
||||
WaitForShutdownCallers();
|
||||
if (!shutdownErrors.IsEmpty)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
shutdownErrors.Enqueue(ExceptionDispatchInfo.Capture(exception));
|
||||
}
|
||||
}, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default))
|
||||
.ToArray();
|
||||
|
||||
try
|
||||
{
|
||||
for (var iteration = 0; iteration < iterations; iteration++)
|
||||
{
|
||||
service = new PyannoteDiarizationWarmupHostedService(
|
||||
finalizer,
|
||||
new FakeLaunchProfileOptionsProvider(new MeetingAssistantOptions()),
|
||||
NullLogger<PyannoteDiarizationWarmupHostedService>.Instance);
|
||||
await service.StartAsync(applicationLifetime.Token);
|
||||
WaitForShutdownCallers();
|
||||
WaitForShutdownCallers();
|
||||
if (!shutdownErrors.IsEmpty)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
await Task.WhenAll(shutdownTasks).WaitAsync(TimeSpan.FromSeconds(10));
|
||||
}
|
||||
|
||||
if (shutdownErrors.TryPeek(out var shutdownError))
|
||||
{
|
||||
shutdownError.Throw();
|
||||
}
|
||||
|
||||
void WaitForShutdownCallers()
|
||||
{
|
||||
Assert.True(
|
||||
callersReady.SignalAndWait(TimeSpan.FromSeconds(5)),
|
||||
"Timed out coordinating overlapping shutdown requests.");
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HostedServiceWarmsEnabledValidationRuntimeWithoutBlockingStartup()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user