protected override async Task <JobResult> RunInternalAsync(JobContext context) { try { NetInfo netInfo = await _statsCache.GetAsync <NetInfo>(NetInfo.DefaultCacheKey, null).AnyContext(); if (netInfo == null) { return(JobResult.FailedWithMessage("NetInfo is null")); } IEnumerable <CinderAddress> addresses = await _addressRepository.GetStaleAddresses(_settings.Age, _settings.Limit).AnyContext(); IEnumerable <CinderAddress> enumerable = addresses as CinderAddress[] ?? addresses.ToArray(); _logger.LogDebug("Found {Count} addresses to update", enumerable.Count()); List <CinderAddress> updated = new(); foreach (CinderAddress address in enumerable) { _logger.LogDebug("Updating stats for {Hash}", address.Hash); HexBigInteger balance; try { balance = await _web3.Eth.GetBalance.SendRequestAsync(address.Hash, new BlockParameter()).AnyContext(); } catch (Exception e) { _logger.LogDebug(e, "Could not get balance for {Hash}", address.Hash); continue; } address.Balance = UnitConversion.Convert.FromWei(balance); address.Timestamp = (ulong)DateTimeOffset.UtcNow.ToUnixTimeSeconds(); address.ForceRefresh = false; if (_settings.BalanceHistory.Enabled && _settings.BalanceHistory.Days.Any()) { IEnumerable <Task <HexBigInteger> > tasks = _settings.BalanceHistory.Days.Select(d => { ulong block = GetPastBlock(netInfo.BestBlock, netInfo.AverageBlockTime, d); return(_web3.Eth.GetBalance.SendRequestAsync(address.Hash, new BlockParameter(block))); }); try { HexBigInteger[] results = await Task.WhenAll(tasks).AnyContext(); address.BalanceHistory.Clear(); for (int i = 0; i < _settings.BalanceHistory.Days.Length; i++) { address.BalanceHistory.Add(_settings.BalanceHistory.Days[i].ToString(), UnitConversion.Convert.FromWei(results[i])); } } catch (Exception e) { _logger.LogDebug(e, "Could not get historical balance for {Hash}", address.Hash); } } updated.Add(address); } if (!updated.Any()) { return(JobResult.Success); } await _addressRepository.BulkUpsertAddresses(updated).AnyContext(); } catch (Exception e) { return(JobResult.FromException(e)); } return(JobResult.Success); }