private async Task ProcessBlockAsync(long height, PoolContext db, CancellationToken cancellationToken) { var period = Period; var oldestHeight = height - period - 1; var accounts = await db.Accounts.Where(i => i.Shares.Any(x => x.BlockId <= height && x.BlockId > oldestHeight) && !i.AverageShareHistory.Any(x => x.Height == height)).Select(i => i.Id).ToListAsync(cancellationToken); int counter = 0; foreach (var account in accounts) { if (await db.AccountAverageShareHistory.AnyAsync(x => x.AccountId == account && x.Height == height, cancellationToken)) { continue; } var shares = await db.Shares.Where(i => i.AccountId == account && i.BlockId <= height && i.BlockId > oldestHeight).Select(i => new { i.BlockId, i.ShareValue }).ToListAsync(cancellationToken); var average = shares.GroupBy(i => i.BlockId).Select(x => x.Max(t => t.ShareValue)).Sum() / period; Logger.LogInformation("Account {accountId}, computed average shares {average} for block {blockHeight}", account, average, height); db.AccountAverageShareHistory.Add(new AccountAverageShareHistory() { AccountId = account, Height = height, AverageShares = average }); counter += 1; // Save every 1000 inserts, to avoid performance hit. if (counter % 1000 == 0) { await db.SaveChangesAsync(cancellationToken); } } await db.SaveChangesAsync(cancellationToken); }
public async Task RecordSharesAsync(ulong accountId, long block, decimal shares, ulong nonce, ulong deadline) { using (var transaction = await _context.Database.BeginTransactionAsync()) { if (await _context.Shares.AnyAsync(i => i.AccountId == accountId && i.BlockId == block && i.ShareValue >= shares)) { return; } if (!await _context.Accounts.AnyAsync(i => i.Id == accountId)) { _context.Accounts.Add(new Account() { Id = accountId }); await _context.SaveChangesAsync().ConfigureAwait(false); } _context.Shares.Add(new Share() { AccountId = accountId, BlockId = block, ShareValue = shares, Nonce = nonce, Deadline = deadline }); await _context.SaveChangesAsync().ConfigureAwait(false); transaction.Commit(); } var message = new DeadlineMessage(accountId, nonce, (long)deadline, shares); await _messenger.PublishAsync($"Public.Share.Block.Accepted.{block}", data : message); await _messenger.PublishAsync($"Public.Share.Account.Accepted.{accountId}", data : message); }