Add blocks indexed counter at BlockScoutWeb

pull/1267/head
Amanda Sposito 6 years ago
parent bf46d3ee51
commit bd58afff74
  1. 2
      apps/block_scout_web/config/config.exs
  2. 2
      apps/block_scout_web/config/test.exs
  3. 3
      apps/block_scout_web/lib/block_scout_web/application.ex
  4. 63
      apps/block_scout_web/lib/block_scout_web/counters/blocks_indexed_counter.ex
  5. 10
      apps/block_scout_web/lib/block_scout_web/notifier.ex
  6. 15
      apps/block_scout_web/test/block_scout_web/channels/block_channel_test.exs
  7. 39
      apps/block_scout_web/test/block_scout_web/features/viewing_app_test.exs

@ -60,6 +60,8 @@ config :wobserver,
discovery: :none, discovery: :none,
mode: :plug mode: :plug
config :block_scout_web, BlockScoutWeb.Counters.BlocksIndexedCounter, enabled: true
# Import environment specific config. This must remain at the bottom # Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above. # of this file so it overrides the configuration defined above.
import_config "#{Mix.env()}.exs" import_config "#{Mix.env()}.exs"

@ -19,3 +19,5 @@ config :logger, :block_scout_web,
config :wallaby, screenshot_on_failure: true config :wallaby, screenshot_on_failure: true
config :explorer, Explorer.ExchangeRates, enabled: false, store: :none config :explorer, Explorer.ExchangeRates, enabled: false, store: :none
config :block_scout_web, BlockScoutWeb.Counters.BlocksIndexedCounter, enabled: false

@ -20,7 +20,8 @@ defmodule BlockScoutWeb.Application do
# Start the endpoint when the application starts # Start the endpoint when the application starts
supervisor(Endpoint, []), supervisor(Endpoint, []),
supervisor(Absinthe.Subscription, [Endpoint]), supervisor(Absinthe.Subscription, [Endpoint]),
{RealtimeEventHandler, name: RealtimeEventHandler} {RealtimeEventHandler, name: RealtimeEventHandler},
{BlocksIndexedCounter, name: BlocksIndexedCounter}
] ]
opts = [strategy: :one_for_one, name: BlockScoutWeb.Supervisor] opts = [strategy: :one_for_one, name: BlockScoutWeb.Supervisor]

@ -0,0 +1,63 @@
defmodule BlockScoutWeb.Counters.BlocksIndexedCounter do
@moduledoc """
Module responsible for fetching and consolidating the number blocks indexed.
It loads the count asynchronously in a time interval.
"""
use GenServer
alias BlockScoutWeb.Notifier
alias Explorer.Chain
# It is undesirable to automatically start the counter in all environments.
# Consider the test environment: if it initiates but does not finish before a
# test ends, that test will fail.
config = Application.get_env(:block_scout_web, BlockScoutWeb.Counters.BlocksIndexedCounter)
@enabled Keyword.get(config, :enabled)
@doc """
Starts a process to periodically update the % of blocks indexed.
"""
@spec start_link(term()) :: GenServer.on_start()
def start_link(_) do
GenServer.start_link(__MODULE__, :ok, name: __MODULE__)
end
@impl true
def init(args) do
if @enabled do
Task.start_link(&calculate_blocks_indexed/0)
schedule_next_consolidation()
end
{:ok, args}
end
def calculate_blocks_indexed do
ratio = Chain.indexed_ratio()
finished? =
if ratio < 1 do
false
else
Chain.finished_indexing?()
end
Notifier.broadcast_blocks_indexed_ratio(ratio, finished?)
end
defp schedule_next_consolidation do
Process.send_after(self(), :calculate_blocks_indexed, :timer.minutes(5))
end
@impl true
def handle_info(:calculate_blocks_indexed, state) do
calculate_blocks_indexed()
schedule_next_consolidation()
{:noreply, state}
end
end

@ -78,6 +78,16 @@ defmodule BlockScoutWeb.Notifier do
def handle_event(_), do: nil def handle_event(_), do: nil
@doc """
Broadcast the percentage of blocks indexed so far.
"""
def broadcast_blocks_indexed_ratio(ratio, finished?) do
Endpoint.broadcast("blocks:indexing", "index_status", %{
ratio: ratio,
finished: finished?
})
end
defp broadcast_address_coin_balance(%{address_hash: address_hash, block_number: block_number}) do defp broadcast_address_coin_balance(%{address_hash: address_hash, block_number: block_number}) do
Endpoint.broadcast("addresses:#{address_hash}", "coin_balance", %{ Endpoint.broadcast("addresses:#{address_hash}", "coin_balance", %{
block_number: block_number block_number: block_number

@ -19,19 +19,4 @@ defmodule BlockScoutWeb.BlockChannelTest do
assert false, "Expected message received nothing." assert false, "Expected message received nothing."
end end
end end
test "subscribed user is notified of new_block event for catchup" do
topic = "blocks:indexing"
@endpoint.subscribe(topic)
Notifier.handle_event({:chain_event, :blocks, :catchup, []})
receive do
%Phoenix.Socket.Broadcast{topic: ^topic, event: "index_status", payload: %{}} ->
assert true
after
:timer.seconds(5) ->
assert false, "Expected message received nothing."
end
end
end end

@ -3,18 +3,23 @@ defmodule BlockScoutWeb.ViewingAppTest do
use BlockScoutWeb.FeatureCase, async: true use BlockScoutWeb.FeatureCase, async: true
alias BlockScoutWeb.{AppPage, Notifier} alias BlockScoutWeb.AppPage
alias BlockScoutWeb.Counters.BlocksIndexedCounter
alias Explorer.Counters.AddressesWithBalanceCounter alias Explorer.Counters.AddressesWithBalanceCounter
setup do
start_supervised!(AddressesWithBalanceCounter)
AddressesWithBalanceCounter.consolidate()
:ok
end
describe "loading bar when indexing" do describe "loading bar when indexing" do
test "shows blocks indexed percentage", %{session: session} do test "shows blocks indexed percentage", %{session: session} do
for index <- 5..9 do for index <- 5..9 do
insert(:block, number: index) insert(:block, number: index)
end end
start_supervised!(AddressesWithBalanceCounter)
AddressesWithBalanceCounter.consolidate()
assert Explorer.Chain.indexed_ratio() == 0.5 assert Explorer.Chain.indexed_ratio() == 0.5
session session
@ -27,9 +32,6 @@ defmodule BlockScoutWeb.ViewingAppTest do
insert(:block, number: index) insert(:block, number: index)
end end
start_supervised!(AddressesWithBalanceCounter)
AddressesWithBalanceCounter.consolidate()
assert Explorer.Chain.indexed_ratio() == 1.0 assert Explorer.Chain.indexed_ratio() == 1.0
session session
@ -37,13 +39,12 @@ defmodule BlockScoutWeb.ViewingAppTest do
|> assert_has(AppPage.indexed_status("Indexing Tokens")) |> assert_has(AppPage.indexed_status("Indexing Tokens"))
end end
test "live updates blocks indexed percentage", %{session: session} do test "updates blocks indexed percentage", %{session: session} do
for index <- 5..9 do for index <- 5..9 do
insert(:block, number: index) insert(:block, number: index)
end end
start_supervised!(AddressesWithBalanceCounter) BlocksIndexedCounter.calculate_blocks_indexed()
AddressesWithBalanceCounter.consolidate()
assert Explorer.Chain.indexed_ratio() == 0.5 assert Explorer.Chain.indexed_ratio() == 0.5
@ -52,18 +53,18 @@ defmodule BlockScoutWeb.ViewingAppTest do
|> assert_has(AppPage.indexed_status("50% Blocks Indexed")) |> assert_has(AppPage.indexed_status("50% Blocks Indexed"))
insert(:block, number: 4) insert(:block, number: 4)
Notifier.handle_event({:chain_event, :blocks, :catchup, []})
BlocksIndexedCounter.calculate_blocks_indexed()
assert_has(session, AppPage.indexed_status("60% Blocks Indexed")) assert_has(session, AppPage.indexed_status("60% Blocks Indexed"))
end end
test "live updates when blocks are fully indexed", %{session: session} do test "updates when blocks are fully indexed", %{session: session} do
for index <- 1..9 do for index <- 1..9 do
insert(:block, number: index) insert(:block, number: index)
end end
start_supervised!(AddressesWithBalanceCounter) BlocksIndexedCounter.calculate_blocks_indexed()
AddressesWithBalanceCounter.consolidate()
assert Explorer.Chain.indexed_ratio() == 0.9 assert Explorer.Chain.indexed_ratio() == 0.9
@ -72,19 +73,19 @@ defmodule BlockScoutWeb.ViewingAppTest do
|> assert_has(AppPage.indexed_status("90% Blocks Indexed")) |> assert_has(AppPage.indexed_status("90% Blocks Indexed"))
insert(:block, number: 0) insert(:block, number: 0)
Notifier.handle_event({:chain_event, :blocks, :catchup, []})
BlocksIndexedCounter.calculate_blocks_indexed()
assert_has(session, AppPage.indexed_status("Indexing Tokens")) assert_has(session, AppPage.indexed_status("Indexing Tokens"))
end end
test "live removes message when chain is indexed", %{session: session} do test "removes message when chain is indexed", %{session: session} do
[block | _] = [block | _] =
for index <- 0..9 do for index <- 0..9 do
insert(:block, number: index) insert(:block, number: index)
end end
start_supervised!(AddressesWithBalanceCounter) BlocksIndexedCounter.calculate_blocks_indexed()
AddressesWithBalanceCounter.consolidate()
assert Explorer.Chain.indexed_ratio() == 1.0 assert Explorer.Chain.indexed_ratio() == 1.0
@ -96,7 +97,7 @@ defmodule BlockScoutWeb.ViewingAppTest do
|> insert() |> insert()
|> with_block(block, internal_transactions_indexed_at: DateTime.utc_now()) |> with_block(block, internal_transactions_indexed_at: DateTime.utc_now())
Notifier.handle_event({:chain_event, :blocks, :catchup, []}) BlocksIndexedCounter.calculate_blocks_indexed()
refute_has(session, AppPage.still_indexing?()) refute_has(session, AppPage.still_indexing?())
end end

Loading…
Cancel
Save