diff --git a/src/Features/Core/Portable/SymbolSearch/Windows/SymbolSearchUpdateEngine.Update.cs b/src/Features/Core/Portable/SymbolSearch/Windows/SymbolSearchUpdateEngine.Update.cs index 3bc55f0f752b7..a19ffc164f5cd 100644 --- a/src/Features/Core/Portable/SymbolSearch/Windows/SymbolSearchUpdateEngine.Update.cs +++ b/src/Features/Core/Portable/SymbolSearch/Windows/SymbolSearchUpdateEngine.Update.cs @@ -511,23 +511,22 @@ private async Task DownloadFileAsync(string serverPath, CancellationTo { cancellationToken.ThrowIfCancellationRequested(); - var resultOpt = await TryDownloadFileAsync(client, cancellationToken).ConfigureAwait(false); - if (resultOpt == null) + var (element, delay) = await TryDownloadFileAsync(client, cancellationToken).ConfigureAwait(false); + if (element == null) { - var delay = _service._delayService.CachePollDelay; await LogInfoAsync($"File not downloaded. Trying again in {delay}", cancellationToken).ConfigureAwait(false); await Task.Delay(delay, cancellationToken).ConfigureAwait(false); } else { // File was downloaded. - return resultOpt; + return element; } } } /// Returns 'null' if download is not available and caller should keep polling. - private async Task TryDownloadFileAsync(IFileDownloader fileDownloader, CancellationToken cancellationToken) + private async Task<(XElement element, TimeSpan delay)> TryDownloadFileAsync(IFileDownloader fileDownloader, CancellationToken cancellationToken) { await LogInfoAsync("Read file from client", cancellationToken).ConfigureAwait(false); @@ -536,7 +535,7 @@ private async Task TryDownloadFileAsync(IFileDownloader fileDownloader if (stream == null) { await LogInfoAsync("Read file completed. Client returned no data", cancellationToken).ConfigureAwait(false); - return null; + return (element: null, _service._delayService.CachePollDelay); } await LogInfoAsync("Read file completed. Client returned data", cancellationToken).ConfigureAwait(false); @@ -554,28 +553,23 @@ private async Task TryDownloadFileAsync(IFileDownloader fileDownloader // This code must always succeed. If it does not, that means that either the server reported bogus data // to the file-downloader, or the file-downloader is serving us bogus data. In other event, there is - // something wrong with those components, and we should both report the issue to watson, and stop doing + // something wrong with those components, and we should both report the issue to Watson, and stop doing // the update. try { using var reader = XmlReader.Create(stream, settings); - var result = XElement.Load(reader); + var element = XElement.Load(reader); await LogInfoAsync("Converting data to XElement completed", cancellationToken).ConfigureAwait(false); - return result; - } - catch (Exception e) when (ReportAndDoNotCatch(e)) - { - throw ExceptionUtilities.Unreachable(); + return (element, delay: default); } - - bool ReportAndDoNotCatch(Exception exception) + catch (Exception e) when (_service._reportAndSwallowExceptionUnlessCanceled(e, cancellationToken)) { - // Directly report issue here so we can collect a dump that indicates precisely what is in the - // stream. Then return 'false' explicitly so that the catch handler doesn't run and the exception - // properly tears down the update. - _service._reportAndSwallowExceptionUnlessCanceled(exception, cancellationToken); - return false; + // We retrieved bytes from the server, but we couldn't make parse it an xml. out of it. That's very + // bad. Just trying again one minute later isn't going to help. We need to wait until there is + // good data on the server for us to download. + await LogInfoAsync($"Unable to parse file as XElement", cancellationToken).ConfigureAwait(false); + return (element: null, _service._delayService.CatastrophicFailureDelay); } }