public async Task <List <IpAddressDetails> > Process(List <IpAddressDetailsRequest> requests)
        {
            _log.LogInformation($"IpAddressProcessor received request for {requests.Count} ip address details");
            List <IpAddressDetails> cachedDetails = await _ipAddressDetailsDao.GetIpAddressDetails(requests);

            List <IpAddressDetailsRequest> cacheMisses = requests
                                                         .Where(request => !cachedDetails.Any(response => response.IpAddress == request.IpAddress && response.Date == request.Date))
                                                         .ToList();

            if (cacheMisses.Any())
            {
                _log.LogInformation($"Looking up {cacheMisses.Count} IpAddressDetails not found in database");
                List <IpAddressDetails> lookedUpDetails = await _ipAddressLookup.Lookup(cacheMisses);

                await _ipAddressDetailsDao.SaveIpAddressDetails(lookedUpDetails);

                cachedDetails.AddRange(lookedUpDetails);
            }

            _log.LogInformation($"IpAddressProcessor returned {cachedDetails.Count} IpAddressDetails of {requests.Count} requested");

            return(cachedDetails);
        }
        public async Task Handle(ReverseDnsBackfillBatch message)
        {
            Stopwatch stopwatch = Stopwatch.StartNew();

            _log.LogInformation($"Received batch of {message.IpsToBackfill?.Count ?? 0} reverse dns entries to backfill with reverseDns lookups");

            if (message.IpsToBackfill == null || message.IpsToBackfill.Count == 0)
            {
                return;
            }

            foreach (string ipAddress in message.IpsToBackfill)
            {
                DateTime         now = DateTime.UtcNow;
                ReverseDnsResult currentReverseDnsResult = await Lookup(ipAddress);

                List <IpAddressDetails> entries = await _ipAddressAddressDetailsDao.GetIpAddressDetails(ipAddress);

                List <IpAddressDetails> entriesWithReverseDns    = entries.Where(x => x.ReverseDnsResponses != null).ToList();
                List <IpAddressDetails> entriesWithoutReverseDns = entries.Where(x => x.ReverseDnsResponses == null).ToList();

                List <IpAddressDetailsUpdateDto> entriesToUpdate = new List <IpAddressDetailsUpdateDto>();

                foreach (IpAddressDetails existingEntry in entriesWithoutReverseDns)
                {
                    if (entriesWithReverseDns.Any())
                    {
                        IpAddressDetails nearestNeighbour = entriesWithReverseDns.OrderBy(x => Math.Abs(x.Date.Ticks - existingEntry.Date.Ticks)).First();

                        long timeBetweenEntryAndNow = Math.Abs(now.Ticks - existingEntry.Date.Ticks);
                        long timeBetweenEntryAndNearestNeighbour = Math.Abs(nearestNeighbour.Date.Ticks - existingEntry.Date.Ticks);

                        if (timeBetweenEntryAndNearestNeighbour < timeBetweenEntryAndNow)
                        {
                            IpAddressDetailsUpdateDto entryToUpdate = new IpAddressDetailsUpdateDto(
                                existingEntry.IpAddress,
                                existingEntry.Date,
                                nearestNeighbour.ReverseDnsResponses,
                                nearestNeighbour.ReverseDnsLookupTimestamp);

                            entriesToUpdate.Add(entryToUpdate);
                        }
                        else
                        {
                            IpAddressDetailsUpdateDto entryToUpdate = new IpAddressDetailsUpdateDto(
                                existingEntry.IpAddress,
                                existingEntry.Date,
                                currentReverseDnsResult.ForwardResponses,
                                now);

                            entriesToUpdate.Add(entryToUpdate);
                        }
                    }
                    else
                    {
                        IpAddressDetailsUpdateDto entryToUpdate = new IpAddressDetailsUpdateDto(
                            existingEntry.IpAddress,
                            existingEntry.Date,
                            currentReverseDnsResult.ForwardResponses,
                            now);

                        entriesToUpdate.Add(entryToUpdate);
                    }
                }

                await _ipAddressAddressDetailsDao.UpdateReverseDns(entriesToUpdate);
            }

            _log.LogInformation(
                $"Processed batch of {message.IpsToBackfill?.Count} reverse dns entries in {stopwatch.ElapsedMilliseconds} ms");
        }