Merge branch 'feature/#1476-add-styles-for-POSDAO-network' into feature/#1638-new-style-for-lukso-network
* feature/#1476-add-styles-for-POSDAO-network: fix test remove inspect add line numbers change colors add CHANGELOG entry Remove internal tx and token balance fetching from realtime fetcher (#1724) fix empty block time change styles add test fix highlighting add CHANGELOG entry highlight decompiled source code Flatten indexer module hierarchy and supervisor tree (#1718)pull/1755/head
commit
408f249b43
@ -1,3 +1,38 @@ |
||||
defmodule BlockScoutWeb.AddressDecompiledContractView do |
||||
use BlockScoutWeb, :view |
||||
|
||||
@colors %{ |
||||
"\e[95m" => "136, 0, 0", |
||||
# red |
||||
"\e[91m" => "236, 89, 58", |
||||
# gray |
||||
"\e[38;5;8m" => "111, 110, 111", |
||||
# green |
||||
"\e[32m" => "57, 115, 0", |
||||
# yellowgreen |
||||
"\e[93m" => "57, 115, 0", |
||||
# yellow |
||||
"\e[92m" => "119, 232, 81", |
||||
# purple |
||||
"\e[94m" => "136, 0, 0" |
||||
} |
||||
|
||||
def highlight_decompiled_code(code) do |
||||
@colors |
||||
|> Enum.reduce(code, fn {symbol, rgb}, acc -> |
||||
String.replace(acc, symbol, "<span style=\"color:rgb(#{rgb})\">") |
||||
end) |
||||
|> String.replace("\e[1m", "<span style=\"font-weight:bold\">") |
||||
|> String.replace("»", "»") |
||||
|> String.replace("\e[0m", "</span>") |
||||
|> add_line_numbers() |
||||
end |
||||
|
||||
defp add_line_numbers(code) do |
||||
code |
||||
|> String.split("\n") |
||||
|> Enum.reduce("", fn line, acc -> |
||||
acc <> "<code>#{line}</code>\n" |
||||
end) |
||||
end |
||||
end |
||||
|
@ -1,46 +0,0 @@ |
||||
defmodule Indexer.Block.Reward.Supervisor do |
||||
@moduledoc """ |
||||
Supervises `Indexer.Block.Reward.Fetcher` and its batch tasks through `Indexer.Block.Reward.TaskSupervisor` |
||||
""" |
||||
|
||||
use Supervisor |
||||
|
||||
alias Indexer.Block.Reward.Fetcher |
||||
|
||||
def child_spec([init_arguments]) do |
||||
child_spec([init_arguments, []]) |
||||
end |
||||
|
||||
def child_spec([_init_arguments, _gen_server_options] = start_link_arguments) do |
||||
default = %{ |
||||
id: __MODULE__, |
||||
start: {__MODULE__, :start_link, start_link_arguments}, |
||||
type: :supervisor |
||||
} |
||||
|
||||
Supervisor.child_spec(default, []) |
||||
end |
||||
|
||||
def start_link(arguments, gen_server_options \\ []) do |
||||
if disabled?() do |
||||
:ignore |
||||
else |
||||
Supervisor.start_link(__MODULE__, arguments, Keyword.put_new(gen_server_options, :name, __MODULE__)) |
||||
end |
||||
end |
||||
|
||||
def disabled?() do |
||||
Application.get_env(:indexer, __MODULE__, [])[:disabled?] == true |
||||
end |
||||
|
||||
@impl Supervisor |
||||
def init(fetcher_arguments) do |
||||
Supervisor.init( |
||||
[ |
||||
{Task.Supervisor, name: Indexer.Block.Reward.TaskSupervisor}, |
||||
{Fetcher, [fetcher_arguments, [name: Fetcher]]} |
||||
], |
||||
strategy: :one_for_one |
||||
) |
||||
end |
||||
end |
@ -1,78 +0,0 @@ |
||||
defmodule Indexer.Block.Supervisor do |
||||
@moduledoc """ |
||||
Supervises `Indexer.Block.Catchup.Supervisor` and `Indexer.Block.Realtime.Supervisor`. |
||||
""" |
||||
|
||||
alias Indexer.Block |
||||
alias Indexer.Block.{Catchup, Realtime, Reward, Uncle} |
||||
alias Indexer.Temporary.{AddressesWithoutCode, FailedCreatedAddresses} |
||||
|
||||
use Supervisor |
||||
|
||||
def start_link([arguments, gen_server_options]) do |
||||
Supervisor.start_link(__MODULE__, arguments, gen_server_options) |
||||
end |
||||
|
||||
@impl Supervisor |
||||
def init( |
||||
%{ |
||||
block_interval: block_interval, |
||||
json_rpc_named_arguments: json_rpc_named_arguments, |
||||
subscribe_named_arguments: subscribe_named_arguments, |
||||
realtime_overrides: realtime_overrides |
||||
} = named_arguments |
||||
) do |
||||
block_fetcher = |
||||
named_arguments |
||||
|> Map.drop(~w(block_interval memory_monitor subscribe_named_arguments realtime_overrides)a) |
||||
|> Block.Fetcher.new() |
||||
|
||||
fixing_realtime_fetcher = %Block.Fetcher{ |
||||
broadcast: false, |
||||
callback_module: Realtime.Fetcher, |
||||
json_rpc_named_arguments: json_rpc_named_arguments |
||||
} |
||||
|
||||
realtime_block_fetcher = |
||||
named_arguments |
||||
|> Map.drop(~w(block_interval memory_monitor subscribe_named_arguments realtime_overrides)a) |
||||
|> Map.merge(Enum.into(realtime_overrides, %{})) |
||||
|> Block.Fetcher.new() |
||||
|
||||
realtime_subscribe_named_arguments = realtime_overrides[:subscribe_named_arguments] || subscribe_named_arguments |
||||
|
||||
memory_monitor = Map.get(named_arguments, :memory_monitor) |
||||
|
||||
Supervisor.init( |
||||
[ |
||||
{Catchup.Supervisor, |
||||
[ |
||||
%{block_fetcher: block_fetcher, block_interval: block_interval, memory_monitor: memory_monitor}, |
||||
[name: Catchup.Supervisor] |
||||
]}, |
||||
{Realtime.Supervisor, |
||||
[ |
||||
%{block_fetcher: realtime_block_fetcher, subscribe_named_arguments: realtime_subscribe_named_arguments}, |
||||
[name: Realtime.Supervisor] |
||||
]}, |
||||
{Uncle.Supervisor, [[block_fetcher: block_fetcher, memory_monitor: memory_monitor], [name: Uncle.Supervisor]]}, |
||||
{Reward.Supervisor, |
||||
[ |
||||
[json_rpc_named_arguments: json_rpc_named_arguments, memory_monitor: memory_monitor], |
||||
[name: Reward.Supervisor] |
||||
]}, |
||||
{FailedCreatedAddresses.Supervisor, |
||||
[ |
||||
json_rpc_named_arguments, |
||||
[name: FailedCreatedAddresses.Supervisor] |
||||
]}, |
||||
{AddressesWithoutCode.Supervisor, |
||||
[ |
||||
fixing_realtime_fetcher, |
||||
[name: AddressesWithoutCode.Supervisor] |
||||
]} |
||||
], |
||||
strategy: :one_for_one |
||||
) |
||||
end |
||||
end |
@ -1,21 +0,0 @@ |
||||
defmodule Indexer.Block.Transform do |
||||
@moduledoc """ |
||||
Protocol for transforming blocks. |
||||
""" |
||||
|
||||
@type block :: map() |
||||
|
||||
@doc """ |
||||
Transforms a block. |
||||
""" |
||||
@callback transform(block :: block()) :: block() |
||||
|
||||
@doc """ |
||||
Runs a list of blocks through the configured block transformer. |
||||
""" |
||||
def transform_blocks(blocks) when is_list(blocks) do |
||||
transformer = Application.get_env(:indexer, :block_transformer) |
||||
|
||||
Enum.map(blocks, &transformer.transform/1) |
||||
end |
||||
end |
@ -1,38 +0,0 @@ |
||||
defmodule Indexer.Block.Uncle.Supervisor do |
||||
@moduledoc """ |
||||
Supervises `Indexer.Block.Uncle.Fetcher`. |
||||
""" |
||||
|
||||
use Supervisor |
||||
|
||||
alias Indexer.Block.Uncle.Fetcher |
||||
|
||||
def child_spec([init_arguments]) do |
||||
child_spec([init_arguments, []]) |
||||
end |
||||
|
||||
def child_spec([_init_arguments, _gen_server_options] = start_link_arguments) do |
||||
default = %{ |
||||
id: __MODULE__, |
||||
start: {__MODULE__, :start_link, start_link_arguments}, |
||||
type: :supervisor |
||||
} |
||||
|
||||
Supervisor.child_spec(default, []) |
||||
end |
||||
|
||||
def start_link(arguments, gen_server_options \\ []) do |
||||
Supervisor.start_link(__MODULE__, arguments, gen_server_options) |
||||
end |
||||
|
||||
@impl Supervisor |
||||
def init(fetcher_arguments) do |
||||
Supervisor.init( |
||||
[ |
||||
{Task.Supervisor, name: Indexer.Block.Uncle.TaskSupervisor}, |
||||
{Fetcher, [fetcher_arguments, [name: Fetcher]]} |
||||
], |
||||
strategy: :rest_for_one |
||||
) |
||||
end |
||||
end |
@ -1,39 +0,0 @@ |
||||
defmodule Indexer.Code.Supervisor do |
||||
@moduledoc """ |
||||
Supervises `Indexer.Code.Fetcher` and its batch tasks through |
||||
`Indexer.Code.TaskSupervisor`. |
||||
""" |
||||
|
||||
use Supervisor |
||||
|
||||
alias Indexer.Code.Fetcher |
||||
|
||||
def child_spec([init_arguments]) do |
||||
child_spec([init_arguments, []]) |
||||
end |
||||
|
||||
def child_spec([_init_arguments, _gen_server_options] = start_link_arguments) do |
||||
default = %{ |
||||
id: __MODULE__, |
||||
start: {__MODULE__, :start_link, start_link_arguments}, |
||||
type: :supervisor |
||||
} |
||||
|
||||
Supervisor.child_spec(default, []) |
||||
end |
||||
|
||||
def start_link(arguments, gen_server_options \\ []) do |
||||
Supervisor.start_link(__MODULE__, arguments, Keyword.put_new(gen_server_options, :name, __MODULE__)) |
||||
end |
||||
|
||||
@impl Supervisor |
||||
def init(fetcher_arguments) do |
||||
Supervisor.init( |
||||
[ |
||||
{Task.Supervisor, name: Indexer.Code.TaskSupervisor}, |
||||
{Fetcher, [fetcher_arguments, [name: Fetcher]]} |
||||
], |
||||
strategy: :one_for_one |
||||
) |
||||
end |
||||
end |
@ -1,39 +0,0 @@ |
||||
defmodule Indexer.CoinBalance.Supervisor do |
||||
@moduledoc """ |
||||
Supervises `Indexer.CoinBalance.Fetcher` and its batch tasks through `Indexer.CoinBalance.TaskSupervisor` |
||||
""" |
||||
|
||||
use Supervisor |
||||
|
||||
alias Indexer.CoinBalance.{Fetcher, OnDemandFetcher} |
||||
|
||||
def child_spec([init_arguments]) do |
||||
child_spec([init_arguments, []]) |
||||
end |
||||
|
||||
def child_spec([_init_arguments, _gen_server_options] = start_link_arguments) do |
||||
default = %{ |
||||
id: __MODULE__, |
||||
start: {__MODULE__, :start_link, start_link_arguments}, |
||||
type: :supervisor |
||||
} |
||||
|
||||
Supervisor.child_spec(default, []) |
||||
end |
||||
|
||||
def start_link(arguments, gen_server_options \\ []) do |
||||
Supervisor.start_link(__MODULE__, arguments, Keyword.put_new(gen_server_options, :name, __MODULE__)) |
||||
end |
||||
|
||||
@impl Supervisor |
||||
def init(fetcher_arguments) do |
||||
Supervisor.init( |
||||
[ |
||||
{Task.Supervisor, name: Indexer.CoinBalance.TaskSupervisor}, |
||||
{Fetcher, [fetcher_arguments, [name: Fetcher]]}, |
||||
{OnDemandFetcher, [fetcher_arguments[:json_rpc_named_arguments], [name: OnDemandFetcher]]} |
||||
], |
||||
strategy: :one_for_one |
||||
) |
||||
end |
||||
end |
@ -0,0 +1,77 @@ |
||||
defmodule Indexer.Fetcher do |
||||
@moduledoc """ |
||||
General fetcher infrastructure. |
||||
""" |
||||
|
||||
alias Macro.Env |
||||
|
||||
defmacro __using__(opts \\ []) do |
||||
quote do |
||||
require Indexer.Fetcher |
||||
|
||||
Indexer.Fetcher.defsupervisor(unquote(opts)) |
||||
end |
||||
end |
||||
|
||||
# credo:disable-for-next-line Credo.Check.Refactor.CyclomaticComplexity |
||||
defmacro defsupervisor(opts \\ []) do |
||||
quote location: :keep do |
||||
opts = unquote(opts) |
||||
|
||||
strategy = Keyword.get(opts, :strategy, :one_for_one) |
||||
fetcher = __MODULE__ |
||||
supervisor = Keyword.get(opts, :supervisor, Module.concat(fetcher, Supervisor)) |
||||
task_supervisor = Keyword.get(opts, :task_supervisor, Module.concat(fetcher, TaskSupervisor)) |
||||
|
||||
Module.create( |
||||
supervisor, |
||||
quote bind_quoted: [strategy: strategy, fetcher: fetcher, task_supervisor: task_supervisor] do |
||||
use Supervisor |
||||
|
||||
def child_spec([]), do: child_spec([[], []]) |
||||
def child_spec([init_arguments]), do: child_spec([init_arguments, []]) |
||||
|
||||
def child_spec([_init_arguments, _gen_server_options] = start_link_arguments) do |
||||
default = %{ |
||||
id: __MODULE__, |
||||
start: {__MODULE__, :start_link, start_link_arguments}, |
||||
restart: :transient, |
||||
type: :supervisor |
||||
} |
||||
|
||||
Supervisor.child_spec(default, []) |
||||
end |
||||
|
||||
def start_link(arguments, gen_server_options \\ []) do |
||||
if disabled?() do |
||||
:ignore |
||||
else |
||||
Supervisor.start_link(__MODULE__, arguments, Keyword.put_new(gen_server_options, :name, __MODULE__)) |
||||
end |
||||
end |
||||
|
||||
def disabled?() do |
||||
Application.get_env(:indexer, __MODULE__, [])[:disabled?] == true |
||||
end |
||||
|
||||
@impl Supervisor |
||||
def init(fetcher_arguments) do |
||||
children = [ |
||||
{Task.Supervisor, name: unquote(task_supervisor)}, |
||||
{unquote(fetcher), [put_supervisor_when_is_list(fetcher_arguments), [name: unquote(fetcher)]]} |
||||
] |
||||
|
||||
Supervisor.init(children, strategy: unquote(strategy)) |
||||
end |
||||
|
||||
defp put_supervisor_when_is_list(arguments) when is_list(arguments) do |
||||
Keyword.put(arguments, :supervisor, self()) |
||||
end |
||||
|
||||
defp put_supervisor_when_is_list(arguments), do: arguments |
||||
end, |
||||
Env.location(__ENV__) |
||||
) |
||||
end |
||||
end |
||||
end |
@ -1,16 +1,17 @@ |
||||
defmodule Indexer.Token.MetadataUpdater do |
||||
defmodule Indexer.Fetcher.TokenUpdater do |
||||
@moduledoc """ |
||||
Updates metadata for cataloged tokens |
||||
""" |
||||
|
||||
use GenServer |
||||
use Indexer.Fetcher |
||||
|
||||
alias Explorer.Chain |
||||
alias Explorer.Chain.Token |
||||
alias Explorer.Token.MetadataRetriever |
||||
|
||||
def start_link(initial_state) do |
||||
GenServer.start_link(__MODULE__, initial_state, name: __MODULE__) |
||||
def start_link([initial_state, gen_server_options]) do |
||||
GenServer.start_link(__MODULE__, initial_state, gen_server_options) |
||||
end |
||||
|
||||
@impl true |
@ -1,39 +0,0 @@ |
||||
defmodule Indexer.InternalTransaction.Supervisor do |
||||
@moduledoc """ |
||||
Supervises `Indexer.InternalTransaction.Fetcher` and its batch tasks through |
||||
`Indexer.InternalTransaction.TaskSupervisor`. |
||||
""" |
||||
|
||||
use Supervisor |
||||
|
||||
alias Indexer.InternalTransaction.Fetcher |
||||
|
||||
def child_spec([init_arguments]) do |
||||
child_spec([init_arguments, []]) |
||||
end |
||||
|
||||
def child_spec([_init_arguments, _gen_server_options] = start_link_arguments) do |
||||
default = %{ |
||||
id: __MODULE__, |
||||
start: {__MODULE__, :start_link, start_link_arguments}, |
||||
type: :supervisor |
||||
} |
||||
|
||||
Supervisor.child_spec(default, []) |
||||
end |
||||
|
||||
def start_link(arguments, gen_server_options \\ []) do |
||||
Supervisor.start_link(__MODULE__, arguments, Keyword.put_new(gen_server_options, :name, __MODULE__)) |
||||
end |
||||
|
||||
@impl Supervisor |
||||
def init(fetcher_arguments) do |
||||
Supervisor.init( |
||||
[ |
||||
{Task.Supervisor, name: Indexer.InternalTransaction.TaskSupervisor}, |
||||
{Fetcher, [fetcher_arguments, [name: Fetcher]]} |
||||
], |
||||
strategy: :one_for_one |
||||
) |
||||
end |
||||
end |
@ -1,39 +0,0 @@ |
||||
defmodule Indexer.PendingTransaction.Supervisor do |
||||
@moduledoc """ |
||||
Supervises `Indexer.PendingTransaction.Fetcher` and its batch tasks through |
||||
`Indexer.PendingTransaction.TaskSupervisor`. |
||||
""" |
||||
|
||||
use Supervisor |
||||
|
||||
alias Indexer.PendingTransaction.Fetcher |
||||
|
||||
def child_spec([init_arguments]) do |
||||
child_spec([init_arguments, []]) |
||||
end |
||||
|
||||
def child_spec([_init_arguments, _gen_server_options] = start_link_arguments) do |
||||
default = %{ |
||||
id: __MODULE__, |
||||
start: {__MODULE__, :start_link, start_link_arguments}, |
||||
type: :supervisor |
||||
} |
||||
|
||||
Supervisor.child_spec(default, []) |
||||
end |
||||
|
||||
def start_link(arguments, gen_server_options \\ []) do |
||||
Supervisor.start_link(__MODULE__, arguments, Keyword.put_new(gen_server_options, :name, __MODULE__)) |
||||
end |
||||
|
||||
@impl Supervisor |
||||
def init(fetcher_arguments) do |
||||
Supervisor.init( |
||||
[ |
||||
{Task.Supervisor, name: Indexer.PendingTransaction.TaskSupervisor}, |
||||
{Fetcher, [fetcher_arguments, [name: Fetcher]]} |
||||
], |
||||
strategy: :one_for_one |
||||
) |
||||
end |
||||
end |
@ -1,47 +0,0 @@ |
||||
defmodule Indexer.ReplacedTransaction.Supervisor do |
||||
@moduledoc """ |
||||
Supervises `Indexer.ReplacedTransaction.Fetcher` and its batch tasks through |
||||
`Indexer.ReplacedTransaction.TaskSupervisor`. |
||||
""" |
||||
|
||||
use Supervisor |
||||
|
||||
alias Indexer.ReplacedTransaction.Fetcher |
||||
|
||||
def child_spec([init_arguments]) do |
||||
child_spec([init_arguments, []]) |
||||
end |
||||
|
||||
def child_spec([_init_arguments, _gen_server_options] = start_link_arguments) do |
||||
default = %{ |
||||
id: __MODULE__, |
||||
start: {__MODULE__, :start_link, start_link_arguments}, |
||||
type: :supervisor |
||||
} |
||||
|
||||
Supervisor.child_spec(default, []) |
||||
end |
||||
|
||||
def start_link(arguments, gen_server_options \\ []) do |
||||
if disabled?() do |
||||
:ignore |
||||
else |
||||
Supervisor.start_link(__MODULE__, arguments, Keyword.put_new(gen_server_options, :name, __MODULE__)) |
||||
end |
||||
end |
||||
|
||||
def disabled?() do |
||||
Application.get_env(:indexer, __MODULE__, [])[:disabled?] == true |
||||
end |
||||
|
||||
@impl Supervisor |
||||
def init(fetcher_arguments) do |
||||
Supervisor.init( |
||||
[ |
||||
{Task.Supervisor, name: Indexer.ReplacedTransaction.TaskSupervisor}, |
||||
{Fetcher, [fetcher_arguments, [name: Fetcher]]} |
||||
], |
||||
strategy: :one_for_one |
||||
) |
||||
end |
||||
end |
@ -1,97 +0,0 @@ |
||||
defmodule Indexer.Shrinkable.Supervisor do |
||||
@moduledoc """ |
||||
Supervisor of all supervision trees that depend on `Indexer.Alarm.Supervisor`. |
||||
""" |
||||
|
||||
use Supervisor |
||||
|
||||
alias Indexer.{ |
||||
Block, |
||||
Code, |
||||
CoinBalance, |
||||
InternalTransaction, |
||||
PendingTransaction, |
||||
ReplacedTransaction, |
||||
Token, |
||||
TokenBalance, |
||||
TokenTransfer |
||||
} |
||||
|
||||
def child_spec([]) do |
||||
child_spec([[]]) |
||||
end |
||||
|
||||
def child_spec([init_arguments]) do |
||||
child_spec([init_arguments, []]) |
||||
end |
||||
|
||||
def child_spec([_init_arguments, _gen_server_options] = start_link_arguments) do |
||||
default = %{ |
||||
id: __MODULE__, |
||||
start: {__MODULE__, :start_link, start_link_arguments}, |
||||
type: :supervisor |
||||
} |
||||
|
||||
Supervisor.child_spec(default, []) |
||||
end |
||||
|
||||
def start_link(arguments, gen_server_options \\ []) do |
||||
Supervisor.start_link(__MODULE__, arguments, Keyword.put_new(gen_server_options, :name, __MODULE__)) |
||||
end |
||||
|
||||
@impl Supervisor |
||||
def init(%{memory_monitor: memory_monitor}) do |
||||
json_rpc_named_arguments = Application.fetch_env!(:indexer, :json_rpc_named_arguments) |
||||
|
||||
block_fetcher_supervisor_named_arguments = |
||||
:indexer |
||||
|> Application.get_all_env() |
||||
|> Keyword.take( |
||||
~w(blocks_batch_size blocks_concurrency block_interval json_rpc_named_arguments receipts_batch_size |
||||
receipts_concurrency subscribe_named_arguments realtime_overrides)a |
||||
) |
||||
|> Enum.into(%{}) |
||||
|> Map.put(:memory_monitor, memory_monitor) |
||||
|> Map.put_new(:realtime_overrides, %{}) |
||||
|
||||
Supervisor.init( |
||||
[ |
||||
{CoinBalance.Supervisor, |
||||
[ |
||||
[json_rpc_named_arguments: json_rpc_named_arguments, memory_monitor: memory_monitor], |
||||
[name: CoinBalance.Supervisor] |
||||
]}, |
||||
{PendingTransaction.Supervisor, |
||||
[[json_rpc_named_arguments: json_rpc_named_arguments], [name: PendingTransactionFetcher]]}, |
||||
{Code.Supervisor, |
||||
[ |
||||
[json_rpc_named_arguments: json_rpc_named_arguments, memory_monitor: memory_monitor], |
||||
[name: Code.Supervisor] |
||||
]}, |
||||
{ReplacedTransaction.Supervisor, |
||||
[ |
||||
[memory_monitor: memory_monitor], |
||||
[name: ReplacedTransaction.Supervisor] |
||||
]}, |
||||
{InternalTransaction.Supervisor, |
||||
[ |
||||
[json_rpc_named_arguments: json_rpc_named_arguments, memory_monitor: memory_monitor], |
||||
[name: InternalTransaction.Supervisor] |
||||
]}, |
||||
{Token.Supervisor, |
||||
[ |
||||
[json_rpc_named_arguments: json_rpc_named_arguments, memory_monitor: memory_monitor], |
||||
[name: Token.Supervisor] |
||||
]}, |
||||
{TokenBalance.Supervisor, |
||||
[ |
||||
[json_rpc_named_arguments: json_rpc_named_arguments, memory_monitor: memory_monitor], |
||||
[name: TokenBalance.Supervisor] |
||||
]}, |
||||
{Block.Supervisor, [block_fetcher_supervisor_named_arguments, [name: Block.Supervisor]]}, |
||||
{TokenTransfer.Uncataloged.Supervisor, [[], [name: TokenTransfer.Uncataloged.Supervisor]]} |
||||
], |
||||
strategy: :one_for_one |
||||
) |
||||
end |
||||
end |
@ -0,0 +1,137 @@ |
||||
defmodule Indexer.Supervisor do |
||||
@moduledoc """ |
||||
Supervisor of all indexer worker supervision trees |
||||
""" |
||||
|
||||
use Supervisor |
||||
|
||||
alias Indexer.Block |
||||
alias Indexer.Block.{Catchup, Realtime} |
||||
|
||||
alias Indexer.Fetcher.{ |
||||
BlockReward, |
||||
CoinBalance, |
||||
CoinBalanceOnDemand, |
||||
ContractCode, |
||||
InternalTransaction, |
||||
PendingTransaction, |
||||
ReplacedTransaction, |
||||
Token, |
||||
TokenBalance, |
||||
TokenUpdater, |
||||
UncleBlock |
||||
} |
||||
|
||||
alias Indexer.Temporary.{ |
||||
AddressesWithoutCode, |
||||
FailedCreatedAddresses, |
||||
UncatalogedTokenTransfers |
||||
} |
||||
|
||||
def child_spec([]) do |
||||
child_spec([[]]) |
||||
end |
||||
|
||||
def child_spec([init_arguments]) do |
||||
child_spec([init_arguments, []]) |
||||
end |
||||
|
||||
def child_spec([_init_arguments, _gen_server_options] = start_link_arguments) do |
||||
default = %{ |
||||
id: __MODULE__, |
||||
start: {__MODULE__, :start_link, start_link_arguments}, |
||||
type: :supervisor |
||||
} |
||||
|
||||
Supervisor.child_spec(default, []) |
||||
end |
||||
|
||||
def start_link(arguments, gen_server_options \\ []) do |
||||
Supervisor.start_link(__MODULE__, arguments, Keyword.put_new(gen_server_options, :name, __MODULE__)) |
||||
end |
||||
|
||||
@impl Supervisor |
||||
def init(%{memory_monitor: memory_monitor}) do |
||||
json_rpc_named_arguments = Application.fetch_env!(:indexer, :json_rpc_named_arguments) |
||||
|
||||
named_arguments = |
||||
:indexer |
||||
|> Application.get_all_env() |
||||
|> Keyword.take( |
||||
~w(blocks_batch_size blocks_concurrency block_interval json_rpc_named_arguments receipts_batch_size |
||||
receipts_concurrency subscribe_named_arguments realtime_overrides)a |
||||
) |
||||
|> Enum.into(%{}) |
||||
|> Map.put(:memory_monitor, memory_monitor) |
||||
|> Map.put_new(:realtime_overrides, %{}) |
||||
|
||||
%{ |
||||
block_interval: block_interval, |
||||
realtime_overrides: realtime_overrides, |
||||
subscribe_named_arguments: subscribe_named_arguments |
||||
} = named_arguments |
||||
|
||||
metadata_updater_inverval = Application.get_env(:indexer, :metadata_updater_days_interval) |
||||
|
||||
block_fetcher = |
||||
named_arguments |
||||
|> Map.drop(~w(block_interval memory_monitor subscribe_named_arguments realtime_overrides)a) |
||||
|> Block.Fetcher.new() |
||||
|
||||
fixing_realtime_fetcher = %Block.Fetcher{ |
||||
broadcast: false, |
||||
callback_module: Realtime.Fetcher, |
||||
json_rpc_named_arguments: json_rpc_named_arguments |
||||
} |
||||
|
||||
realtime_block_fetcher = |
||||
named_arguments |
||||
|> Map.drop(~w(block_interval memory_monitor subscribe_named_arguments realtime_overrides)a) |
||||
|> Map.merge(Enum.into(realtime_overrides, %{})) |
||||
|> Block.Fetcher.new() |
||||
|
||||
realtime_subscribe_named_arguments = realtime_overrides[:subscribe_named_arguments] || subscribe_named_arguments |
||||
|
||||
Supervisor.init( |
||||
[ |
||||
# Root fetchers |
||||
{PendingTransaction.Supervisor, [[json_rpc_named_arguments: json_rpc_named_arguments]]}, |
||||
{Realtime.Supervisor, |
||||
[ |
||||
%{block_fetcher: realtime_block_fetcher, subscribe_named_arguments: realtime_subscribe_named_arguments}, |
||||
[name: Realtime.Supervisor] |
||||
]}, |
||||
{Catchup.Supervisor, |
||||
[ |
||||
%{block_fetcher: block_fetcher, block_interval: block_interval, memory_monitor: memory_monitor}, |
||||
[name: Catchup.Supervisor] |
||||
]}, |
||||
|
||||
# Async catchup fetchers |
||||
{UncleBlock.Supervisor, [[block_fetcher: block_fetcher, memory_monitor: memory_monitor]]}, |
||||
{BlockReward.Supervisor, |
||||
[[json_rpc_named_arguments: json_rpc_named_arguments, memory_monitor: memory_monitor]]}, |
||||
{InternalTransaction.Supervisor, |
||||
[[json_rpc_named_arguments: json_rpc_named_arguments, memory_monitor: memory_monitor]]}, |
||||
{CoinBalance.Supervisor, |
||||
[[json_rpc_named_arguments: json_rpc_named_arguments, memory_monitor: memory_monitor]]}, |
||||
{Token.Supervisor, [[json_rpc_named_arguments: json_rpc_named_arguments, memory_monitor: memory_monitor]]}, |
||||
{ContractCode.Supervisor, |
||||
[[json_rpc_named_arguments: json_rpc_named_arguments, memory_monitor: memory_monitor]]}, |
||||
{TokenBalance.Supervisor, |
||||
[[json_rpc_named_arguments: json_rpc_named_arguments, memory_monitor: memory_monitor]]}, |
||||
{ReplacedTransaction.Supervisor, [[memory_monitor: memory_monitor]]}, |
||||
|
||||
# Out-of-band fetchers |
||||
{CoinBalanceOnDemand.Supervisor, [json_rpc_named_arguments]}, |
||||
{TokenUpdater.Supervisor, [%{update_interval: metadata_updater_inverval}]}, |
||||
|
||||
# Temporary workers |
||||
{AddressesWithoutCode.Supervisor, [fixing_realtime_fetcher]}, |
||||
{FailedCreatedAddresses.Supervisor, [json_rpc_named_arguments]}, |
||||
{UncatalogedTokenTransfers.Supervisor, [[]]} |
||||
], |
||||
strategy: :one_for_one |
||||
) |
||||
end |
||||
end |
@ -1,38 +0,0 @@ |
||||
defmodule Indexer.Temporary.AddressesWithoutCode.Supervisor do |
||||
@moduledoc """ |
||||
Supervises `Indexer.Temporary.FailedCreatedAddresses`. |
||||
""" |
||||
|
||||
use Supervisor |
||||
|
||||
alias Indexer.Temporary.AddressesWithoutCode |
||||
|
||||
def child_spec([init_arguments]) do |
||||
child_spec([init_arguments, []]) |
||||
end |
||||
|
||||
def child_spec([_init_arguments, _gen_server_options] = start_link_arguments) do |
||||
default = %{ |
||||
id: __MODULE__, |
||||
start: {__MODULE__, :start_link, start_link_arguments}, |
||||
type: :supervisor |
||||
} |
||||
|
||||
Supervisor.child_spec(default, []) |
||||
end |
||||
|
||||
def start_link(fetcher, gen_server_options \\ []) do |
||||
Supervisor.start_link(__MODULE__, fetcher, gen_server_options) |
||||
end |
||||
|
||||
@impl Supervisor |
||||
def init(fetcher) do |
||||
Supervisor.init( |
||||
[ |
||||
{Task.Supervisor, name: Indexer.Temporary.AddressesWithoutCode.TaskSupervisor}, |
||||
{AddressesWithoutCode, [fetcher, [name: FailedCreatedAddresses]]} |
||||
], |
||||
strategy: :rest_for_one |
||||
) |
||||
end |
||||
end |
@ -1,38 +0,0 @@ |
||||
defmodule Indexer.Temporary.FailedCreatedAddresses.Supervisor do |
||||
@moduledoc """ |
||||
Supervises `Indexer.Temporary.FailedCreatedAddresses`. |
||||
""" |
||||
|
||||
use Supervisor |
||||
|
||||
alias Indexer.Temporary.FailedCreatedAddresses |
||||
|
||||
def child_spec([init_arguments]) do |
||||
child_spec([init_arguments, []]) |
||||
end |
||||
|
||||
def child_spec([_init_arguments, _gen_server_options] = start_link_arguments) do |
||||
default = %{ |
||||
id: __MODULE__, |
||||
start: {__MODULE__, :start_link, start_link_arguments}, |
||||
type: :supervisor |
||||
} |
||||
|
||||
Supervisor.child_spec(default, []) |
||||
end |
||||
|
||||
def start_link(json_rpc_named_arguments, gen_server_options \\ []) do |
||||
Supervisor.start_link(__MODULE__, json_rpc_named_arguments, gen_server_options) |
||||
end |
||||
|
||||
@impl Supervisor |
||||
def init(json_rpc_named_arguments) do |
||||
Supervisor.init( |
||||
[ |
||||
{Task.Supervisor, name: Indexer.Temporary.FailedCreatedAddresses.TaskSupervisor}, |
||||
{FailedCreatedAddresses, [json_rpc_named_arguments, [name: FailedCreatedAddresses]]} |
||||
], |
||||
strategy: :rest_for_one |
||||
) |
||||
end |
||||
end |
@ -1,41 +0,0 @@ |
||||
defmodule Indexer.Token.Supervisor do |
||||
@moduledoc """ |
||||
Supervises `Indexer.Token.Fetcher` and its batch tasks through `Indexer.Token.TaskSupervisor`. |
||||
""" |
||||
|
||||
use Supervisor |
||||
|
||||
alias Indexer.Token.{Fetcher, MetadataUpdater} |
||||
|
||||
def child_spec([init_arguments]) do |
||||
child_spec([init_arguments, []]) |
||||
end |
||||
|
||||
def child_spec([_init_arguments, _gen_server_options] = start_link_arguments) do |
||||
default = %{ |
||||
id: __MODULE__, |
||||
start: {__MODULE__, :start_link, start_link_arguments}, |
||||
type: :supervisor |
||||
} |
||||
|
||||
Supervisor.child_spec(default, []) |
||||
end |
||||
|
||||
def start_link(arguments, gen_server_options \\ []) do |
||||
Supervisor.start_link(__MODULE__, arguments, Keyword.put_new(gen_server_options, :name, __MODULE__)) |
||||
end |
||||
|
||||
@impl Supervisor |
||||
def init(fetcher_arguments) do |
||||
metadata_updater_inverval = Application.get_env(:indexer, :metadata_updater_days_interval) |
||||
|
||||
Supervisor.init( |
||||
[ |
||||
{Task.Supervisor, name: Indexer.Token.TaskSupervisor}, |
||||
{Fetcher, [fetcher_arguments, [name: Fetcher]]}, |
||||
{MetadataUpdater, %{update_interval: metadata_updater_inverval}} |
||||
], |
||||
strategy: :one_for_one |
||||
) |
||||
end |
||||
end |
@ -1,38 +0,0 @@ |
||||
defmodule Indexer.TokenBalance.Supervisor do |
||||
@moduledoc """ |
||||
Supervises `Indexer.TokenBalance.Fetcher` and its batch tasks through `Indexer.TokenBalance.TaskSupervisor` |
||||
""" |
||||
|
||||
use Supervisor |
||||
|
||||
alias Indexer.TokenBalance.Fetcher |
||||
|
||||
def child_spec([init_arguments]) do |
||||
child_spec([init_arguments, []]) |
||||
end |
||||
|
||||
def child_spec([_init_arguments, _gen_server_options] = start_link_arguments) do |
||||
default = %{ |
||||
id: __MODULE__, |
||||
start: {__MODULE__, :start_link, start_link_arguments}, |
||||
type: :supervisor |
||||
} |
||||
|
||||
Supervisor.child_spec(default, []) |
||||
end |
||||
|
||||
def start_link(arguments, gen_server_options \\ []) do |
||||
Supervisor.start_link(__MODULE__, arguments, Keyword.put_new(gen_server_options, :name, __MODULE__)) |
||||
end |
||||
|
||||
@impl Supervisor |
||||
def init(fetcher_arguments) do |
||||
Supervisor.init( |
||||
[ |
||||
{Task.Supervisor, name: Indexer.TokenBalance.TaskSupervisor}, |
||||
{Fetcher, [fetcher_arguments, [name: Fetcher]]} |
||||
], |
||||
strategy: :one_for_one |
||||
) |
||||
end |
||||
end |
@ -1,44 +0,0 @@ |
||||
defmodule Indexer.TokenTransfer.Uncataloged.Supervisor do |
||||
@moduledoc """ |
||||
Supervises process for ensuring uncataloged token transfers get queued for indexing. |
||||
""" |
||||
|
||||
use Supervisor |
||||
|
||||
alias Indexer.TokenTransfer.Uncataloged.Worker |
||||
|
||||
def child_spec([]) do |
||||
child_spec([[]]) |
||||
end |
||||
|
||||
def child_spec([init_arguments]) do |
||||
child_spec([init_arguments, [name: __MODULE__]]) |
||||
end |
||||
|
||||
def child_spec([_init_arguments, _gen_server_options] = start_link_arguments) do |
||||
spec = %{ |
||||
id: __MODULE__, |
||||
start: {__MODULE__, :start_link, start_link_arguments}, |
||||
restart: :transient, |
||||
type: :supervisor |
||||
} |
||||
|
||||
Supervisor.child_spec(spec, []) |
||||
end |
||||
|
||||
def start_link(init_arguments, gen_server_options \\ []) do |
||||
Supervisor.start_link(__MODULE__, init_arguments, gen_server_options) |
||||
end |
||||
|
||||
@impl Supervisor |
||||
def init(_) do |
||||
children = [ |
||||
{Worker, [[supervisor: self()], [name: Worker]]}, |
||||
{Task.Supervisor, name: Indexer.TokenTransfer.Uncataloged.TaskSupervisor} |
||||
] |
||||
|
||||
opts = [strategy: :one_for_all] |
||||
|
||||
Supervisor.init(children, opts) |
||||
end |
||||
end |
@ -1,9 +0,0 @@ |
||||
defmodule Indexer.TokenTransfers do |
||||
@moduledoc """ |
||||
Context for working with token transfers. |
||||
""" |
||||
|
||||
alias Indexer.TokenTransfer.Parser |
||||
|
||||
defdelegate parse(items), to: Parser |
||||
end |
@ -1,4 +1,4 @@ |
||||
defmodule Indexer.Address.CoinBalances do |
||||
defmodule Indexer.Transform.AddressCoinBalances do |
||||
@moduledoc """ |
||||
Extracts `Explorer.Chain.Address.CoinBalance` params from other schema's params. |
||||
""" |
@ -1,4 +1,4 @@ |
||||
defmodule Indexer.Address.TokenBalances do |
||||
defmodule Indexer.Transform.AddressTokenBalances do |
||||
@moduledoc """ |
||||
Extracts `Explorer.Address.TokenBalance` params from other schema's params. |
||||
""" |
@ -1,8 +1,24 @@ |
||||
defmodule Indexer.Block.Util do |
||||
defmodule Indexer.Transform.Blocks do |
||||
@moduledoc """ |
||||
Helper functions for parsing block information. |
||||
Protocol for transforming blocks. |
||||
""" |
||||
|
||||
@type block :: map() |
||||
|
||||
@doc """ |
||||
Transforms a block. |
||||
""" |
||||
@callback transform(block :: block()) :: block() |
||||
|
||||
@doc """ |
||||
Runs a list of blocks through the configured block transformer. |
||||
""" |
||||
def transform_blocks(blocks) when is_list(blocks) do |
||||
transformer = Application.get_env(:indexer, :block_transformer) |
||||
|
||||
Enum.map(blocks, &transformer.transform/1) |
||||
end |
||||
|
||||
@doc """ |
||||
Calculates the signer's address by recovering the ECDSA public key. |
||||
|
@ -1,13 +1,13 @@ |
||||
defmodule Indexer.Block.Transform.Base do |
||||
defmodule Indexer.Transform.Blocks.Base do |
||||
@moduledoc """ |
||||
Default block transformer to be used. |
||||
""" |
||||
|
||||
alias Indexer.Block.Transform |
||||
alias Indexer.Transform.Blocks |
||||
|
||||
@behaviour Transform |
||||
@behaviour Blocks |
||||
|
||||
@impl Transform |
||||
@impl Blocks |
||||
def transform(block) when is_map(block) do |
||||
block |
||||
end |
@ -1,17 +1,17 @@ |
||||
defmodule Indexer.Block.Transform.Clique do |
||||
defmodule Indexer.Transform.Blocks.Clique do |
||||
@moduledoc """ |
||||
Handles block transforms for Clique chain. |
||||
""" |
||||
|
||||
alias Indexer.Block.{Transform, Util} |
||||
alias Indexer.Transform.Blocks |
||||
|
||||
@behaviour Transform |
||||
@behaviour Blocks |
||||
|
||||
@impl Transform |
||||
@impl Blocks |
||||
def transform(%{number: 0} = block), do: block |
||||
|
||||
def transform(block) when is_map(block) do |
||||
miner_address = Util.signer(block) |
||||
miner_address = Blocks.signer(block) |
||||
|
||||
%{block | miner_hash: miner_address} |
||||
end |
@ -1,4 +1,4 @@ |
||||
defmodule Indexer.TokenTransfer.Parser do |
||||
defmodule Indexer.Transform.TokenTransfers do |
||||
@moduledoc """ |
||||
Helper functions for transforming data for ERC-20 and ERC-721 token transfers. |
||||
""" |
@ -1,8 +1,8 @@ |
||||
defmodule Indexer.SequenceTest do |
||||
defmodule Indexer.Block.Catchup.SequenceTest do |
||||
use ExUnit.Case |
||||
|
||||
alias Indexer.Block.Catchup.Sequence |
||||
alias Indexer.Memory.Shrinkable |
||||
alias Indexer.Sequence |
||||
|
||||
describe "start_link/1" do |
||||
test "without :ranges with :first with positive step pops infinitely" do |
@ -1,40 +0,0 @@ |
||||
defmodule Indexer.Block.UtilTest do |
||||
use ExUnit.Case |
||||
|
||||
alias Indexer.Block.Util |
||||
|
||||
test "signer/1" do |
||||
data = %{ |
||||
difficulty: 1, |
||||
extra_data: |
||||
"0xd68301080d846765746886676f312e3130856c696e7578000000000000000000773ab2ca8f47904a14739ad80a75b71d9d29b9fff8b7ecdcb73efffa6f74122f17d304b5dc8e6e5f256c9474dd115c8d4dae31b7a3d409e5c3270f8fde41cd8c00", |
||||
gas_limit: 7_753_377, |
||||
gas_used: 1_810_195, |
||||
hash: "0x7004c895e812c55b0c2be8a46d72ca300a683dc27d1d7917ee7742d4d0359c1f", |
||||
logs_bloom: |
||||
"0x00000000000000020000000000002000000400000000000000000000000000000000000000000000040000080004000020000010000000000000000000000000000000000000000008000008000000000000000000200000000000000000000000000000020000000000000000000800000000000000804000000010080000000800000000000000000000000000000000000000000000800000000000080000000008000400000000404000000000000000000000000200000000000000000000000002000000000000001002000000000000002000000008000000000020000000000000000000000000000000000000000000000000400000800000000000", |
||||
miner_hash: "0x0000000000000000000000000000000000000000", |
||||
mix_hash: "0x0000000000000000000000000000000000000000000000000000000000000000", |
||||
nonce: "0x0000000000000000", |
||||
number: 2_848_394, |
||||
parent_hash: "0x20350fc367e19d3865be1ea7da72ab81f8f9941c43ac6bb24a34a0a7caa2f3df", |
||||
receipts_root: "0x6ade4ac1079ea50cfadcce2b75ffbe4f9b14bf69b4607bbf1739463076ca6246", |
||||
sha3_uncles: "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", |
||||
size: 6437, |
||||
state_root: "0x23f63347851bcd109059d007d71e19c4f5e73b7f0862bebcd04458333a004d92", |
||||
timestamp: DateTime.from_unix!(1_534_796_040), |
||||
total_difficulty: 5_353_647, |
||||
transactions: [ |
||||
"0x7e3bb851fc74a436826d2af6b96e4db9484431811ef0d9c9e78370488d33d4e5", |
||||
"0x3976fd1e3d2a715c3cfcfde9bd3210798c26c017b8edb841d319227ecb3322fb", |
||||
"0xd8db124005bb8b6fda7b71fd56ac782552a66af58fe843ba3c4930423b87d1d2", |
||||
"0x10c1a1ca4d9f4b2bd5b89f7bbcbbc2d69e166fe23662b8db4f6beae0f50ac9fd", |
||||
"0xaa58a6545677c796a56b8bc874174c8cfd31a6c6e6ca3a87e086d4f66d52858a" |
||||
], |
||||
transactions_root: "0xde8d25c0b9b54310128a21601331094b43f910f9f96102869c2e2dca94884bf4", |
||||
uncles: [] |
||||
} |
||||
|
||||
assert Util.signer(data) == "0xfc18cbc391de84dbd87db83b20935d3e89f5dd91" |
||||
end |
||||
end |
@ -1,7 +1,7 @@ |
||||
defmodule Indexer.Block.Transform.BaseTest do |
||||
defmodule Indexer.Transform.Blocks.BaseTest do |
||||
use ExUnit.Case |
||||
|
||||
alias Indexer.Block.Transform.Base |
||||
alias Indexer.Transform.Blocks.Base |
||||
|
||||
@block %{ |
||||
difficulty: 1, |
@ -1,7 +1,7 @@ |
||||
defmodule Indexer.Block.Transform.CliqueTest do |
||||
defmodule Indexer.Transform.Blocks.CliqueTest do |
||||
use ExUnit.Case |
||||
|
||||
alias Indexer.Block.Transform.Clique |
||||
alias Indexer.Transform.Blocks.Clique |
||||
|
||||
@block %{ |
||||
difficulty: 1, |
@ -1,5 +1,5 @@ |
||||
defmodule Indexer.CoinBalance.Supervisor.Case do |
||||
alias Indexer.CoinBalance |
||||
defmodule Indexer.Fetcher.CoinBalance.Supervisor.Case do |
||||
alias Indexer.Fetcher.CoinBalance |
||||
|
||||
def start_supervised!(fetcher_arguments \\ []) when is_list(fetcher_arguments) do |
||||
merged_fetcher_arguments = |
@ -1,5 +1,5 @@ |
||||
defmodule Indexer.InternalTransaction.Supervisor.Case do |
||||
alias Indexer.InternalTransaction |
||||
defmodule Indexer.Fetcher.InternalTransaction.Supervisor.Case do |
||||
alias Indexer.Fetcher.InternalTransaction |
||||
|
||||
def start_supervised!(fetcher_arguments \\ []) when is_list(fetcher_arguments) do |
||||
merged_fetcher_arguments = |
@ -1,5 +1,5 @@ |
||||
defmodule Indexer.PendingTransaction.Supervisor.Case do |
||||
alias Indexer.PendingTransaction |
||||
defmodule Indexer.Fetcher.PendingTransaction.Supervisor.Case do |
||||
alias Indexer.Fetcher.PendingTransaction |
||||
|
||||
def start_supervised!(fetcher_arguments \\ []) when is_list(fetcher_arguments) do |
||||
merged_fetcher_arguments = |
@ -1,5 +1,5 @@ |
||||
defmodule Indexer.ReplacedTransaction.Supervisor.Case do |
||||
alias Indexer.ReplacedTransaction |
||||
defmodule Indexer.Fetcher.ReplacedTransaction.Supervisor.Case do |
||||
alias Indexer.Fetcher.ReplacedTransaction |
||||
|
||||
def start_supervised!(fetcher_arguments \\ []) when is_list(fetcher_arguments) do |
||||
merged_fetcher_arguments = |
@ -1,5 +1,5 @@ |
||||
defmodule Indexer.TokenBalance.Supervisor.Case do |
||||
alias Indexer.TokenBalance |
||||
defmodule Indexer.Fetcher.TokenBalance.Supervisor.Case do |
||||
alias Indexer.Fetcher.TokenBalance |
||||
|
||||
def start_supervised!(fetcher_arguments \\ []) when is_list(fetcher_arguments) do |
||||
merged_fetcher_arguments = |
@ -1,5 +1,5 @@ |
||||
defmodule Indexer.Token.Supervisor.Case do |
||||
alias Indexer.Token |
||||
defmodule Indexer.Fetcher.Token.Supervisor.Case do |
||||
alias Indexer.Fetcher.Token |
||||
|
||||
def start_supervised!(fetcher_arguments \\ []) when is_list(fetcher_arguments) do |
||||
merged_fetcher_arguments = |
Loading…
Reference in new issue