From 36c1aa9b67ddf0424142623ce8cab7db5f2a2716 Mon Sep 17 00:00:00 2001 From: Ayrat Badykov Date: Wed, 4 Sep 2019 15:52:25 +0300 Subject: [PATCH] fetch token counters in parallel the slowest part of the token overview page is fetching of total token transfers and total token holders counters queries. Sometimes they even cause page load failures. Now we will start fetching these counters in parallel and limiting query execution to 40 seconds. If they fail to load, we won't show these counters. --- .../controllers/tokens/holder_controller.ex | 8 +++-- .../tokens/inventory_controller.ex | 7 ++-- .../tokens/read_contract_controller.ex | 8 +++-- .../controllers/tokens/token_controller.ex | 34 +++++++++++++++++++ .../controllers/tokens/transfer_controller.ex | 7 ++-- .../tokens/overview/_details.html.eex | 8 +++-- 6 files changed, 62 insertions(+), 10 deletions(-) diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/holder_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/holder_controller.ex index 4de35fc012..553efef03e 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/holder_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/holder_controller.ex @@ -12,6 +12,8 @@ defmodule BlockScoutWeb.Tokens.HolderController do next_page_params: 3 ] + import BlockScoutWeb.Tokens.TokenController, only: [fetch_token_counters: 2] + def index(conn, %{"token_id" => address_hash_string, "type" => "JSON"} = params) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), {:ok, token} <- Chain.token_from_address_hash(address_hash), @@ -47,13 +49,15 @@ defmodule BlockScoutWeb.Tokens.HolderController do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), {:ok, token} <- Chain.token_from_address_hash(address_hash, options) do + {total_token_transfers, total_token_holders} = fetch_token_counters(token, address_hash) + render( conn, "index.html", current_path: current_path(conn), token: Market.add_price(token), - total_token_holders: token.holder_count || Chain.count_token_holders_from_token_hash(address_hash), - total_token_transfers: Chain.count_token_transfers_from_token_hash(address_hash) + total_token_holders: total_token_holders, + total_token_transfers: total_token_transfers ) else :error -> diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/inventory_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/inventory_controller.ex index b9783b2c63..ddd12eb392 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/inventory_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/inventory_controller.ex @@ -7,6 +7,7 @@ defmodule BlockScoutWeb.Tokens.InventoryController do alias Phoenix.View import BlockScoutWeb.Chain, only: [split_list_by_page: 1, default_paging_options: 0] + import BlockScoutWeb.Tokens.TokenController, only: [fetch_token_counters: 2] def index(conn, %{"token_id" => address_hash_string, "type" => "JSON"} = params) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), @@ -64,13 +65,15 @@ defmodule BlockScoutWeb.Tokens.InventoryController do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), {:ok, token} <- Chain.token_from_address_hash(address_hash, options) do + {total_token_transfers, total_token_holders} = fetch_token_counters(token, address_hash) + render( conn, "index.html", current_path: current_path(conn), token: Market.add_price(token), - total_token_transfers: Chain.count_token_transfers_from_token_hash(address_hash), - total_token_holders: token.holder_count || Chain.count_token_holders_from_token_hash(address_hash) + total_token_transfers: total_token_transfers, + total_token_holders: total_token_holders ) else :error -> diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/read_contract_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/read_contract_controller.ex index f6ae63f537..2f0c8773a4 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/read_contract_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/read_contract_controller.ex @@ -3,17 +3,21 @@ defmodule BlockScoutWeb.Tokens.ReadContractController do alias Explorer.{Chain, Market} + import BlockScoutWeb.Tokens.TokenController, only: [fetch_token_counters: 2] + def index(conn, %{"token_id" => address_hash_string}) do options = [necessity_by_association: %{[contract_address: :smart_contract] => :optional}] with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), {:ok, token} <- Chain.token_from_address_hash(address_hash, options) do + {total_token_transfers, total_token_holders} = fetch_token_counters(token, address_hash) + render( conn, "index.html", token: Market.add_price(token), - total_token_transfers: token.holder_count || Chain.count_token_transfers_from_token_hash(address_hash), - total_token_holders: Chain.count_token_holders_from_token_hash(address_hash) + total_token_transfers: total_token_transfers, + total_token_holders: total_token_holders ) else :error -> diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/token_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/token_controller.ex index 47b73cc942..58d6978008 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/token_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/token_controller.ex @@ -1,7 +1,41 @@ defmodule BlockScoutWeb.Tokens.TokenController do use BlockScoutWeb, :controller + require Logger + + alias Explorer.Chain + def show(conn, %{"id" => address_hash_string}) do redirect(conn, to: token_transfer_path(conn, :index, address_hash_string)) end + + def fetch_token_counters(token, address_hash) do + total_token_transfers_task = + Task.async(fn -> + Chain.count_token_transfers_from_token_hash(address_hash) + end) + + total_token_holders_task = + Task.async(fn -> + token.holder_count || Chain.count_token_holders_from_token_hash(address_hash) + end) + + [total_token_transfers_task, total_token_holders_task] + |> Task.yield_many(:timer.seconds(40)) + |> Enum.map(fn {_task, res} -> + case res do + {:ok, result} -> + result + + {:exit, reason} -> + Logger.warn("Query fetching token counters terminated: #{inspect(reason)}") + 0 + + nil -> + Logger.warn("Query fetching token counters timed out.") + 0 + end + end) + |> List.to_tuple() + end end diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/transfer_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/transfer_controller.ex index 9b75087c45..f977d091f1 100644 --- a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/transfer_controller.ex +++ b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/transfer_controller.ex @@ -6,6 +6,7 @@ defmodule BlockScoutWeb.Tokens.TransferController do alias Phoenix.View import BlockScoutWeb.Chain, only: [split_list_by_page: 1, paging_options: 1, next_page_params: 3] + import BlockScoutWeb.Tokens.TokenController, only: [fetch_token_counters: 2] def index(conn, %{"token_id" => address_hash_string, "type" => "JSON"} = params) do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), @@ -48,13 +49,15 @@ defmodule BlockScoutWeb.Tokens.TransferController do with {:ok, address_hash} <- Chain.string_to_address_hash(address_hash_string), {:ok, token} <- Chain.token_from_address_hash(address_hash, options) do + {total_token_transfers, total_token_holders} = fetch_token_counters(token, address_hash) + render( conn, "index.html", current_path: current_path(conn), token: Market.add_price(token), - total_token_transfers: Chain.count_token_transfers_from_token_hash(address_hash), - total_token_holders: token.holder_count || Chain.count_token_holders_from_token_hash(address_hash) + total_token_transfers: total_token_transfers, + total_token_holders: total_token_holders ) else :error -> diff --git a/apps/block_scout_web/lib/block_scout_web/templates/tokens/overview/_details.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/tokens/overview/_details.html.eex index c4fbdc2af2..8f2928990a 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/tokens/overview/_details.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/tokens/overview/_details.html.eex @@ -57,8 +57,12 @@
<%= @token.type %> - <%= @total_token_holders %> <%= gettext "Addresses" %> - <%= @total_token_transfers %> <%= gettext "Transfers" %> + <%= if @total_token_holders > 0 do %> + <%= @total_token_holders %> <%= gettext "Addresses" %> + <% end %> + <%= if @total_token_transfers > 0 do %> + <%= @total_token_transfers %> <%= gettext "Transfers" %> + <% end %> <%= if decimals?(@token) do %> <%= @token.decimals %> <%= gettext "Decimals" %> <% end %>