public async Task WhenWorkIsAddedAgainWhenPreviousIsAnalysing_ThenDontWaitAnotherOneToGetReady() { var now = DateTime.UtcNow; var queue = new AnalyzerWorkQueue(new LoggerFactory(), utcNow: () => now, timeoutForPendingWorkMs: 10 * 1000); var document = CreateTestDocumentId(); queue.PutWork(new[] { document }, AnalyzerWorkType.Foreground); now = PassOverThrotlingPeriod(now); var work = queue.TakeWork(AnalyzerWorkType.Foreground); var waitingCall = Task.Run(async() => await queue.WaitForegroundWorkComplete()); await Task.Delay(50); // User updates code -> document is queued again during period when theres already api call waiting // to continue. queue.PutWork(new[] { document }, AnalyzerWorkType.Foreground); // First iteration of work is done. queue.WorkComplete(AnalyzerWorkType.Foreground); // Waiting call continues because its iteration of work is done, even when theres next // already waiting. await waitingCall; Assert.True(waitingCall.IsCompleted); }
private async Task Worker(AnalyzerWorkType workType) { while (true) { try { var currentWorkGroupedByProjects = _workQueue .TakeWork(workType) .Select(document => (project: document.Project, document)) .GroupBy(x => x.project, x => x.document) .ToImmutableArray(); foreach (var projectGroup in currentWorkGroupedByProjects) { var projectPath = projectGroup.Key.FilePath; EventIfBackgroundWork(workType, projectPath, ProjectDiagnosticStatus.Started); await AnalyzeProject(projectGroup); EventIfBackgroundWork(workType, projectPath, ProjectDiagnosticStatus.Ready); } _workQueue.WorkComplete(workType); await Task.Delay(50); } catch (Exception ex) { _logger.LogError($"Analyzer worker failed: {ex}"); } } }
public void WhenForegroundWorkIsUnderAnalysisOutFromQueueThenWaitUntilNextIterationOfItIsReady() { var now = DateTime.UtcNow; var queue = new AnalyzerWorkQueue(new LoggerFactory(), utcNow: () => now, timeoutForPendingWorkMs: 500); var document = CreateTestDocumentId(); queue.PutWork(new[] { document }, AnalyzerWorkType.Foreground); now = PassOverThrotlingPeriod(now); var work = queue.TakeWork(AnalyzerWorkType.Foreground); var pendingTask = queue.WaitForegroundWorkComplete(); pendingTask.Wait(TimeSpan.FromMilliseconds(50)); Assert.False(pendingTask.IsCompleted); queue.WorkComplete(AnalyzerWorkType.Foreground); pendingTask.Wait(TimeSpan.FromMilliseconds(50)); Assert.True(pendingTask.IsCompleted); }
private async Task Worker(AnalyzerWorkType workType) { while (true) { try { var solution = _workspace.CurrentSolution; var currentWorkGroupedByProjects = _workQueue .TakeWork(workType) .Select(documentId => (projectId: solution.GetDocument(documentId)?.Project?.Id, documentId)) .Where(x => x.projectId != null) .GroupBy(x => x.projectId, x => x.documentId) .ToImmutableArray(); foreach (var projectGroup in currentWorkGroupedByProjects) { var projectPath = solution.GetProject(projectGroup.Key).FilePath; EventIfBackgroundWork(workType, projectPath, ProjectDiagnosticStatus.Started); await AnalyzeAndReport(solution, projectGroup); EventIfBackgroundWork(workType, projectPath, ProjectDiagnosticStatus.Ready); } _workQueue.WorkComplete(workType); await Task.Delay(50); } catch (Exception ex) { _logger.LogError($"Analyzer worker failed: {ex}"); } } }