public Dictionary <string, Task <RecommendationDetails> > GetApiRecommendation(IEnumerable <string> namespaces)
        {
            var recommendationTaskCompletionSources = new Dictionary <string, TaskCompletionSource <RecommendationDetails> >();

            try
            {
                if (_manifest == null)
                {
                    var manifestTask = GetManifestAsync();
                    manifestTask.Wait();
                    _manifest = manifestTask.Result;
                }
                var foundPackages = new Dictionary <string, List <string> >();
                namespaces.ToList().ForEach(p =>
                {
                    var value = _manifest.GetValueOrDefault(p, null);
                    if (value != null)
                    {
                        recommendationTaskCompletionSources.Add(p, new TaskCompletionSource <RecommendationDetails>());
                        if (!foundPackages.ContainsKey(value))
                        {
                            foundPackages.Add(value, new List <string>());
                        }
                        foundPackages[value].Add(p);
                    }
                });

                _logger.LogInformation("Checking Github files {0} for recommendations", foundPackages.Count);
                if (foundPackages.Any())
                {
                    Task.Run(() =>
                    {
                        _semaphore.Wait();
                        try
                        {
                            ProcessCompatibility(namespaces, foundPackages, recommendationTaskCompletionSources);
                        }
                        finally
                        {
                            _semaphore.Release();
                        }
                    });
                }

                return(recommendationTaskCompletionSources.ToDictionary(t => t.Key, t => t.Value.Task));
            }
            catch (Exception ex)
            {
                foreach (var @namespace in namespaces)
                {
                    if (recommendationTaskCompletionSources.TryGetValue(@namespace, out var taskCompletionSource))
                    {
                        taskCompletionSource.TrySetException(
                            new PortingAssistantClientException(ExceptionMessage.NamespaceNotFound(@namespace), ex));
                    }
                }
                return(recommendationTaskCompletionSources.ToDictionary(t => t.Key, t => t.Value.Task));
            }
        }
        private async void ProcessCompatibility(IEnumerable <string> namespaces,
                                                Dictionary <string, List <string> > foundPackages,
                                                Dictionary <string, TaskCompletionSource <RecommendationDetails> > recommendationTaskCompletionSources)
        {
            var namespacesFound      = new HashSet <string>();
            var namespacesWithErrors = new HashSet <string>();

            try
            {
                foreach (var url in foundPackages)
                {
                    try
                    {
                        _logger.LogInformation("Downloading {0} from {1}", url.Key, CompatibilityCheckerType);
                        using var stream = await _httpService.DownloadGitHubFileAsync("recommendation/" + url.Key);

                        using var streamReader = new StreamReader(stream);
                        var packageFromGithub = JsonConvert.DeserializeObject <RecommendationDetails>(streamReader.ReadToEnd());

                        foreach (var @namespace in url.Value)
                        {
                            if (recommendationTaskCompletionSources.TryGetValue(@namespace, out var taskCompletionSource))
                            {
                                taskCompletionSource.SetResult(packageFromGithub);
                                namespacesFound.Add(@namespace);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError("Failed when downloading recommendation and parsing {0} from {1}, {2}", url.Key, CompatibilityCheckerType, ex);
                        foreach (var @namespace in url.Value)
                        {
                            if (recommendationTaskCompletionSources.TryGetValue(@namespace, out var taskCompletionSource))
                            {
                                taskCompletionSource.SetException(new PortingAssistantClientException(ExceptionMessage.NamespaceFailedToProcess(@namespace), ex));
                                namespacesWithErrors.Add(@namespace);
                            }
                        }
                    }
                }

                foreach (var @namespace in namespaces)
                {
                    if (namespacesFound.Contains(@namespace) || namespacesWithErrors.Contains(@namespace))
                    {
                        continue;
                    }

                    if (recommendationTaskCompletionSources.TryGetValue(@namespace, out var taskCompletionSource))
                    {
                        var errorMessage = $"Could not find {@namespace} recommendation in external source; discarding this namespace.";
                        _logger.LogInformation(errorMessage);

                        var innerException = new NamespaceNotFoundException(errorMessage);
                        taskCompletionSource.TrySetException(new PortingAssistantClientException(ExceptionMessage.NamespaceNotFound(@namespace), innerException));
                    }
                }
            }
            catch (Exception ex)
            {
                foreach (var @namespace in namespaces)
                {
                    if (recommendationTaskCompletionSources.TryGetValue(@namespace, out var taskCompletionSource))
                    {
                        taskCompletionSource.TrySetException(
                            new PortingAssistantClientException(ExceptionMessage.NamespaceFailedToProcess(@namespace), ex));
                    }
                }

                _logger.LogError("Error encountered while processing recommendations: {0}", ex);
            }
        }