diff --git a/apps/block_scout_web/lib/block_scout_web/counters/blocks_indexed_counter.ex b/apps/block_scout_web/lib/block_scout_web/counters/blocks_indexed_counter.ex index eab9a96af8..1e7d7f0746 100644 --- a/apps/block_scout_web/lib/block_scout_web/counters/blocks_indexed_counter.ex +++ b/apps/block_scout_web/lib/block_scout_web/counters/blocks_indexed_counter.ex @@ -39,10 +39,9 @@ defmodule BlockScoutWeb.Counters.BlocksIndexedCounter do ratio = Chain.indexed_ratio() finished? = - if ratio < 1 do - false - else - Chain.finished_indexing?() + case Decimal.cmp(ratio, 1) do + :lt -> false + _ -> Chain.finished_indexing?() end Notifier.broadcast_blocks_indexed_ratio(ratio, finished?) diff --git a/apps/block_scout_web/test/block_scout_web/features/viewing_app_test.exs b/apps/block_scout_web/test/block_scout_web/features/viewing_app_test.exs index af303bff17..27742d31eb 100644 --- a/apps/block_scout_web/test/block_scout_web/features/viewing_app_test.exs +++ b/apps/block_scout_web/test/block_scout_web/features/viewing_app_test.exs @@ -20,7 +20,7 @@ defmodule BlockScoutWeb.ViewingAppTest do insert(:block, number: index) end - assert Explorer.Chain.indexed_ratio() == 0.5 + assert Decimal.cmp(Explorer.Chain.indexed_ratio(), Decimal.from_float(0.5)) == :eq session |> AppPage.visit_page() @@ -32,7 +32,7 @@ defmodule BlockScoutWeb.ViewingAppTest do insert(:block, number: index) end - assert Explorer.Chain.indexed_ratio() == 1.0 + assert Decimal.cmp(Explorer.Chain.indexed_ratio(), 1) == :eq session |> AppPage.visit_page() @@ -46,7 +46,7 @@ defmodule BlockScoutWeb.ViewingAppTest do BlocksIndexedCounter.calculate_blocks_indexed() - assert Explorer.Chain.indexed_ratio() == 0.5 + assert Decimal.cmp(Explorer.Chain.indexed_ratio(), Decimal.from_float(0.5)) == :eq session |> AppPage.visit_page() @@ -66,7 +66,7 @@ defmodule BlockScoutWeb.ViewingAppTest do BlocksIndexedCounter.calculate_blocks_indexed() - assert Explorer.Chain.indexed_ratio() == 0.9 + assert Decimal.cmp(Explorer.Chain.indexed_ratio(), Decimal.from_float(0.9)) == :eq session |> AppPage.visit_page() @@ -87,7 +87,7 @@ defmodule BlockScoutWeb.ViewingAppTest do BlocksIndexedCounter.calculate_blocks_indexed() - assert Explorer.Chain.indexed_ratio() == 1.0 + assert Decimal.cmp(Explorer.Chain.indexed_ratio(), 1) == :eq session |> AppPage.visit_page() diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index 2406b3df27..7875127a77 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -835,23 +835,31 @@ defmodule Explorer.Chain do ...> insert(:block, number: index) ...> end iex> Explorer.Chain.indexed_ratio() - 0.5 + Decimal.new(1, 50000000000000000000, -20) If there are no blocks, the percentage is 0. iex> Explorer.Chain.indexed_ratio() - 0 + Decimal.new(0) """ - @spec indexed_ratio() :: float() + @spec indexed_ratio() :: Decimal.t() def indexed_ratio do - with {:ok, min_block_number} <- consensus_block_number(:min), - {:ok, max_block_number} <- consensus_block_number(:max) do - indexed_blocks = max_block_number - min_block_number + 1 - indexed_blocks / (max_block_number + 1) - else - {:error, _} -> 0 - end + # subquery so we need to cast less + decimal_min_max_query = + from(block in Block, + select: %{min_number: type(min(block.number), :decimal), max_number: type(max(block.number), :decimal)}, + where: block.consensus == true + ) + + query = + from(decimal_min_max in subquery(decimal_min_max_query), + # math on `NULL` returns `NULL` so `coalesce` works as expected + select: + coalesce((decimal_min_max.max_number - decimal_min_max.min_number + 1) / (decimal_min_max.max_number + 1), 0) + ) + + Repo.one!(query) end @doc """ diff --git a/apps/explorer/test/explorer/chain_test.exs b/apps/explorer/test/explorer/chain_test.exs index 0435889f43..c4c23796e0 100644 --- a/apps/explorer/test/explorer/chain_test.exs +++ b/apps/explorer/test/explorer/chain_test.exs @@ -921,11 +921,11 @@ defmodule Explorer.ChainTest do insert(:block, number: index) end - assert 0.5 == Chain.indexed_ratio() + assert Decimal.cmp(Chain.indexed_ratio(), Decimal.from_float(0.5)) == :eq end test "returns 0 if no blocks" do - assert 0 == Chain.indexed_ratio() + assert Decimal.new(0) == Chain.indexed_ratio() end test "returns 1.0 if fully indexed blocks" do @@ -933,7 +933,7 @@ defmodule Explorer.ChainTest do insert(:block, number: index) end - assert 1.0 == Chain.indexed_ratio() + assert Decimal.cmp(Chain.indexed_ratio(), 1) == :eq end end