This commit is contained in:
David Wengier 2024-11-21 09:54:13 +11:00
Родитель 69388cdace
Коммит 4357c314b1
3 изменённых файлов: 34 добавлений и 14 удалений

Просмотреть файл

@ -17,7 +17,8 @@ internal class AsyncBatchingWorkQueue<TItem>(
TimeSpan delay,
Func<ImmutableArray<TItem>, CancellationToken, ValueTask> processBatchAsync,
IEqualityComparer<TItem>? equalityComparer,
CancellationToken cancellationToken) : AsyncBatchingWorkQueue<TItem, VoidResult>(delay, Convert(processBatchAsync), equalityComparer, cancellationToken)
Action? idleAction,
CancellationToken cancellationToken) : AsyncBatchingWorkQueue<TItem, VoidResult>(delay, Convert(processBatchAsync), equalityComparer, idleAction, cancellationToken)
{
public AsyncBatchingWorkQueue(
TimeSpan delay,
@ -30,6 +31,19 @@ internal class AsyncBatchingWorkQueue<TItem>(
{
}
public AsyncBatchingWorkQueue(
TimeSpan delay,
Func<ImmutableArray<TItem>, CancellationToken, ValueTask> processBatchAsync,
IEqualityComparer<TItem>? equalityComparer,
CancellationToken cancellationToken)
: this(delay,
processBatchAsync,
equalityComparer,
idleAction: null,
cancellationToken)
{
}
private static Func<ImmutableArray<TItem>, CancellationToken, ValueTask<VoidResult>> Convert(Func<ImmutableArray<TItem>, CancellationToken, ValueTask> processBatchAsync)
=> async (items, ct) =>
{

Просмотреть файл

@ -31,15 +31,6 @@ namespace Microsoft.AspNetCore.Razor.Utilities;
/// </summary>
internal class AsyncBatchingWorkQueue<TItem, TResult>
{
/// <summary>
/// Fired when all batches have finished being processed, and the queue is waiting for an AddWork call.
/// </summary>
/// <remarks>
/// This is a best-effort signal with no guarantee that more work won't be queued, and hence the queue
/// going non-idle, immediately after (or during!) the event firing.
/// </remarks>
public event EventHandler? Idle;
/// <summary>
/// Delay we wait after finishing the processing of one batch and starting up on then.
/// </summary>
@ -50,6 +41,15 @@ internal class AsyncBatchingWorkQueue<TItem, TResult>
/// </summary>
private readonly IEqualityComparer<TItem>? _equalityComparer;
/// <summary>
/// Fired when all batches have finished being processed, and the queue is waiting for an AddWork call.
/// </summary>
/// <remarks>
/// This is a best-effort signal with no guarantee that more work won't be queued, and hence the queue
/// going non-idle, immediately after (or during!) the event firing.
/// </remarks>
private readonly Action? _idleAction;
/// <summary>
/// Callback to actually perform the processing of the next batch of work.
/// </summary>
@ -115,11 +115,13 @@ internal class AsyncBatchingWorkQueue<TItem, TResult>
TimeSpan delay,
Func<ImmutableArray<TItem>, CancellationToken, ValueTask<TResult>> processBatchAsync,
IEqualityComparer<TItem>? equalityComparer,
Action? idleAction,
CancellationToken cancellationToken)
{
_delay = delay;
_processBatchAsync = processBatchAsync;
_equalityComparer = equalityComparer;
_idleAction = idleAction;
_entireQueueCancellationToken = cancellationToken;
_uniqueItems = new HashSet<TItem>(equalityComparer);
@ -224,9 +226,9 @@ internal class AsyncBatchingWorkQueue<TItem, TResult>
// Not worried about the lock here because we don't want to fire the event under the lock, which means
// there is no effective way to avoid a race. The event doesn't guarantee that there will never be any
// more work anyway, it's merely a best effort.
if (_nextBatch.Count == 0)
if (_idleAction is { } idleAction && _nextBatch.Count == 0)
{
Idle?.Invoke(this, EventArgs.Empty);
idleAction();
}
return result;

Просмотреть файл

@ -54,8 +54,12 @@ internal partial class BackgroundDocumentGenerator : IRazorStartupService, IDisp
_logger = loggerFactory.GetOrCreateLogger<BackgroundDocumentGenerator>();
_disposeTokenSource = new();
_workQueue = new AsyncBatchingWorkQueue<(IProjectSnapshot, IDocumentSnapshot)>(delay, ProcessBatchAsync, _disposeTokenSource.Token);
_workQueue.Idle += (_, _) => RazorEventSource.Instance.BackgroundDocumentGeneratorIdle();
_workQueue = new AsyncBatchingWorkQueue<(IProjectSnapshot, IDocumentSnapshot)>(
delay,
processBatchAsync: ProcessBatchAsync,
equalityComparer: null,
idleAction: () => RazorEventSource.Instance.BackgroundDocumentGeneratorIdle(),
_disposeTokenSource.Token);
_suppressedDocuments = ImmutableHashSet<string>.Empty.WithComparer(FilePathComparer.Instance);
_projectManager.Changed += ProjectManager_Changed;
}