private void EventIfBackgroundWork(AnalyzerWorkType workType, string projectPath, ProjectDiagnosticStatus status)
 {
     if (workType == AnalyzerWorkType.Background)
     {
         _forwarder.ProjectAnalyzedInBackground(projectPath, status);
     }
 }
Пример #2
0
        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}");
                }
            }
        }
Пример #3
0
        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));
        }
Пример #4
0
        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));
        }
Пример #5
0
        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;
            }
        }
Пример #6
0
        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);
            }
        }
Пример #7
0
        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));
        }
Пример #8
0
        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);
 }