private void EventIfBackgroundWork(AnalyzerWorkType workType, string projectPath, ProjectDiagnosticStatus status) { if (workType == AnalyzerWorkType.Background) { _forwarder.ProjectAnalyzedInBackground(projectPath, status); } }
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 WhenItemsAreAddedButThrotlingIsntOverNoWorkShouldBeReturned(AnalyzerWorkType workType) { var now = DateTime.UtcNow; var queue = new AnalyzerWorkQueue(new LoggerFactory(), utcNow: () => now, timeoutForPendingWorkMs: 10 * 1000); var document = CreateTestDocumentId(); queue.PutWork(new[] { document }, workType); Assert.Empty(queue.TakeWork(workType)); }
public void WhenWorksIsAddedToQueueThenTheyWillBeReturned(AnalyzerWorkType workType) { var now = DateTime.UtcNow; var queue = new AnalyzerWorkQueue(new LoggerFactory(), utcNow: () => now, timeoutForPendingWorkMs: 10 * 1000); var document = CreateTestDocumentId(); queue.PutWork(new[] { document }, workType); now = PassOverThrotlingPeriod(now); var work = queue.TakeWork(workType); Assert.Contains(document, work); Assert.Empty(queue.TakeWork(workType)); }
public void WorkComplete(AnalyzerWorkType workType) { lock (_queueLock) { if (_queues[workType].WorkExecuting.IsEmpty) { return; } _queues[workType].WorkPendingToken?.Cancel(); _queues[workType].WorkPendingToken = null; _queues[workType].WorkExecuting = ImmutableHashSet <DocumentId> .Empty; } }
public IReadOnlyCollection <DocumentId> TakeWork(AnalyzerWorkType workType) { lock (_queueLock) { var queue = _queues[workType]; if (IsThrottlingActive(queue) || queue.WorkWaitingToExecute.IsEmpty) { return(ImmutableHashSet <DocumentId> .Empty); } queue.WorkExecuting = queue.WorkWaitingToExecute; queue.WorkWaitingToExecute = ImmutableHashSet <DocumentId> .Empty; return(queue.WorkExecuting); } }
public void WhenSameItemIsAddedMultipleTimesInRowThenThrottleItemAsOne(AnalyzerWorkType workType) { var now = DateTime.UtcNow; var queue = new AnalyzerWorkQueue(new LoggerFactory(), utcNow: () => now, timeoutForPendingWorkMs: 10 * 1000); var document = CreateTestDocumentId(); queue.PutWork(new[] { document }, workType); queue.PutWork(new[] { document }, workType); queue.PutWork(new[] { document }, workType); Assert.Empty(queue.TakeWork(workType)); now = PassOverThrotlingPeriod(now); Assert.Contains(document, queue.TakeWork(workType)); Assert.Empty(queue.TakeWork(workType)); }
public void PutWork(IReadOnlyCollection <DocumentId> documentIds, AnalyzerWorkType workType) { lock (_queueLock) { var queue = _queues[workType]; if (queue.WorkWaitingToExecute.IsEmpty) { queue.LastThrottlingBegan = _utcNow(); } if (queue.WorkPendingToken == null) { queue.WorkPendingToken = new CancellationTokenSource(); } queue.WorkWaitingToExecute = queue.WorkWaitingToExecute.Union(documentIds); } }
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}"); } } }
private void QueueForAnalysis(ImmutableArray <DocumentId> documentIds, AnalyzerWorkType workType) { _workQueue.PutWork(documentIds, workType); }