diff --git a/apps/block_scout_web/test/block_scout_web/channels/address_channel_test.exs b/apps/block_scout_web/test/block_scout_web/channels/address_channel_test.exs index 2e59c8435c..e6c6d623a6 100644 --- a/apps/block_scout_web/test/block_scout_web/channels/address_channel_test.exs +++ b/apps/block_scout_web/test/block_scout_web/channels/address_channel_test.exs @@ -17,7 +17,7 @@ defmodule BlockScoutWeb.AddressChannelTest do Notifier.handle_event({:chain_event, :addresses, :realtime, [address]}) - assert_receive %Phoenix.Socket.Broadcast{topic: ^topic, event: "count", payload: %{count: _}}, 5_000 + assert_receive %Phoenix.Socket.Broadcast{topic: ^topic, event: "count", payload: %{count: _}}, :timer.seconds(5) end describe "user subscribed to address" do @@ -36,7 +36,9 @@ defmodule BlockScoutWeb.AddressChannelTest do Notifier.handle_event({:chain_event, :addresses, :realtime, [address_with_balance]}) - assert_receive %Phoenix.Socket.Broadcast{topic: ^topic, event: "balance_update", payload: payload}, 5_000 + assert_receive %Phoenix.Socket.Broadcast{topic: ^topic, event: "balance_update", payload: payload}, + :timer.seconds(5) + assert payload.address.hash == address_with_balance.hash end @@ -54,7 +56,9 @@ defmodule BlockScoutWeb.AddressChannelTest do Notifier.handle_event({:chain_event, :transactions, :realtime, [pending.hash]}) - assert_receive %Phoenix.Socket.Broadcast{topic: ^topic, event: "pending_transaction", payload: payload}, 5_000 + assert_receive %Phoenix.Socket.Broadcast{topic: ^topic, event: "pending_transaction", payload: payload}, + :timer.seconds(5) + assert payload.address.hash == address.hash assert payload.transaction.hash == pending.hash end @@ -67,7 +71,7 @@ defmodule BlockScoutWeb.AddressChannelTest do Notifier.handle_event({:chain_event, :transactions, :realtime, [transaction.hash]}) - assert_receive %Phoenix.Socket.Broadcast{topic: ^topic, event: "transaction", payload: payload}, 5_000 + assert_receive %Phoenix.Socket.Broadcast{topic: ^topic, event: "transaction", payload: payload}, :timer.seconds(5) assert payload.address.hash == address.hash assert payload.transaction.hash == transaction.hash end @@ -80,7 +84,7 @@ defmodule BlockScoutWeb.AddressChannelTest do Notifier.handle_event({:chain_event, :transactions, :realtime, [transaction.hash]}) - assert_receive %Phoenix.Socket.Broadcast{topic: ^topic, event: "transaction", payload: payload}, 5_000 + assert_receive %Phoenix.Socket.Broadcast{topic: ^topic, event: "transaction", payload: payload}, :timer.seconds(5) assert payload.address.hash == address.hash assert payload.transaction.hash == transaction.hash end @@ -93,7 +97,7 @@ defmodule BlockScoutWeb.AddressChannelTest do Notifier.handle_event({:chain_event, :transactions, :realtime, [transaction.hash]}) - assert_receive %Phoenix.Socket.Broadcast{topic: ^topic, event: "transaction", payload: payload}, 5_000 + assert_receive %Phoenix.Socket.Broadcast{topic: ^topic, event: "transaction", payload: payload}, :timer.seconds(5) assert payload.address.hash == address.hash assert payload.transaction.hash == transaction.hash @@ -118,7 +122,7 @@ defmodule BlockScoutWeb.AddressChannelTest do internal_transaction: %{transaction_hash: transaction_hash, index: index} } }, - 5_000 + :timer.seconds(5) assert address_hash == address.hash assert {transaction_hash, index} == {internal_transaction.transaction_hash, internal_transaction.index} @@ -142,7 +146,7 @@ defmodule BlockScoutWeb.AddressChannelTest do internal_transaction: %{transaction_hash: transaction_hash, index: index} } }, - 5_000 + :timer.seconds(5) assert address_hash == address.hash assert {transaction_hash, index} == {internal_transaction.transaction_hash, internal_transaction.index} @@ -170,7 +174,7 @@ defmodule BlockScoutWeb.AddressChannelTest do internal_transaction: %{transaction_hash: transaction_hash, index: index} } }, - 5_000 + :timer.seconds(5) assert address_hash == address.hash assert {transaction_hash, index} == {internal_transaction.transaction_hash, internal_transaction.index} diff --git a/apps/block_scout_web/test/block_scout_web/channels/block_channel_test.exs b/apps/block_scout_web/test/block_scout_web/channels/block_channel_test.exs index c5848597e8..dd1d281a9a 100644 --- a/apps/block_scout_web/test/block_scout_web/channels/block_channel_test.exs +++ b/apps/block_scout_web/test/block_scout_web/channels/block_channel_test.exs @@ -15,7 +15,7 @@ defmodule BlockScoutWeb.BlockChannelTest do %Phoenix.Socket.Broadcast{topic: ^topic, event: "new_block", payload: %{block: _}} -> assert true after - 5_000 -> + :timer.seconds(5) -> assert false, "Expected message received nothing." end end @@ -30,7 +30,7 @@ defmodule BlockScoutWeb.BlockChannelTest do %Phoenix.Socket.Broadcast{topic: ^topic, event: "index_status", payload: %{}} -> assert true after - 5_000 -> + :timer.seconds(5) -> assert false, "Expected message received nothing." end end diff --git a/apps/block_scout_web/test/block_scout_web/channels/exchange_rate_channel_test.exs b/apps/block_scout_web/test/block_scout_web/channels/exchange_rate_channel_test.exs index 704f4170b3..7c495e6bfc 100644 --- a/apps/block_scout_web/test/block_scout_web/channels/exchange_rate_channel_test.exs +++ b/apps/block_scout_web/test/block_scout_web/channels/exchange_rate_channel_test.exs @@ -52,7 +52,7 @@ defmodule BlockScoutWeb.ExchangeRateChannelTest do assert payload.exchange_rate == token assert payload.market_history_data == [] after - 5_000 -> + :timer.seconds(5) -> assert false, "Expected message received nothing." end end @@ -84,7 +84,7 @@ defmodule BlockScoutWeb.ExchangeRateChannelTest do assert payload.exchange_rate == token assert payload.market_history_data == records after - 5_000 -> + :timer.seconds(5) -> assert false, "Expected message received nothing." end end diff --git a/apps/block_scout_web/test/block_scout_web/channels/transaction_channel_test.exs b/apps/block_scout_web/test/block_scout_web/channels/transaction_channel_test.exs index 2488855188..519658875b 100644 --- a/apps/block_scout_web/test/block_scout_web/channels/transaction_channel_test.exs +++ b/apps/block_scout_web/test/block_scout_web/channels/transaction_channel_test.exs @@ -19,7 +19,7 @@ defmodule BlockScoutWeb.TransactionChannelTest do %Phoenix.Socket.Broadcast{topic: ^topic, event: "transaction", payload: payload} -> assert payload.transaction.hash == transaction.hash after - 5_000 -> + :timer.seconds(5) -> assert false, "Expected message received nothing." end end @@ -36,7 +36,7 @@ defmodule BlockScoutWeb.TransactionChannelTest do %Phoenix.Socket.Broadcast{topic: ^topic, event: "pending_transaction", payload: payload} -> assert payload.transaction.hash == pending.hash after - 5_000 -> + :timer.seconds(5) -> assert false, "Expected message received nothing." end end @@ -56,7 +56,7 @@ defmodule BlockScoutWeb.TransactionChannelTest do %Phoenix.Socket.Broadcast{topic: ^topic, event: "collated", payload: %{}} -> assert true after - 5_000 -> + :timer.seconds(5) -> assert false, "Expected message received nothing." end end diff --git a/apps/explorer/config/config.exs b/apps/explorer/config/config.exs index d5ccdaa619..d40551bbfc 100644 --- a/apps/explorer/config/config.exs +++ b/apps/explorer/config/config.exs @@ -21,7 +21,7 @@ config :explorer, Explorer.Counters.BlockValidationCounter, enabled: true, enabl config :explorer, Explorer.ExchangeRates, enabled: true, store: :ets -config :explorer, Explorer.Integrations.EctoLogger, query_time_ms_threshold: 2_000 +config :explorer, Explorer.Integrations.EctoLogger, query_time_ms_threshold: :timer.seconds(2) config :explorer, Explorer.Market.History.Cataloger, enabled: true diff --git a/apps/explorer/config/dev.exs b/apps/explorer/config/dev.exs index 34e1a357af..95019470fc 100644 --- a/apps/explorer/config/dev.exs +++ b/apps/explorer/config/dev.exs @@ -5,7 +5,7 @@ config :explorer, Explorer.Repo, database: "explorer_dev", hostname: "localhost", pool_size: 20, - timeout: 80_000 + timeout: :timer.seconds(80) config :explorer, Explorer.Tracer, env: "dev", disabled?: true diff --git a/apps/explorer/config/dev/ganache.exs b/apps/explorer/config/dev/ganache.exs index f9ed96fb0e..fec954d325 100644 --- a/apps/explorer/config/dev/ganache.exs +++ b/apps/explorer/config/dev/ganache.exs @@ -6,7 +6,7 @@ config :explorer, transport_options: [ http: EthereumJSONRPC.HTTP.HTTPoison, url: System.get_env("ETHEREUM_JSONRPC_HTTP_URL") || "http://localhost:7545", - http_options: [recv_timeout: 60_000, timeout: 60_000, hackney: [pool: :ethereum_jsonrpc]] + http_options: [recv_timeout: :timer.minutes(1), timeout: :timer.minutes(1), hackney: [pool: :ethereum_jsonrpc]] ], variant: EthereumJSONRPC.Ganache ], diff --git a/apps/explorer/config/dev/geth.exs b/apps/explorer/config/dev/geth.exs index 6bdba9a0b0..5d57d1a3f2 100644 --- a/apps/explorer/config/dev/geth.exs +++ b/apps/explorer/config/dev/geth.exs @@ -6,7 +6,7 @@ config :explorer, transport_options: [ http: EthereumJSONRPC.HTTP.HTTPoison, url: System.get_env("ETHEREUM_JSONRPC_HTTP_URL") || "https://mainnet.infura.io/8lTvJTKmHPCHazkneJsY", - http_options: [recv_timeout: 60_000, timeout: 60_000, hackney: [pool: :ethereum_jsonrpc]] + http_options: [recv_timeout: :timer.minutes(1), timeout: :timer.minutes(1), hackney: [pool: :ethereum_jsonrpc]] ], variant: EthereumJSONRPC.Geth ], diff --git a/apps/explorer/config/dev/parity.exs b/apps/explorer/config/dev/parity.exs index d503892fe0..7f92c092cc 100644 --- a/apps/explorer/config/dev/parity.exs +++ b/apps/explorer/config/dev/parity.exs @@ -11,7 +11,7 @@ config :explorer, eth_getBalance: System.get_env("ETHEREUM_JSONRPC_TRACE_URL") || "http://localhost:8545", trace_replayTransaction: System.get_env("ETHEREUM_JSONRPC_TRACE_URL") || "http://localhost:8545" ], - http_options: [recv_timeout: 60_000, timeout: 60_000, hackney: [pool: :ethereum_jsonrpc]] + http_options: [recv_timeout: :timer.minutes(1), timeout: :timer.minutes(1), hackney: [pool: :ethereum_jsonrpc]] ], variant: EthereumJSONRPC.Parity ], diff --git a/apps/explorer/config/prod.exs b/apps/explorer/config/prod.exs index 29a377d219..0957ffa1f7 100644 --- a/apps/explorer/config/prod.exs +++ b/apps/explorer/config/prod.exs @@ -6,7 +6,7 @@ config :explorer, Explorer.Repo, pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"), ssl: String.equivalent?(System.get_env("ECTO_USE_SSL") || "true", "true"), prepare: :unnamed, - timeout: 60_000 + timeout: :timer.seconds(60) config :explorer, Explorer.Tracer, env: "production", disabled?: true diff --git a/apps/explorer/config/prod/ganache.exs b/apps/explorer/config/prod/ganache.exs index f9ed96fb0e..fec954d325 100644 --- a/apps/explorer/config/prod/ganache.exs +++ b/apps/explorer/config/prod/ganache.exs @@ -6,7 +6,7 @@ config :explorer, transport_options: [ http: EthereumJSONRPC.HTTP.HTTPoison, url: System.get_env("ETHEREUM_JSONRPC_HTTP_URL") || "http://localhost:7545", - http_options: [recv_timeout: 60_000, timeout: 60_000, hackney: [pool: :ethereum_jsonrpc]] + http_options: [recv_timeout: :timer.minutes(1), timeout: :timer.minutes(1), hackney: [pool: :ethereum_jsonrpc]] ], variant: EthereumJSONRPC.Ganache ], diff --git a/apps/explorer/config/prod/geth.exs b/apps/explorer/config/prod/geth.exs index 6bdba9a0b0..5d57d1a3f2 100644 --- a/apps/explorer/config/prod/geth.exs +++ b/apps/explorer/config/prod/geth.exs @@ -6,7 +6,7 @@ config :explorer, transport_options: [ http: EthereumJSONRPC.HTTP.HTTPoison, url: System.get_env("ETHEREUM_JSONRPC_HTTP_URL") || "https://mainnet.infura.io/8lTvJTKmHPCHazkneJsY", - http_options: [recv_timeout: 60_000, timeout: 60_000, hackney: [pool: :ethereum_jsonrpc]] + http_options: [recv_timeout: :timer.minutes(1), timeout: :timer.minutes(1), hackney: [pool: :ethereum_jsonrpc]] ], variant: EthereumJSONRPC.Geth ], diff --git a/apps/explorer/config/prod/parity.exs b/apps/explorer/config/prod/parity.exs index 3e5c8ca64d..68c1d14fdf 100644 --- a/apps/explorer/config/prod/parity.exs +++ b/apps/explorer/config/prod/parity.exs @@ -11,7 +11,7 @@ config :explorer, eth_getBalance: System.get_env("ETHEREUM_JSONRPC_TRACE_URL"), trace_replayTransaction: System.get_env("ETHEREUM_JSONRPC_TRACE_URL") ], - http_options: [recv_timeout: 60_000, timeout: 60_000, hackney: [pool: :ethereum_jsonrpc]] + http_options: [recv_timeout: :timer.minutes(1), timeout: :timer.minutes(1), hackney: [pool: :ethereum_jsonrpc]] ], variant: EthereumJSONRPC.Parity ], diff --git a/apps/explorer/config/test.exs b/apps/explorer/config/test.exs index 194b2f2ccc..aa8bb02dd1 100644 --- a/apps/explorer/config/test.exs +++ b/apps/explorer/config/test.exs @@ -9,7 +9,7 @@ config :explorer, Explorer.Repo, hostname: "localhost", pool: Ecto.Adapters.SQL.Sandbox, # Default of `5_000` was too low for `BlockFetcher` test - ownership_timeout: 60_000 + ownership_timeout: :timer.minutes(1) config :explorer, Explorer.ExchangeRates, enabled: false, store: :ets diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index 6bf306c0ce..ce4b897681 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -1245,76 +1245,69 @@ defmodule Explorer.Chain do def missing_block_number_ranges(range) def missing_block_number_ranges(range_start..range_end) do - # subquery so we can check for NULL in `range_min_query`, which happens for empty table - min_query = from(block in Block, select: %{number: min(block.number)}, where: block.consensus == true) - # this acts a fake found block, so it has to before the range of blocks we actually care to check - before_range_min = min(range_start, range_end) - 1 + range_min = min(range_start, range_end) + range_max = max(range_start, range_end) - range_min_query = - from(min_block in subquery(min_query), - select: %{ - # `LEAST` ignores `NULL`, so it picks the fake range when there is no `min_block.number` - # because `blocks` is empty - number: fragment("LEAST(?, ?)", min_block.number, ^before_range_min) - }, - # `blocks` is empty - # same number will not be returned by `number_query` - where: is_nil(min_block.number) or min_block.number != ^before_range_min + missing_prefix_query = + from(block in Block, + select: %{min: type(^range_min, block.number), max: min(block.number) - 1}, + where: block.consensus == true, + having: ^range_min < min(block.number) and min(block.number) < ^range_max ) - number_query = from(block in Block, select: %{number: block.number}, where: block.consensus == true) - - # subquery so we can check for NULL in `range_max_query`, which happens for empty table - max_query = from(block in Block, select: %{number: max(block.number)}, where: block.consensus == true) - # this acts a fake found block, so it has to after the range of blocks we actually care to check - after_range_max = max(range_start, range_end) + 1 - - range_max_query = - from(max_block in subquery(max_query), - select: %{ - # `GREATEST` ignores `NULL`, so it picks the fake range when there is no `max_block.number` - # because `blocks` is empty - number: fragment("GREATEST(?, ?)", max_block.number, ^after_range_max) - }, - # blocks is empty - # same number will not be returned by `number_query` - where: is_nil(max_block.number) or max_block.number != ^after_range_max + missing_suffix_query = + from(block in Block, + select: %{min: max(block.number) + 1, max: type(^range_max, block.number)}, + where: block.consensus == true, + having: ^range_min < max(block.number) and max(block.number) < ^range_max ) - # The actual blocks and a boundary of fake found blocks outside of `range_start..range_end` so that there is always - # a `lag` block - search_range_query = - number_query - |> union_all(^range_min_query) - |> union_all(^range_max_query) + missing_infix_query = + from(block in Block, + select: %{min: type(^range_min, block.number), max: type(^range_max, block.number)}, + where: block.consensus == true, + having: + (is_nil(min(block.number)) and is_nil(max(block.number))) or + (^range_max < min(block.number) or max(block.number) < ^range_min) + ) # Gaps and Islands is the term-of-art for finding the runs of missing (gaps) and existing (islands) data. If you # Google for `sql missing ranges` you won't find much, but `sql gaps and islands` will get a lot of hits. - island_query = - from( - search_block in subquery(search_range_query), - windows: [w: [order_by: search_block.number]], - select: %{last_number: search_block.number |> lag() |> over(:w), next_number: search_block.number} + land_query = + from(block in Block, + where: block.consensus == true and ^range_min <= block.number and block.number <= ^range_max, + windows: [w: [order_by: block.number]], + select: %{last_number: block.number |> lag() |> over(:w), next_number: block.number} ) gap_query = from( - island in subquery(island_query), - where: island.last_number != island.next_number - 1, - select: %Range{first: island.last_number + 1, last: island.next_number - 1}, - order_by: island.last_number + coastline in subquery(land_query), + where: coastline.last_number != coastline.next_number - 1, + select: %{min: coastline.last_number + 1, max: coastline.next_number - 1} ) - ascending = Repo.all(gap_query, timeout: :infinity) + missing_query = + missing_prefix_query + |> union_all(^missing_infix_query) + |> union_all(^gap_query) + |> union_all(^missing_suffix_query) + + {first, last, direction} = + if range_start <= range_end do + {:min, :max, :asc} + else + {:max, :min, :desc} + end - if range_start <= range_end do - ascending - else - ascending - |> Enum.reverse() - |> Enum.map(fn first..last -> last..first end) - end + ordered_missing_query = + from(missing_range in subquery(missing_query), + select: %Range{first: field(missing_range, ^first), last: field(missing_range, ^last)}, + order_by: [{^direction, field(missing_range, ^first)}] + ) + + Repo.all(ordered_missing_query, timeout: :infinity) end @doc """ diff --git a/apps/explorer/lib/explorer/chain/import.ex b/apps/explorer/lib/explorer/chain/import.ex index ac9295fca3..50964e8751 100644 --- a/apps/explorer/lib/explorer/chain/import.ex +++ b/apps/explorer/lib/explorer/chain/import.ex @@ -60,7 +60,7 @@ defmodule Explorer.Chain.Import do @type timestamps :: %{inserted_at: DateTime.t(), updated_at: DateTime.t()} # milliseconds - @transaction_timeout 120_000 + @transaction_timeout :timer.minutes(4) @imported_table_rows @runners |> Stream.map(&Map.put(&1.imported_table_row(), :key, &1.option_key())) diff --git a/apps/explorer/lib/explorer/chain/import/runner/blocks.ex b/apps/explorer/lib/explorer/chain/import/runner/blocks.ex index 9f24d0be7b..5917ae9968 100644 --- a/apps/explorer/lib/explorer/chain/import/runner/blocks.ex +++ b/apps/explorer/lib/explorer/chain/import/runner/blocks.ex @@ -133,6 +133,9 @@ defmodule Explorer.Chain.Import.Runner.Blocks do insert_sql = """ INSERT INTO transaction_forks (uncle_hash, index, hash, inserted_at, updated_at) #{select_sql} + ON CONFLICT (uncle_hash, index) + DO UPDATE SET hash = EXCLUDED.hash + WHERE EXCLUDED.hash <> transaction_forks.hash RETURNING uncle_hash, hash """ diff --git a/apps/explorer/test/explorer/chain/import/runner/blocks_test.exs b/apps/explorer/test/explorer/chain/import/runner/blocks_test.exs new file mode 100644 index 0000000000..cba86e999a --- /dev/null +++ b/apps/explorer/test/explorer/chain/import/runner/blocks_test.exs @@ -0,0 +1,84 @@ +defmodule Explorer.Chain.Import.Runner.BlocksTest do + use Explorer.DataCase + + import Ecto.Query, only: [from: 2, select: 2, where: 2] + + alias Ecto.Multi + alias Explorer.Chain.Import.Runner.{Blocks, Transaction} + alias Explorer.Chain.{Block, Transaction} + alias Explorer.Repo + + describe "run/1" do + setup do + block = insert(:block, consensus: true) + + transaction = + :transaction + |> insert() + |> with_block(block) + + %{consensus_block: block, transaction: transaction} + end + + test "derive_transaction_forks replaces hash on conflicting (uncle_hash, index)", %{ + consensus_block: %Block{hash: block_hash, miner_hash: miner_hash, number: block_number}, + transaction: transaction + } do + block_params = + params_for(:block, hash: block_hash, miner_hash: miner_hash, number: block_number, consensus: false) + + %Ecto.Changeset{valid?: true, changes: block_changes} = Block.changeset(%Block{}, block_params) + changes_list = [block_changes] + + timestamp = DateTime.utc_now() + options = %{timestamps: %{inserted_at: timestamp, updated_at: timestamp}} + + assert Repo.aggregate(from(transaction in Transaction, where: is_nil(transaction.block_number)), :count, :hash) == + 0 + + assert count(Transaction.Fork) == 0 + + # re-org consensus_block to uncle + + assert {:ok, %{derive_transaction_forks: [_]}} = + Multi.new() + |> Blocks.run(changes_list, options) + |> Repo.transaction() + + assert Repo.aggregate(where(Block, consensus: false), :count, :number) == 1 + + assert Repo.aggregate(from(transaction in Transaction, where: is_nil(transaction.block_number)), :count, :hash) == + 1 + + assert count(Transaction.Fork) == 1 + + non_consensus_transaction = Repo.get(Transaction, transaction.hash) + non_consensus_block = Repo.get(Block, block_hash) + + # Make it consensus again + new_consensus_block = + non_consensus_block + |> Block.changeset(%{consensus: true}) + |> Repo.update!() + + with_block(non_consensus_transaction, new_consensus_block) + + ctid = Repo.one!(from(transaction_fork in Transaction.Fork, select: "ctid")) + + assert Repo.aggregate(from(transaction in Transaction, where: is_nil(transaction.block_number)), :count, :hash) == + 0 + + assert {:ok, %{derive_transaction_forks: []}} = + Multi.new() + |> Blocks.run(changes_list, options) + |> Repo.transaction() + + assert Repo.one!(from(transaction_fork in Transaction.Fork, select: "ctid")) == ctid, + "Tuple was written even though it is not distinct" + end + end + + defp count(schema) do + Repo.one!(select(schema, fragment("COUNT(*)"))) + end +end diff --git a/apps/explorer/test/explorer/chain_test.exs b/apps/explorer/test/explorer/chain_test.exs index b49bfd844e..83f4bf3883 100644 --- a/apps/explorer/test/explorer/chain_test.exs +++ b/apps/explorer/test/explorer/chain_test.exs @@ -2191,6 +2191,117 @@ defmodule Explorer.ChainTest do end end + describe "missing_block_number_ranges/1" do + # 0000 + test "0..0 without blocks" do + assert Chain.missing_block_number_ranges(0..0) == [0..0] + end + + # 0001 + test "0..0 with block 3" do + insert(:block, number: 3) + + assert Chain.missing_block_number_ranges(0..0) == [0..0] + end + + # 0010 + test "0..0 with block 2" do + insert(:block, number: 2) + + assert Chain.missing_block_number_ranges(0..0) == [0..0] + end + + # 0011 + test "0..0 with blocks 2,3" do + Enum.each([2, 3], &insert(:block, number: &1)) + + assert Chain.missing_block_number_ranges(0..0) == [0..0] + end + + # 0100 + test "0..0 with block 1" do + insert(:block, number: 1) + + assert Chain.missing_block_number_ranges(0..0) == [0..0] + end + + # 0101 + test "0..0 with blocks 1,3" do + Enum.each([1, 3], &insert(:block, number: &1)) + + assert Chain.missing_block_number_ranges(0..0) == [0..0] + end + + # 0111 + test "0..0 with blocks 1..3" do + Enum.each(1..3, &insert(:block, number: &1)) + + assert Chain.missing_block_number_ranges(0..0) == [0..0] + end + + # 1000 + test "0..0 with block 0" do + insert(:block, number: 0) + + assert Chain.missing_block_number_ranges(0..0) == [] + end + + # 1001 + test "0..0 with blocks 0,3" do + Enum.each([0, 3], &insert(:block, number: &1)) + + assert Chain.missing_block_number_ranges(0..0) == [] + end + + # 1010 + test "0..0 with blocks 0,2" do + Enum.each([0, 2], &insert(:block, number: &1)) + + assert Chain.missing_block_number_ranges(0..0) == [] + end + + # 1011 + test "0..0 with blocks 0,2,3" do + Enum.each([0, 2, 3], &insert(:block, number: &1)) + + assert Chain.missing_block_number_ranges(0..0) == [] + end + + # 1100 + test "0..0 with blocks 0..1" do + Enum.each(0..1, &insert(:block, number: &1)) + + assert Chain.missing_block_number_ranges(0..0) == [] + end + + # 1101 + test "0..0 with blocks 0,1,3" do + Enum.each([0, 1, 3], &insert(:block, number: &1)) + + assert Chain.missing_block_number_ranges(0..0) == [] + end + + # 1110 + test "0..0 with blocks 0..2" do + Enum.each(0..2, &insert(:block, number: &1)) + + assert Chain.missing_block_number_ranges(0..0) == [] + end + + # 1111 + test "0..0 with blocks 0..3" do + Enum.each(0..2, &insert(:block, number: &1)) + + assert Chain.missing_block_number_ranges(0..0) == [] + end + + test "0..2 with block 1" do + insert(:block, number: 1) + + assert Chain.missing_block_number_ranges(0..2) == [0..0, 2..2] + end + end + describe "recent_collated_transactions/1" do test "with no collated transactions it returns an empty list" do assert [] == Explorer.Chain.recent_collated_transactions() diff --git a/apps/indexer/config/dev/ganache.exs b/apps/indexer/config/dev/ganache.exs index 174ba47d4f..337c2317c6 100644 --- a/apps/indexer/config/dev/ganache.exs +++ b/apps/indexer/config/dev/ganache.exs @@ -1,13 +1,13 @@ use Mix.Config config :indexer, - block_interval: 5_000, + block_interval: :timer.seconds(5), json_rpc_named_arguments: [ transport: EthereumJSONRPC.HTTP, transport_options: [ http: EthereumJSONRPC.HTTP.HTTPoison, url: System.get_env("ETHEREUM_JSONRPC_HTTP_URL") || "http://localhost:7545", - http_options: [recv_timeout: 60_000, timeout: 60_000, hackney: [pool: :ethereum_jsonrpc]] + http_options: [recv_timeout: :timer.minutes(1), timeout: :timer.minutes(1), hackney: [pool: :ethereum_jsonrpc]] ], variant: EthereumJSONRPC.Ganache ], diff --git a/apps/indexer/config/dev/geth.exs b/apps/indexer/config/dev/geth.exs index 4950dccd3f..cf1113119d 100644 --- a/apps/indexer/config/dev/geth.exs +++ b/apps/indexer/config/dev/geth.exs @@ -1,13 +1,13 @@ use Mix.Config config :indexer, - block_interval: 5_000, + block_interval: :timer.seconds(5), json_rpc_named_arguments: [ transport: EthereumJSONRPC.HTTP, transport_options: [ http: EthereumJSONRPC.HTTP.HTTPoison, url: System.get_env("ETHEREUM_JSONRPC_HTTP_URL") || "https://mainnet.infura.io/8lTvJTKmHPCHazkneJsY", - http_options: [recv_timeout: 60_000, timeout: 60_000, hackney: [pool: :ethereum_jsonrpc]] + http_options: [recv_timeout: :timer.minutes(1), timeout: :timer.minutes(1), hackney: [pool: :ethereum_jsonrpc]] ], variant: EthereumJSONRPC.Geth ], diff --git a/apps/indexer/config/dev/parity.exs b/apps/indexer/config/dev/parity.exs index e903be4141..b63f1d8ccf 100644 --- a/apps/indexer/config/dev/parity.exs +++ b/apps/indexer/config/dev/parity.exs @@ -1,7 +1,7 @@ use Mix.Config config :indexer, - block_interval: 5_000, + block_interval: :timer.seconds(5), json_rpc_named_arguments: [ transport: EthereumJSONRPC.HTTP, transport_options: [ @@ -12,7 +12,7 @@ config :indexer, trace_block: System.get_env("ETHEREUM_JSONRPC_TRACE_URL") || "http://localhost:8545", trace_replayTransaction: System.get_env("ETHEREUM_JSONRPC_TRACE_URL") || "http://localhost:8545" ], - http_options: [recv_timeout: 60_000, timeout: 60_000, hackney: [pool: :ethereum_jsonrpc]] + http_options: [recv_timeout: :timer.minutes(1), timeout: :timer.minutes(1), hackney: [pool: :ethereum_jsonrpc]] ], variant: EthereumJSONRPC.Parity ], diff --git a/apps/indexer/config/prod/ganache.exs b/apps/indexer/config/prod/ganache.exs index 174ba47d4f..337c2317c6 100644 --- a/apps/indexer/config/prod/ganache.exs +++ b/apps/indexer/config/prod/ganache.exs @@ -1,13 +1,13 @@ use Mix.Config config :indexer, - block_interval: 5_000, + block_interval: :timer.seconds(5), json_rpc_named_arguments: [ transport: EthereumJSONRPC.HTTP, transport_options: [ http: EthereumJSONRPC.HTTP.HTTPoison, url: System.get_env("ETHEREUM_JSONRPC_HTTP_URL") || "http://localhost:7545", - http_options: [recv_timeout: 60_000, timeout: 60_000, hackney: [pool: :ethereum_jsonrpc]] + http_options: [recv_timeout: :timer.minutes(1), timeout: :timer.minutes(1), hackney: [pool: :ethereum_jsonrpc]] ], variant: EthereumJSONRPC.Ganache ], diff --git a/apps/indexer/config/prod/geth.exs b/apps/indexer/config/prod/geth.exs index 4950dccd3f..cf1113119d 100644 --- a/apps/indexer/config/prod/geth.exs +++ b/apps/indexer/config/prod/geth.exs @@ -1,13 +1,13 @@ use Mix.Config config :indexer, - block_interval: 5_000, + block_interval: :timer.seconds(5), json_rpc_named_arguments: [ transport: EthereumJSONRPC.HTTP, transport_options: [ http: EthereumJSONRPC.HTTP.HTTPoison, url: System.get_env("ETHEREUM_JSONRPC_HTTP_URL") || "https://mainnet.infura.io/8lTvJTKmHPCHazkneJsY", - http_options: [recv_timeout: 60_000, timeout: 60_000, hackney: [pool: :ethereum_jsonrpc]] + http_options: [recv_timeout: :timer.minutes(1), timeout: :timer.minutes(1), hackney: [pool: :ethereum_jsonrpc]] ], variant: EthereumJSONRPC.Geth ], diff --git a/apps/indexer/config/prod/parity.exs b/apps/indexer/config/prod/parity.exs index 463dc3f079..8c12ff4485 100644 --- a/apps/indexer/config/prod/parity.exs +++ b/apps/indexer/config/prod/parity.exs @@ -1,7 +1,7 @@ use Mix.Config config :indexer, - block_interval: 5_000, + block_interval: :timer.seconds(5), json_rpc_named_arguments: [ transport: EthereumJSONRPC.HTTP, transport_options: [ @@ -12,7 +12,7 @@ config :indexer, trace_block: System.get_env("ETHEREUM_JSONRPC_TRACE_URL"), trace_replayTransaction: System.get_env("ETHEREUM_JSONRPC_TRACE_URL") ], - http_options: [recv_timeout: 60_000, timeout: 60_000, hackney: [pool: :ethereum_jsonrpc]] + http_options: [recv_timeout: :timer.minutes(1), timeout: :timer.minutes(1), hackney: [pool: :ethereum_jsonrpc]] ], variant: EthereumJSONRPC.Parity ], diff --git a/apps/indexer/test/indexer/block/fetcher_test.exs b/apps/indexer/test/indexer/block/fetcher_test.exs index 0328abf028..2529df75e0 100644 --- a/apps/indexer/test/indexer/block/fetcher_test.exs +++ b/apps/indexer/test/indexer/block/fetcher_test.exs @@ -611,7 +611,7 @@ defmodule Indexer.Block.FetcherTest do end defp wait_for_tasks(buffered_task) do - wait_until(10_000, fn -> + wait_until(:timer.seconds(10), fn -> counts = BufferedTask.debug_count(buffered_task) counts.buffer == 0 and counts.tasks == 0 end) diff --git a/apps/indexer/test/indexer/sequence_test.exs b/apps/indexer/test/indexer/sequence_test.exs index b7ed8f9ab3..49933c85fb 100644 --- a/apps/indexer/test/indexer/sequence_test.exs +++ b/apps/indexer/test/indexer/sequence_test.exs @@ -16,7 +16,7 @@ defmodule Indexer.SequenceTest do {child_pid, child_ref} = spawn_monitor(fn -> Sequence.start_link(first: 1, step: -1) - Process.sleep(5_000) + Process.sleep(:timer.seconds(5)) end) assert_receive {:DOWN, ^child_ref, :process, ^child_pid, @@ -27,7 +27,7 @@ defmodule Indexer.SequenceTest do {child_pid, child_ref} = spawn_monitor(fn -> Sequence.start_link(step: -1) - Process.sleep(5_000) + Process.sleep(:timer.seconds(5)) end) assert_receive {:DOWN, ^child_ref, :process, ^child_pid, "either :ranges or :first must be set"} @@ -47,7 +47,7 @@ defmodule Indexer.SequenceTest do {child_pid, child_ref} = spawn_monitor(fn -> Sequence.start_link(ranges: [1..0], first: 1, step: -1) - Process.sleep(5_000) + Process.sleep(:timer.seconds(5)) end) assert_receive {:DOWN, ^child_ref, :process, ^child_pid,