public async Task <IEnumerable <PostcodeDto> > GetPostCodesAndAddressesFromQasAsync(IEnumerable <string> missingPostcodes, CancellationToken cancellationToken) { // call QAS for missing postcodes and addresses List <Task <QasSearchRootResponse> > qasSearchResponseTasks = new List <Task <QasSearchRootResponse> >(); List <QasSearchRootResponse> qasSearchResponses = new List <QasSearchRootResponse>(); foreach (string missingPostcode in missingPostcodes) { Task <QasSearchRootResponse> qasResponseTask = _qasService.GetGlobalIntuitiveSearchResponseAsync(PostcodeFormatter.FormatPostcode(missingPostcode), cancellationToken); qasSearchResponseTasks.Add(qasResponseTask); } while (qasSearchResponseTasks.Count > 0) { Task <QasSearchRootResponse> finishedQasResponseTask = await Task.WhenAny(qasSearchResponseTasks); qasSearchResponseTasks.Remove(finishedQasResponseTask); QasSearchRootResponse qasSearchResponse = await finishedQasResponseTask; qasSearchResponses.Add(qasSearchResponse); } // call QAS for address details (grouped by postcode to avoid sending 1000s of request at once and to map a single PostcodeDto at a time) ILookup <string, string> missingQasFormatIdsGroupedByPostCode = _qasMapper.GetFormatIds(qasSearchResponses); List <PostcodeDto> missingPostcodeDtos = new List <PostcodeDto>(); foreach (IGrouping <string, string> missingQasFormatIds in missingQasFormatIdsGroupedByPostCode) { List <Task <QasFormatRootResponse> > qasFormatResponseTasks = new List <Task <QasFormatRootResponse> >(); foreach (string missingQasFormatId in missingQasFormatIds) { Task <QasFormatRootResponse> qasFormatResponseTask = _qasService.GetGlobalIntuitiveFormatResponseAsync(missingQasFormatId, cancellationToken); qasFormatResponseTasks.Add(qasFormatResponseTask); } List <QasFormatRootResponse> qasFormatResponses = new List <QasFormatRootResponse>(); while (qasFormatResponseTasks.Count > 0) { Task <QasFormatRootResponse> finishedQasFormatResponseTask = await Task.WhenAny(qasFormatResponseTasks); qasFormatResponseTasks.Remove(finishedQasFormatResponseTask); QasFormatRootResponse qasFormatResponse = await finishedQasFormatResponseTask; qasFormatResponses.Add(qasFormatResponse); } PostcodeDto missingPostcodeDtosForThisBatch = _qasMapper.MapToPostcodeDto(missingQasFormatIds.Key, qasFormatResponses); try { //new addresses need a friendly name _friendlyNameGenerator.GenerateFriendlyName(missingPostcodeDtosForThisBatch); } catch (Exception ex) { _logger.LogWarning("Error generating friendly name", ex); } missingPostcodeDtos.Add(missingPostcodeDtosForThisBatch); } if (missingPostcodeDtos.Any()) { await _repository.SaveAddressesAndFriendlyNameAsync(missingPostcodeDtos); } return(missingPostcodeDtos); }