|
|
|
@ -12,16 +12,24 @@ defmodule Explorer.Chain.Import do |
|
|
|
|
require Logger |
|
|
|
|
|
|
|
|
|
@stages [ |
|
|
|
|
Import.Stage.BlockRelated, |
|
|
|
|
Import.Stage.BlockReferencing, |
|
|
|
|
Import.Stage.BlockFollowing, |
|
|
|
|
Import.Stage.BlockPending, |
|
|
|
|
Import.Stage.ChainTypeSpecific |
|
|
|
|
[ |
|
|
|
|
Import.Stage.Main |
|
|
|
|
], |
|
|
|
|
[ |
|
|
|
|
Import.Stage.BlockTransactionReferencing, |
|
|
|
|
Import.Stage.TokenReferencing, |
|
|
|
|
Import.Stage.InternalTransactions, |
|
|
|
|
Import.Stage.ChainTypeSpecific |
|
|
|
|
] |
|
|
|
|
] |
|
|
|
|
|
|
|
|
|
# in order so that foreign keys are inserted before being referenced |
|
|
|
|
@configured_runners Enum.flat_map(@stages, fn stage -> stage.runners() end) |
|
|
|
|
@all_runners Enum.flat_map(@stages, fn stage -> stage.all_runners() end) |
|
|
|
|
@configured_runners Enum.flat_map(@stages, fn stage_batch -> |
|
|
|
|
Enum.flat_map(stage_batch, fn stage -> stage.runners() end) |
|
|
|
|
end) |
|
|
|
|
@all_runners Enum.flat_map(@stages, fn stage_batch -> |
|
|
|
|
Enum.flat_map(stage_batch, fn stage -> stage.all_runners() end) |
|
|
|
|
end) |
|
|
|
|
|
|
|
|
|
quoted_runner_option_value = |
|
|
|
|
quote do |
|
|
|
@ -283,9 +291,11 @@ defmodule Explorer.Chain.Import do |
|
|
|
|
timestamps = timestamps() |
|
|
|
|
full_options = Map.put(options, :timestamps, timestamps) |
|
|
|
|
|
|
|
|
|
{multis, final_runner_to_changes_list} = |
|
|
|
|
Enum.flat_map_reduce(@stages, runner_to_changes_list, fn stage, remaining_runner_to_changes_list -> |
|
|
|
|
stage.multis(remaining_runner_to_changes_list, full_options) |
|
|
|
|
{multis_batches, final_runner_to_changes_list} = |
|
|
|
|
Enum.map_reduce(@stages, runner_to_changes_list, fn stage_batch, remaining_runner_to_changes_list -> |
|
|
|
|
Enum.flat_map_reduce(stage_batch, remaining_runner_to_changes_list, fn stage, inner_remaining_list -> |
|
|
|
|
stage.multis(inner_remaining_list, full_options) |
|
|
|
|
end) |
|
|
|
|
end) |
|
|
|
|
|
|
|
|
|
unless Enum.empty?(final_runner_to_changes_list) do |
|
|
|
@ -293,7 +303,7 @@ defmodule Explorer.Chain.Import do |
|
|
|
|
"No stages consumed the following runners: #{final_runner_to_changes_list |> Map.keys() |> inspect()}" |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
multis |
|
|
|
|
multis_batches |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
def insert_changes_list(repo, changes_list, options) when is_atom(repo) and is_list(changes_list) do |
|
|
|
@ -337,17 +347,21 @@ defmodule Explorer.Chain.Import do |
|
|
|
|
reraise exception, __STACKTRACE__ |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp logged_import(multis, options) when is_list(multis) and is_map(options) do |
|
|
|
|
defp logged_import(multis_batches, options) when is_list(multis_batches) and is_map(options) do |
|
|
|
|
import_id = :erlang.unique_integer([:positive]) |
|
|
|
|
|
|
|
|
|
Explorer.Logger.metadata(fn -> import_transactions(multis, options) end, import_id: import_id) |
|
|
|
|
Explorer.Logger.metadata(fn -> import_batch_transactions(multis_batches, options) end, import_id: import_id) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp import_transactions(multis, options) when is_list(multis) and is_map(options) do |
|
|
|
|
Enum.reduce_while(multis, {:ok, %{}}, fn multi, {:ok, acc_changes} -> |
|
|
|
|
case import_transaction(multi, options) do |
|
|
|
|
{:ok, changes} -> {:cont, {:ok, Map.merge(acc_changes, changes)}} |
|
|
|
|
{:error, _, _, _} = error -> {:halt, error} |
|
|
|
|
defp import_batch_transactions(multis_batches, options) when is_list(multis_batches) and is_map(options) do |
|
|
|
|
Enum.reduce_while(multis_batches, {:ok, %{}}, fn multis, {:ok, acc_changes} -> |
|
|
|
|
multis |
|
|
|
|
|> run_parallel_multis(options) |
|
|
|
|
|> Task.yield_many(:infinity) |
|
|
|
|
|> handle_task_results(acc_changes) |
|
|
|
|
|> case do |
|
|
|
|
{:ok, changes} -> {:cont, {:ok, changes}} |
|
|
|
|
error -> {:halt, error} |
|
|
|
|
end |
|
|
|
|
end) |
|
|
|
|
rescue |
|
|
|
@ -358,8 +372,26 @@ defmodule Explorer.Chain.Import do |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp run_parallel_multis(multis, options) do |
|
|
|
|
Enum.map(multis, fn multi -> Task.async(fn -> import_transaction(multi, options) end) end) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp import_transaction(multi, options) when is_map(options) do |
|
|
|
|
Repo.logged_transaction(multi, timeout: Map.get(options, :timeout, @transaction_timeout)) |
|
|
|
|
rescue |
|
|
|
|
exception -> {:exception, exception, __STACKTRACE__} |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp handle_task_results(task_results, acc_changes) do |
|
|
|
|
Enum.reduce_while(task_results, {:ok, acc_changes}, fn {_task, task_result}, {:ok, acc_changes_inner} -> |
|
|
|
|
case task_result do |
|
|
|
|
{:ok, {:ok, changes}} -> {:cont, {:ok, Map.merge(acc_changes_inner, changes)}} |
|
|
|
|
{:ok, {:exception, exception, stacktrace}} -> reraise exception, stacktrace |
|
|
|
|
{:ok, error} -> {:halt, error} |
|
|
|
|
{:exit, reason} -> {:halt, reason} |
|
|
|
|
nil -> {:halt, :timeout} |
|
|
|
|
end |
|
|
|
|
end) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
defp set_refetch_needed_for_partially_imported_blocks(%{blocks: %{params: blocks_params}}) do |
|
|
|
|