Skip to content

Commit

Permalink
Merge pull request #545 from radixdlt/ledger-lookup-epoch-perf
Browse files Browse the repository at this point in the history
Optimized epoch and epoch + round based ledger state lookups
  • Loading branch information
krzlabrdx authored Oct 20, 2023
2 parents ab1ab54 + c16647d commit 6c8c9a6
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 39 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## 1.1.1 - Babylon
Release Date: _unreleased_

TBA
- Fixed `epoch [+ round]` based ledger state lookups.

## 1.1.0 - Babylon
Release Date: _unreleased_
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,37 +162,18 @@ public static IQueryable<LedgerTransaction> GetFirstLedgerTransactionAfterTimest
}

/// <summary>
/// Returns most recently committed ledger transaction at or before given epoch and round.
/// Returns ledger transaction committed at given epoch and round.
/// </summary>
/// <remarks>
/// A LedgerTransaction row contains large blobs, so you must SELECT the fields you need after using this, and not pull down the whole
/// ledger transaction row, to avoid possible performance issues.
/// </remarks>
public static IQueryable<LedgerTransaction> GetLatestLedgerTransactionAtEpochRound<TDbContext>(this TDbContext dbContext, long epoch, long round)
public static IQueryable<LedgerTransaction> GetLedgerTransactionAtEpochAndRound<TDbContext>(this TDbContext dbContext, long epoch, long round)
where TDbContext : CommonDbContext
{
return dbContext
.LedgerTransactions
.Where(lt => lt.Epoch == epoch && lt.RoundInEpoch >= round && lt.IndexInRound == 0)
.OrderByDescending(lt => lt.StateVersion)
.Take(1)
.AnnotateMetricName();
}

/// <summary>
/// Returns the first committed ledger transaction at or after given epoch and round.
/// </summary>
/// <remarks>
/// A LedgerTransaction row contains large blobs, so you must SELECT the fields you need after using this, and not pull down the whole
/// ledger transaction row, to avoid possible performance issues.
/// </remarks>
public static IQueryable<LedgerTransaction> GetFirstLedgerTransactionAtEpochRound<TDbContext>(this TDbContext dbContext, long epoch, long round)
where TDbContext : CommonDbContext
{
return dbContext
.LedgerTransactions
.Where(lt => lt.Epoch >= epoch && lt.RoundInEpoch >= round && lt.IndexInRound == 0)
.OrderBy(lt => lt.StateVersion)
.Where(lt => lt.Epoch == epoch && lt.RoundInEpoch == round && lt.IndexInRound == 0)
.Take(1)
.AnnotateMetricName();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ public LedgerStateQuerier(
}
else if (fromLedgerStateIdentifier?.HasEpoch() == true)
{
ledgerStateReport = await GetLedgerStateAfterEpochAndRound(fromLedgerStateIdentifier.Epoch.Value, fromLedgerStateIdentifier.Round ?? 0, token);
ledgerStateReport = await GetLedgerStateAtEpochAndRound(fromLedgerStateIdentifier.Epoch.Value, fromLedgerStateIdentifier.Round ?? 1, token);
}

return ledgerStateReport?.LedgerState;
Expand Down Expand Up @@ -300,7 +300,7 @@ private async Task<LedgerStateReport> GetLedgerState(GatewayModel.LedgerStateSel
}
else if (at?.HasEpoch() == true)
{
result = await GetLedgerStateAtEpochAndRound(at.Epoch.Value, at.Round ?? 0, token);
result = await GetLedgerStateAtEpochAndRound(at.Epoch.Value, at.Round ?? 1, token);
}
else
{
Expand Down Expand Up @@ -372,23 +372,11 @@ private async Task<LedgerStateReport> GetLedgerStateAfterTimestamp(DateTime time

private async Task<LedgerStateReport> GetLedgerStateAtEpochAndRound(long epoch, long round, CancellationToken token)
{
var ledgerState = await SelectLedgerStateFromQuery(_dbContext.GetLatestLedgerTransactionAtEpochRound(epoch, round), false, token);
var ledgerState = await SelectLedgerStateFromQuery(_dbContext.GetLedgerTransactionAtEpochAndRound(epoch, round), false, token);

if (ledgerState == null)
{
throw InvalidRequestException.FromOtherError($"Epoch {epoch} is beyond the end of the known ledger");
}

return ledgerState;
}

private async Task<LedgerStateReport> GetLedgerStateAfterEpochAndRound(long epoch, long round, CancellationToken token)
{
var ledgerState = await SelectLedgerStateFromQuery(_dbContext.GetFirstLedgerTransactionAtEpochRound(epoch, round), false, token);

if (ledgerState == null)
{
throw InvalidRequestException.FromOtherError($"Epoch {epoch} round {round} is beyond the end of the known ledger");
throw InvalidRequestException.FromOtherError($"Epoch {epoch} round {round} is beyond the end of the known ledger or invalid");
}

return ledgerState;
Expand Down

0 comments on commit 6c8c9a6

Please sign in to comment.