Exemple #1
0
        public async Task WhenMultipleThreadsAreConsumingAnalyzerWorkerQueueItWorksAsExpected()
        {
            var now = DateTime.UtcNow;

            var queue = new AnalyzerWorkQueue(new LoggerFactory(), utcNow: () => now, timeoutForPendingWorkMs: 1000);

            var parallelQueues =
                Enumerable.Range(0, 10)
                .Select(_ =>
                        Task.Run(() =>
            {
                var document = CreateTestDocumentId();

                queue.PutWork(new[] { document }, AnalyzerWorkType.Foreground);

                now = PassOverThrotlingPeriod(now);

                var work = queue.TakeWork(AnalyzerWorkType.Foreground);

                var pendingTask = queue.WaitForegroundWorkComplete();

                queue.WaitForegroundWorkComplete();

                pendingTask.Wait(TimeSpan.FromMilliseconds(300));
            }))
                .ToArray();

            await Task.WhenAll(parallelQueues);

            Assert.Empty(queue.TakeWork(AnalyzerWorkType.Foreground));
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        public void WhenBackgroundWorkIsAdded_DontWaitIt()
        {
            var queue    = new AnalyzerWorkQueue(new LoggerFactory(), timeoutForPendingWorkMs: 10 * 1000);
            var document = CreateTestDocumentId();

            queue.PutWork(new[] { document }, AnalyzerWorkType.Background);

            Assert.True(queue.WaitForegroundWorkComplete().IsCompleted);
        }
Exemple #4
0
        private async Task <ImmutableArray <DocumentDiagnostics> > GetDiagnosticsByDocument(ImmutableArray <Document> documents, bool waitForDocuments)
        {
            if (documents.IsDefaultOrEmpty)
            {
                return(ImmutableArray <DocumentDiagnostics> .Empty);
            }

            ImmutableArray <DocumentDiagnostics> .Builder resultsBuilder = ImmutableArray.CreateBuilder <DocumentDiagnostics>(documents.Length);
            resultsBuilder.Count = documents.Length;

            bool foundAll = true;

            for (int i = 0; i < documents.Length; i++)
            {
                if (_currentDiagnosticResultLookup.TryGetValue(documents[i], out var diagnostics))
                {
                    resultsBuilder[i] = diagnostics;
                }
                else
                {
                    _workQueue.QueueDocumentForeground(documents[i]);
                    foundAll = false;
                }
            }

            if (foundAll)
            {
                return(resultsBuilder.MoveToImmutable());
            }

            await _workQueue.WaitForegroundWorkComplete();

            for (int i = 0; i < documents.Length; i++)
            {
                if (_currentDiagnosticResultLookup.TryGetValue(documents[i], out var diagnostics))
                {
                    resultsBuilder[i] = diagnostics;
                }
                else
                {
                    Debug.Fail("Should have diagnostics after waiting for work");
                    resultsBuilder[i] = new DocumentDiagnostics(documents[i], ImmutableArray <Diagnostic> .Empty);
                }
            }

            return(resultsBuilder.MoveToImmutable());
        }
        private async Task <ImmutableArray <DocumentDiagnostics> > GetDiagnosticsByDocumentIds(ImmutableArray <DocumentId> documentIds, bool waitForDocuments)
        {
            if (waitForDocuments)
            {
                foreach (var documentId in documentIds)
                {
                    _workQueue.TryPromote(documentId);
                }

                await _workQueue.WaitForegroundWorkComplete();
            }

            return(documentIds
                   .Where(x => _currentDiagnosticResultLookup.ContainsKey(x))
                   .Select(x => _currentDiagnosticResultLookup[x])
                   .ToImmutableArray());
        }
Exemple #6
0
        public void WhenWorkIsWaitedButTimeoutForWaitIsExceededAllowContinue()
        {
            var now           = DateTime.UtcNow;
            var loggerFactory = new LoggerFactory();
            var queue         = new AnalyzerWorkQueue(loggerFactory, utcNow: () => now, timeoutForPendingWorkMs: 20);
            var document      = CreateTestDocumentId();

            queue.PutWork(new[] { document }, AnalyzerWorkType.Foreground);

            now = PassOverThrotlingPeriod(now);
            var work = queue.TakeWork(AnalyzerWorkType.Foreground);

            var pendingTask = queue.WaitForegroundWorkComplete();
            var cts         = new CancellationTokenSource();

            cts.CancelAfter(TimeSpan.FromSeconds(5));
            pendingTask.Wait(cts.Token);

            Assert.True(pendingTask.IsCompleted);
            Assert.Contains("Timeout before work got ready", loggerFactory.Logger.RecordedMessages.Single());
        }
Exemple #7
0
        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);
        }