Skip to content

Conversation

@ray-roestenburg-da
Copy link
Contributor

@ray-roestenburg-da ray-roestenburg-da commented Sep 24, 2025

Calculating total amulet balance for rounds during aggregation to improve performance of queries in v0/total-amulet-balance.

Note: Only implemented new rounds onward, which I think is enough. (otherwise will have to run a catch up process to add old rounds from round_party_totals table, if we really want total amulet balances by round for all historical rounds).
Responding with NotFound for total amulet balances that have not been calculated.

  • cluster test

Pull Request Checklist

Cluster Testing

  • If a cluster test is required, comment /cluster_test on this PR to request it, and ping someone with access to the DA-internal system to approve it.
  • If a hard-migration test is required (from the latest release), comment /hdm_test on this PR to request it, and ping someone with access to the DA-internal system to approve it.

PR Guidelines

  • Include any change that might be observable by our partners or affect their deployment in the release notes.
  • Specify fixed issues with Fixes #n, and mention issues worked on using #n
  • Include a screenshot for frontend-related PRs - see README or use your favorite screenshot tool

Merge Guidelines

  • Make the git commit message look sensible when squash-merging on GitHub (most likely: just copy your PR description).

@ray-roestenburg-da ray-roestenburg-da force-pushed the ray/leader_boards/1322 branch 7 times, most recently from 5666c77 to 7d841c9 Compare September 25, 2025 18:22
@ray-roestenburg-da ray-roestenburg-da changed the title [ci] pre-calculating balances and leaderboards in aggregation [ci] pre-calculating total amulet balance Sep 26, 2025
@ray-roestenburg-da ray-roestenburg-da marked this pull request as ready for review September 27, 2025 10:51
select greatest(
0,
sum_cumulative_change_to_initial_amount_as_of_round_zero -
sum_cumulative_change_to_holding_fees_rate * ($asOfEndOfRound + 1)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pre-computed sum, so sum_change * ($asOfEndOfRound + 1) instead of sum(change_for_round * ($asOfEndOfRound + 1)): (a+b)*c = ac + bc

@ray-roestenburg-da
Copy link
Contributor Author

/cluster_test

@github-actions
Copy link

Deploy cluster test triggered for Commit 00c7d69b618b5d33b1b943c953b08c5150ea9cd9 in , please contact a Contributor to approve it in CircleCI: https://app.circleci.com/pipelines/github/DACH-NY/canton-network-internal/33947

@@ -413,8 +413,15 @@ class HttpScanHandler(
HttpErrorHandler.onGrpcNotFound(s"Data for round ${asOfEndOfRound} not yet computed")
)
} yield {
definitions.GetTotalAmuletBalanceResponse(
Codec.encode(total)
total.fold(
Copy link
Contributor Author

@ray-roestenburg-da ray-roestenburg-da Sep 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to respond with NotFound for rounds that were not computed. The change in this PR calculates these going forward. Rather 'error-out' with NotFound than fallback to a very slow query. If we get a signal on this from logs that there is a lot of requests for older rounds, we can put some effort in computing all rounds in the round_total_amulet_balance table, but hopefully that will not be needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(the UI already uses getInstrument and this only uses getTotalAmuletBalance if holdingfees are deducted.)

to improve performance of v0/wallet-balance, v0/total-amulet-balance, /v0/top-providers-by-app-rewards

Signed-off-by: Raymond Roestenburg <raymond.roestenburg@digitalasset.com>
Signed-off-by: Raymond Roestenburg <raymond.roestenburg@digitalasset.com>
Signed-off-by: Raymond Roestenburg <raymond.roestenburg@digitalasset.com>
Signed-off-by: Raymond Roestenburg <raymond.roestenburg@digitalasset.com>
Signed-off-by: Raymond Roestenburg <raymond.roestenburg@digitalasset.com>
…work wel for large number of parties.

Signed-off-by: Raymond Roestenburg <raymond.roestenburg@digitalasset.com>
Signed-off-by: Raymond Roestenburg <raymond.roestenburg@digitalasset.com>
Signed-off-by: Raymond Roestenburg <raymond.roestenburg@digitalasset.com>
In the case that the efficient total amulet balance has not been computed for an older round.

Signed-off-by: Raymond Roestenburg <raymond.roestenburg@digitalasset.com>
Signed-off-by: Raymond Roestenburg <raymond.roestenburg@digitalasset.com>
@ray-roestenburg-da
Copy link
Contributor Author

/cluster_test

@github-actions
Copy link

Deploy cluster test triggered for Commit f8748be6b86def950b4c79feaa41f9b0ff6a4482 in , please contact a Contributor to approve it in CircleCI: https://app.circleci.com/pipelines/github/DACH-NY/canton-network-internal/34047

@OriolMunoz-da
Copy link
Contributor

Before I review:

@ray-roestenburg-da
Copy link
Contributor Author

ray-roestenburg-da commented Sep 30, 2025

@OriolMunoz-da

  1. We can't drop anything yet.
  2. Logs show that some are still using it (requests are shown to request older rounds within seconds of the last round, which is not something the FE does)

@OriolMunoz-da
Copy link
Contributor

@meiersi-da
Does it make sense to include the flag mentioned here? Without it, this endpoint will keep subtracting holding fees (test example)

@meiersi-da
Copy link
Contributor

@meiersi-da Does it make sense to include the flag mentioned here? Without it, this endpoint will keep subtracting holding fees (test example)

@OriolMunoz-da : aren't these the "as-of-round zero" endpoints? For these not deducting holding fees is not easily possible, and we said we'll leave them with their current behavior as legacy features.

Copy link
Contributor

@OriolMunoz-da OriolMunoz-da left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I'm mostly coming-back-from-vacation-confused 😄

sql"""
select greatest(
0,
coalesce(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what are you coalescing here?
both sum_cumulative* columns are not null, and you're not left-joining

Copy link
Contributor Author

@ray-roestenburg-da ray-roestenburg-da Oct 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah thanks, cumulative_* in round_party_totals are null, probably misremembered. (it can't really hurt but will remove)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

Comment on lines 958 to 960
on conflict (store_id, closed_round)
do update set sum_cumulative_change_to_initial_amount_as_of_round_zero = excluded.sum_cumulative_change_to_initial_amount_as_of_round_zero,
sum_cumulative_change_to_holding_fees_rate = excluded.sum_cumulative_change_to_holding_fees_rate;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand when a conflict would happen and why. Why is it safe to replace the amounts?

Copy link
Contributor Author

@ray-roestenburg-da ray-roestenburg-da Oct 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unlikely a conflict occurs, but all of this has to be idempotent because of 'reasons outside of my preference ;-)', so just safer, don't want to fail. it's on conflict pk so it would have to mean a previous aggregation already completed.
Since the aggregation calculates this from round_party_totals and most recent active_parties that is created by this aggregation (and all of this is transactional), it's safe to replace the amounts (it would be the same result).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be the same result

then you could as well ignore it, right? I was mostly surprised because some lines above it's ignored. No strong feelings one way or the other

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, right, yes could just do on conflict do nothing, let me do that instead for clarity

Comment on lines 929 to 940
create temp table active_parties_for_aggr_rounds on commit drop as
select party, aggr_round as aggr_round, active_round from active_parties_before
union
-- all the parties that were active in the newly aggregated rounds
select party, round as aggr_round, round as active_round from temp_cumulative_totals
union
-- adding the lastClosedRound as aggr_round, for parties that were not active but have been aggregated in that round
select party,
$lastClosedRound as aggr_round,
closed_round as active_round
from active_parties
where store_id = $roundTotalsStoreId;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

open and close parentheses on commit drop as (...), this got very confusing when reviewing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I'll add those

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

sqlu"""
create temp table active_parties_before on commit drop as
select party,
(select max(closed_round) from active_parties where store_id = $roundTotalsStoreId) as aggr_round,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't depend on the rest of the query, have you checked that the query plan doesn't run this for every party?
it might still be better to extract it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why for every party? This happens per aggregation, which is not per party. It aggregates everything for all rounds it finds.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh sorry you mean the sub select.. let me check to be safe

Copy link
Contributor Author

@ray-roestenburg-da ray-roestenburg-da Oct 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Postgres is clever enough luckily (1 loop for aggregate and 1 loop for all the parties). the seq scan is fine cause all parties are needed. (one row per party in this table (per store_id))

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another alternative is:

        with max_closed as (select max(closed_round) as aggr_round from scan_sv_1.active_parties where store_id = 1)
        select party,
               max_closed.aggr_round,
               closed_round as active_round
        from   scan_sv_1.active_parties,
               max_closed 
        where  store_id = 1

but this has the same explain plan, rather keep it simple with scalar sub-query.

Signed-off-by: Raymond Roestenburg <raymond.roestenburg@digitalasset.com>
Signed-off-by: Raymond Roestenburg <raymond.roestenburg@digitalasset.com>
Signed-off-by: Raymond Roestenburg <raymond.roestenburg@digitalasset.com>
Signed-off-by: Raymond Roestenburg <raymond.roestenburg@digitalasset.com>
@ray-roestenburg-da
Copy link
Contributor Author

Have another look please @OriolMunoz-da

Copy link
Contributor

@OriolMunoz-da OriolMunoz-da left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks! let me know if the sub-select does something crazy, otherwise lgtm

Signed-off-by: Raymond Roestenburg <raymond.roestenburg@digitalasset.com>
@ray-roestenburg-da ray-roestenburg-da enabled auto-merge (squash) October 1, 2025 11:28
@ray-roestenburg-da ray-roestenburg-da merged commit d816f69 into main Oct 1, 2025
57 checks passed
@ray-roestenburg-da ray-roestenburg-da deleted the ray/leader_boards/1322 branch October 1, 2025 11:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants