Fetch rewards in parallel with transactions

Problem: the Address main page is too slow. Part of the reason is that it has to execute 3 queries.

Solution: since 2 of these queries are unrelated to each other (transactions and rewards) they will be executed in parallel.
pull/2352/head
pasqu4le 5 years ago
parent 50d57ee839
commit a8823abe17
No known key found for this signature in database
GPG Key ID: 8F3EE01F1DC90687
  1. 1
      CHANGELOG.md
  2. 4
      apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex
  3. 39
      apps/explorer/lib/explorer/chain.ex

@ -1,6 +1,7 @@
## Current
### Features
- [#2352](https://github.com/poanetwork/blockscout/pull/2352) - Fetch rewards in parallel with transactions
- [#2294](https://github.com/poanetwork/blockscout/pull/2294) - add healthy block period checking endpoint
### Fixes

@ -23,7 +23,8 @@ defmodule BlockScoutWeb.AddressTransactionController do
[token_transfers: :token] => :optional,
[token_transfers: :to_address] => :optional,
[token_transfers: :from_address] => :optional,
[token_transfers: :token_contract_address] => :optional
[token_transfers: :token_contract_address] => :optional,
:block => :required
}
]
@ -34,7 +35,6 @@ defmodule BlockScoutWeb.AddressTransactionController do
{:ok, address} <- Chain.hash_to_address(address_hash, address_options, false) do
options =
@transaction_necessity_by_association
|> put_in([:necessity_by_association, :block], :required)
|> Keyword.merge(paging_options(params))
|> Keyword.merge(current_filter(params))

@ -222,25 +222,17 @@ defmodule Explorer.Chain do
Transaction.t()
]
def address_to_transactions_with_rewards(address_hash, options \\ []) when is_list(options) do
direction = Keyword.get(options, :direction)
necessity_by_association = Keyword.get(options, :necessity_by_association, %{})
paging_options = Keyword.get(options, :paging_options, @default_paging_options)
transaction_hashes_from_token_transfers =
TokenTransfer.where_any_address_fields_match(direction, address_hash, paging_options)
transactions_list =
paging_options
|> fetch_transactions()
|> Transaction.where_transaction_matches(transaction_hashes_from_token_transfers, direction, address_hash)
|> join_associations(necessity_by_association)
|> Transaction.preload_token_transfers(address_hash)
|> Repo.all()
if Application.get_env(:block_scout_web, BlockScoutWeb.Chain)[:has_emission_funds] do
rewards_task =
Task.async(fn ->
Reward.fetch_emission_rewards_tuples(address_hash, paging_options)
end)
address_hash
|> Reward.fetch_emission_rewards_tuples(paging_options)
|> Enum.concat(transactions_list)
|> address_to_transactions_without_rewards(paging_options, options)
|> Enum.concat(Task.await(rewards_task))
|> Enum.sort_by(fn item ->
case item do
{%Reward{} = emission_reward, _} ->
@ -252,10 +244,25 @@ defmodule Explorer.Chain do
end)
|> Enum.take(paging_options.page_size)
else
transactions_list
address_to_transactions_without_rewards(address_hash, paging_options, options)
end
end
defp address_to_transactions_without_rewards(address_hash, paging_options, options) do
direction = Keyword.get(options, :direction)
necessity_by_association = Keyword.get(options, :necessity_by_association, %{})
transaction_hashes_from_token_transfers =
TokenTransfer.where_any_address_fields_match(direction, address_hash, paging_options)
paging_options
|> fetch_transactions()
|> Transaction.where_transaction_matches(transaction_hashes_from_token_transfers, direction, address_hash)
|> join_associations(necessity_by_association)
|> Transaction.preload_token_transfers(address_hash)
|> Repo.all()
end
@spec address_to_logs(Hash.Address.t(), Keyword.t()) :: [Log.t()]
def address_to_logs(address_hash, options \\ []) when is_list(options) do
paging_options = Keyword.get(options, :paging_options) || %PagingOptions{page_size: 50}

Loading…
Cancel
Save