From b52d10b22acedf72848b360b068333904de8d8d0 Mon Sep 17 00:00:00 2001 From: pasqu4le Date: Thu, 1 Aug 2019 18:11:10 +0200 Subject: [PATCH] Add generic Ordered Cache behaviour and implementation Problem: multiple caches exist to keep a page of the most recent `n` elements. More are to be implemented, so it would be good to abstract their implementation. Solution: add a behaviour and a macro (providing an implementation) to create this type of caches. Redefine the existing ones using the new macro. --- CHANGELOG.md | 1 + .../api/v1/health_controller_test.exs | 4 +- .../block_scout_web/test/support/conn_case.ex | 4 +- .../test/support/feature_case.ex | 4 +- apps/explorer/lib/explorer/application.ex | 4 +- apps/explorer/lib/explorer/chain.ex | 14 +- .../lib/explorer/chain/cache/blocks.ex | 90 +---- .../lib/explorer/chain/cache/transactions.ex | 153 +------- .../lib/explorer/chain/ordered_cache.ex | 326 ++++++++++++++++++ .../test/explorer/chain/cache/blocks_test.exs | 37 +- .../market/market_history_cache_test.exs | 4 +- .../test/explorer/market/market_test.exs | 8 +- apps/explorer/test/support/data_case.ex | 8 +- apps/indexer/lib/indexer/block/fetcher.ex | 2 +- 14 files changed, 391 insertions(+), 268 deletions(-) create mode 100644 apps/explorer/lib/explorer/chain/ordered_cache.ex diff --git a/CHANGELOG.md b/CHANGELOG.md index d165881076..a5ea36e249 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## Current ### Features +- [#2497](https://github.com/poanetwork/blockscout/pull/2497) - Add generic Ordered Cache behaviour and implementation ### Fixes - [#2564](https://github.com/poanetwork/blockscout/pull/2564) - fix first page button for uncles and reorgs diff --git a/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs b/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs index 19099b8db5..54197c5866 100644 --- a/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs +++ b/apps/block_scout_web/test/block_scout_web/controllers/api/v1/health_controller_test.exs @@ -4,8 +4,8 @@ defmodule BlockScoutWeb.API.V1.HealthControllerTest do alias Explorer.{Chain, PagingOptions} setup do - Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()}) - Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()}) + Supervisor.terminate_child(Explorer.Supervisor, Explorer.Chain.Cache.Blocks.child_id()) + Supervisor.restart_child(Explorer.Supervisor, Explorer.Chain.Cache.Blocks.child_id()) :ok end diff --git a/apps/block_scout_web/test/support/conn_case.ex b/apps/block_scout_web/test/support/conn_case.ex index 3c7aef4e82..4ab8f3bcd9 100644 --- a/apps/block_scout_web/test/support/conn_case.ex +++ b/apps/block_scout_web/test/support/conn_case.ex @@ -40,8 +40,8 @@ defmodule BlockScoutWeb.ConnCase do Ecto.Adapters.SQL.Sandbox.mode(Explorer.Repo, {:shared, self()}) end - Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Transactions.cache_name()}) - Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Transactions.cache_name()}) + Supervisor.terminate_child(Explorer.Supervisor, Explorer.Chain.Cache.Transactions.child_id()) + Supervisor.restart_child(Explorer.Supervisor, Explorer.Chain.Cache.Transactions.child_id()) {:ok, conn: Phoenix.ConnTest.build_conn()} end diff --git a/apps/block_scout_web/test/support/feature_case.ex b/apps/block_scout_web/test/support/feature_case.ex index a9476a7b85..cdacd547bf 100644 --- a/apps/block_scout_web/test/support/feature_case.ex +++ b/apps/block_scout_web/test/support/feature_case.ex @@ -27,8 +27,8 @@ defmodule BlockScoutWeb.FeatureCase do Ecto.Adapters.SQL.Sandbox.mode(Explorer.Repo, {:shared, self()}) end - Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Transactions.cache_name()}) - Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Transactions.cache_name()}) + Supervisor.terminate_child(Explorer.Supervisor, Explorer.Chain.Cache.Transactions.child_id()) + Supervisor.restart_child(Explorer.Supervisor, Explorer.Chain.Cache.Transactions.child_id()) metadata = Phoenix.Ecto.SQL.Sandbox.metadata_for(Explorer.Repo, self()) {:ok, session} = Wallaby.start_session(metadata: metadata) diff --git a/apps/explorer/lib/explorer/application.ex b/apps/explorer/lib/explorer/application.ex index c1fb19f600..5f945a65ce 100644 --- a/apps/explorer/lib/explorer/application.ex +++ b/apps/explorer/lib/explorer/application.ex @@ -43,11 +43,11 @@ defmodule Explorer.Application do {Admin.Recovery, [[], [name: Admin.Recovery]]}, {TransactionCount, [[], []]}, {BlockCount, []}, - con_cache_child_spec(Blocks.cache_name()), + Blocks, con_cache_child_spec(NetVersion.cache_name()), con_cache_child_spec(MarketHistoryCache.cache_name()), con_cache_child_spec(RSK.cache_name(), ttl_check_interval: :timer.minutes(1), global_ttl: :timer.minutes(30)), - con_cache_child_spec(Transactions.cache_name()) + Transactions ] children = base_children ++ configurable_children() diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index 424636f005..dd85692de9 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -1258,14 +1258,16 @@ defmodule Explorer.Chain do block_type = Keyword.get(options, :block_type, "Block") if block_type == "Block" && !paging_options.key do - if Blocks.enough_elements?(paging_options.page_size) do - Blocks.blocks(paging_options.page_size) - else - elements = fetch_blocks(block_type, paging_options, necessity_by_association) + case Blocks.take_enough(paging_options.page_size) do + nil -> + elements = fetch_blocks(block_type, paging_options, necessity_by_association) + + Blocks.update(elements) - Blocks.rewrite_cache(elements) + elements - elements + blocks -> + blocks end else fetch_blocks(block_type, paging_options, necessity_by_association) diff --git a/apps/explorer/lib/explorer/chain/cache/blocks.ex b/apps/explorer/lib/explorer/chain/cache/blocks.ex index 76fc2473a6..4a18646d37 100644 --- a/apps/explorer/lib/explorer/chain/cache/blocks.ex +++ b/apps/explorer/lib/explorer/chain/cache/blocks.ex @@ -3,87 +3,19 @@ defmodule Explorer.Chain.Cache.Blocks do Caches the last imported blocks """ - alias Explorer.Repo + alias Explorer.Chain.Block - @block_numbers_key "block_numbers" - @cache_name :blocks - @number_of_elements 60 + use Explorer.Chain.OrderedCache, + name: :blocks, + max_size: 60, + ids_list_key: "block_numbers", + preload: :transactions, + preload: [miner: :names], + preload: :rewards - def update(block) do - numbers = block_numbers() + @type element :: Block.t() - max_number = if numbers == [], do: -1, else: Enum.max(numbers) - min_number = if numbers == [], do: -1, else: Enum.min(numbers) + @type id :: non_neg_integer() - in_range? = block.number > min_number && Enum.all?(numbers, fn number -> number != block.number end) - not_too_far_away? = block.number > max_number - @number_of_elements - 1 - - if (block.number > max_number || Enum.count(numbers) == 1 || in_range?) && not_too_far_away? do - if Enum.count(numbers) >= @number_of_elements do - remove_block(numbers) - put_block(block, List.delete(numbers, Enum.min(numbers))) - else - put_block(block, numbers) - end - end - end - - def rewrite_cache(elements) do - numbers = block_numbers() - - ConCache.delete(@cache_name, @block_numbers_key) - - numbers - |> Enum.each(fn number -> - ConCache.delete(@cache_name, number) - end) - - elements - |> Enum.reduce([], fn element, acc -> - put_block(element, acc) - - [element.number | acc] - end) - end - - def enough_elements?(number) do - ConCache.size(@cache_name) > number - end - - def update_blocks(blocks) do - Enum.each(blocks, fn block -> - update(block) - end) - end - - def blocks(number \\ nil) do - numbers = block_numbers() - - number = if is_nil(number), do: Enum.count(numbers), else: number - - numbers - |> Enum.sort() - |> Enum.reverse() - |> Enum.slice(0, number) - |> Enum.map(fn number -> - ConCache.get(@cache_name, number) - end) - end - - def cache_name, do: @cache_name - - def block_numbers do - ConCache.get(@cache_name, @block_numbers_key) || [] - end - - defp remove_block(numbers) do - min_number = Enum.min(numbers) - ConCache.delete(@cache_name, min_number) - end - - defp put_block(block, numbers) do - block_with_preloads = Repo.preload(block, [:transactions, [miner: :names], :rewards]) - ConCache.put(@cache_name, block.number, block_with_preloads) - ConCache.put(@cache_name, @block_numbers_key, [block.number | numbers]) - end + def element_to_id(%Block{number: number}), do: number end diff --git a/apps/explorer/lib/explorer/chain/cache/transactions.ex b/apps/explorer/lib/explorer/chain/cache/transactions.ex index 54748258cf..7dee7ec87d 100644 --- a/apps/explorer/lib/explorer/chain/cache/transactions.ex +++ b/apps/explorer/lib/explorer/chain/cache/transactions.ex @@ -4,140 +4,25 @@ defmodule Explorer.Chain.Cache.Transactions do """ alias Explorer.Chain.Transaction - alias Explorer.Repo - @transactions_ids_key "transactions_ids" - @cache_name :transactions - @max_size 51 - @preloads [ - :block, - created_contract_address: :names, - from_address: :names, - to_address: :names, - token_transfers: :token, - token_transfers: :from_address, - token_transfers: :to_address - ] - - @spec cache_name :: atom() - def cache_name, do: @cache_name - - @doc """ - Fetches a transaction from its id ({block_number, index}), returns nil if not found - """ - @spec get({non_neg_integer(), non_neg_integer()}) :: Transaction.t() | nil - def get(id), do: ConCache.get(@cache_name, id) - - @doc """ - Return the current number of transactions stored - """ - @spec size :: non_neg_integer() - def size, do: Enum.count(transactions_ids()) - - @doc """ - Checks if there are enough transactions stored - """ - @spec enough?(non_neg_integer()) :: boolean() - def enough?(amount) do - amount <= size() - end - - @doc """ - Checks if the number of transactions stored is already the max allowed - """ - @spec full? :: boolean() - def full? do - @max_size <= size() - end - - @doc "Returns the list ids of the transactions currently stored" - @spec transactions_ids :: [{non_neg_integer(), non_neg_integer()}] - def transactions_ids do - ConCache.get(@cache_name, @transactions_ids_key) || [] - end - - @doc "Returns all the stored transactions" - @spec all :: [Transaction.t()] - def all, do: Enum.map(transactions_ids(), &get(&1)) - - @doc "Returns the `n` most recent transactions stored" - @spec take(integer()) :: [Transaction.t()] - def take(amount) do - transactions_ids() - |> Enum.take(amount) - |> Enum.map(&get(&1)) - end - - @doc """ - Returns the `n` most recent transactions, unless there are not as many stored, - in which case returns `nil` - """ - @spec take_enough(integer()) :: [Transaction.t()] | nil - def take_enough(amount) do - if enough?(amount), do: take(amount) - end - - @doc """ - Adds a transaction (or a list of transactions). - If the cache is already full, the transaction will be only stored if it can take - the place of a less recent one. - NOTE: each transaction is inserted atomically - """ - @spec update([Transaction.t()] | Transaction.t() | nil) :: :ok - def update(transactions) when is_nil(transactions), do: :ok - - def update(transactions) when is_list(transactions) do - Enum.map(transactions, &update(&1)) - end - - def update(transaction) do - ConCache.isolated(@cache_name, @transactions_ids_key, fn -> - transaction_id = {transaction.block_number, transaction.index} - ids = transactions_ids() - - if full?() do - {init, [min]} = Enum.split(ids, -1) - - cond do - transaction_id < min -> - :ok - - transaction_id > min -> - insert_transaction(transaction_id, transaction, init) - ConCache.delete(@cache_name, min) - - transaction_id == min -> - put_transaction(transaction_id, transaction) - end - else - insert_transaction(transaction_id, transaction, ids) - end - end) - end - - defp insert_transaction(transaction_id, transaction, ids) do - put_transaction(transaction_id, transaction) - - ConCache.put(@cache_name, @transactions_ids_key, insert_sorted(transaction_id, ids)) - end - - defp put_transaction(transaction_id, transaction) do - full_transaction = Repo.preload(transaction, @preloads) - - ConCache.put(@cache_name, transaction_id, full_transaction) - end - - defp insert_sorted(id, ids) do - case ids do - [] -> - [id] - - [head | tail] -> - cond do - head > id -> [head | insert_sorted(id, tail)] - head < id -> [id | ids] - head == id -> ids - end - end + use Explorer.Chain.OrderedCache, + name: :transactions, + max_size: 51, + preloads: [ + :block, + created_contract_address: :names, + from_address: :names, + to_address: :names, + token_transfers: :token, + token_transfers: :from_address, + token_transfers: :to_address + ] + + @type element :: Transaction.t() + + @type id :: {non_neg_integer(), non_neg_integer()} + + def element_to_id(%Transaction{block_number: block_number, index: index}) do + {block_number, index} end end diff --git a/apps/explorer/lib/explorer/chain/ordered_cache.ex b/apps/explorer/lib/explorer/chain/ordered_cache.ex new file mode 100644 index 0000000000..2a1c0fc689 --- /dev/null +++ b/apps/explorer/lib/explorer/chain/ordered_cache.ex @@ -0,0 +1,326 @@ +defmodule Explorer.Chain.OrderedCache do + @moduledoc """ + Behaviour for a cache of ordered elements. + + A macro based on `ConCache` is provided as well, at its minimum it can be used as; + ``` + use Explorer.Chain.OrderedCache, name + ``` + where `name is an `t:atom/0` identifying the cache. + + All default values can be modified by overriding their respective function or + by setting an option. For example (showing all of them): + ``` + use Explorer.Chain.OrderedCache, + name: :name, # need to be set + max_size: 51, # defaults to 100 + ids_list_key: :ids_key, # defaults to `name` + preloads: [] # defaults to [] + ``` + Note: `preloads` can also be set singularly with the option `preload`, e.g.: + ``` + use Explorer.Chain.OrderedCache, + name: :cache + preload: :block + preload: :address + preload: [transaction: :hash] + ``` + Additionally all of the options accepted by `ConCache.start_link/1` can be + provided as well. By default only `ttl_check_interval:` is set (to `false`). + + It's also possible, and advised, to override the implementation of the `c:prevails?/2` + and `c:element_to_id/1` callbacks. + For typechecking purposes it's also recommended to override the `t:element/0` + and `t:id/0` type definitions. + """ + + @type element :: struct() + + @type id :: term() + + @doc """ + An atom that identifies this cache + """ + @callback cache_name :: atom() + + @doc """ + The key used to store the (ordered) list of elements. + Because this list is stored in the cache itself, one needs to make sure it is + cannot be equal to any element id. + """ + @callback ids_list_key :: term() + + @doc """ + The size that this cache cannot exceed. + """ + @callback max_size :: non_neg_integer() + + @doc """ + Fields of the stored elements that need to be preloaded. + For entities that are not stored in `Explorer.Repo` this should be empty. + """ + @callback preloads :: [term()] + + @doc """ + The function that orders the elements and decides the ones that are stored. + `prevails?(id_a, id_b)` should return `true` if (in case there is no space for both) + the element with `id_a` should be stored instead of the element with `id_b`, + `false` otherwise. + """ + @callback prevails?(id, id) :: boolean() + + @doc """ + The function that obtains an unique `t:id/0` from an `t:element/0` + """ + @callback element_to_id(element()) :: id() + + @doc "Returns the list ids of the elements currently stored" + @callback ids_list :: [id] + + @doc """ + Fetches a element from its id, returns nil if not found + """ + @callback get(id) :: element | nil + + @doc """ + Return the current number of elements stored + """ + @callback size() :: non_neg_integer() + + @doc """ + Checks if there are enough elements stored + """ + @callback enough?(non_neg_integer()) :: boolean() + + @doc """ + Checks if the number of elements stored is already the max allowed + """ + @callback full? :: boolean() + + @doc "Returns all the stored elements" + @callback all :: [element] + + @doc "Returns the `n` most prevailing elements stored, based on `c:prevails?/2`" + @callback take(integer()) :: [element] + + @doc """ + Returns the `n` most prevailing elements, based on `c:prevails?/2`, unless there + are not as many stored, in which case it returns `nil` + """ + @callback take_enough(integer()) :: [element] | nil + + @doc """ + Adds an element, or a list of elements, to the cache. + When the cache is full, only the most prevailing elements will be stored, based + on `c:prevails?/2`. + NOTE: every update is isolated from another one. + """ + @callback update([element] | element | nil) :: :ok + + defmacro __using__(name) when is_atom(name), do: do_using(name, []) + + defmacro __using__(opts) when is_list(opts) do + # name is necessary + name = Keyword.fetch!(opts, :name) + do_using(name, opts) + end + + # credo:disable-for-next-line /Complexity/ + defp do_using(name, opts) when is_atom(name) and is_list(opts) do + ids_list_key = Keyword.get(opts, :ids_list_key, name) + max_size = Keyword.get(opts, :max_size, 100) + preloads = Keyword.get(opts, :preloads) || Keyword.get_values(opts, :preload) + + concache_params = + opts + |> Keyword.drop([:ids_list_key, :max_size, :preloads, :preload]) + |> Keyword.put_new(:ttl_check_interval, false) + + # credo:disable-for-next-line Credo.Check.Refactor.LongQuoteBlocks + quote do + alias Explorer.Chain.OrderedCache + + @behaviour OrderedCache + + ### Automatically set functions + + @impl OrderedCache + def cache_name, do: unquote(name) + + @impl OrderedCache + def ids_list_key, do: unquote(ids_list_key) + + @impl OrderedCache + def max_size, do: unquote(max_size) + + @impl OrderedCache + def preloads, do: unquote(preloads) + + ### Settable functions + + @impl OrderedCache + def prevails?(id_a, id_b), do: id_a > id_b + + @impl OrderedCache + def element_to_id(element), do: element + + ### Straightforward fetching functions + + @impl OrderedCache + def ids_list, do: ConCache.get(cache_name(), ids_list_key()) || [] + + @impl OrderedCache + def get(id), do: ConCache.get(cache_name(), id) + + @impl OrderedCache + def size, do: ids_list() |> Enum.count() + + @impl OrderedCache + def enough?(amount), do: amount <= size() + + @impl OrderedCache + def full?, do: max_size() <= size() + + @impl OrderedCache + def all, do: Enum.map(ids_list(), &get(&1)) + + @impl OrderedCache + def take(amount) do + ids_list() + |> Enum.take(amount) + |> Enum.map(&get(&1)) + end + + @impl OrderedCache + def take_enough(amount) do + # behaves just like `if enough?(amount), do: take(amount)` but fetching + # the list only once + ids = ids_list() + + if amount <= Enum.count(ids) do + ids + |> Enum.take(amount) + |> Enum.map(&get(&1)) + end + end + + ### Updating function + + @impl OrderedCache + def update(elements) when is_nil(elements), do: :ok + + def update(elements) when is_list(elements) do + ConCache.update(cache_name(), ids_list_key(), fn ids -> + updated_list = + elements + |> Enum.map(&{element_to_id(&1), &1}) + |> Enum.sort(&prevails?(&1, &2)) + |> merge_and_update(ids || [], max_size()) + + {:ok, updated_list} + end) + end + + def update(element), do: update([element]) + + defp merge_and_update(_candidates, existing, 0) do + # if there is no more space in the list remove the remaining existing + # elements and return an empty list + remove(existing) + [] + end + + defp merge_and_update([], existing, size) do + # if there are no more candidates to be inserted keep as many of the + # exsisting elements and remove the rest + {remaining, to_remove} = Enum.split(existing, size) + remove(to_remove) + remaining + end + + defp merge_and_update(candidates, [], size) do + # if there are still candidates and no more existing value insert as many + # candidates as possible and ignore the rest + candidates + |> Enum.take(size) + |> Enum.map(fn {element_id, element} -> + put_element(element_id, element) + element_id + end) + end + + defp merge_and_update(candidates, existing, size) do + [{candidate_id, candidate} | to_check] = candidates + [head | tail] = existing + + cond do + head == candidate_id -> + # if a candidate has the id of and existing element, update its value + put_element(candidate_id, candidate) + [head | merge_and_update(to_check, tail, size - 1)] + + prevails?(head, candidate_id) -> + # keep the prevaling existing value and compare all candidates against the rest + [head | merge_and_update(candidates, tail, size - 1)] + + true -> + # insert new prevailing candidate and compare the remaining ones with the rest + put_element(candidate_id, candidate) + [candidate_id | merge_and_update(to_check, existing, size - 1)] + end + end + + defp remove(key) do + # Always performs async removal so it can wait 1/10 of a second and + # others have the time to get elements that were in the cache's list. + # Different updates cannot interfere with the removed element because + # if this was scheduled for removal it means it is too old, so following + # updates cannot insert it in the future. + Task.start(fn -> + Process.sleep(100) + + if is_list(key) do + Enum.map(key, &ConCache.delete(cache_name(), &1)) + else + ConCache.delete(cache_name(), key) + end + end) + end + + defp put_element(element_id, element) do + full_element = + if Enum.empty?(preloads()) do + element + else + Explorer.Repo.preload(element, preloads()) + end + + # dirty puts are a little faster than puts with locks. + # this is not a problem because this is the only function modifying rows + # and it only gets called inside `update`, which works isolated + ConCache.dirty_put(cache_name(), element_id, full_element) + end + + ### Supervisor's child specification + + @doc """ + The child specification for a Supervisor. Note that all the `params` + provided to this function will override the ones set by using the macro + """ + def child_spec(params) do + params = Keyword.merge(unquote(concache_params), params) + + Supervisor.child_spec({ConCache, params}, id: child_id()) + end + + def child_id, do: {ConCache, cache_name()} + + defoverridable cache_name: 0, + ids_list_key: 0, + max_size: 0, + preloads: 0, + prevails?: 2, + element_to_id: 1 + end + end +end diff --git a/apps/explorer/test/explorer/chain/cache/blocks_test.exs b/apps/explorer/test/explorer/chain/cache/blocks_test.exs index 52ac4eabb4..87f887ae26 100644 --- a/apps/explorer/test/explorer/chain/cache/blocks_test.exs +++ b/apps/explorer/test/explorer/chain/cache/blocks_test.exs @@ -16,7 +16,7 @@ defmodule Explorer.Chain.Cache.BlocksTest do Blocks.update(block) - assert Blocks.blocks() == [block] + assert Blocks.all() == [block] end test "adds a new elements removing the oldest one" do @@ -30,22 +30,16 @@ defmodule Explorer.Chain.Cache.BlocksTest do block.number end) + assert Blocks.size() == 60 + new_block = insert(:block, number: 70) Blocks.update(new_block) new_blocks = blocks |> List.replace_at(0, new_block.number) |> Enum.sort() |> Enum.reverse() - assert Enum.map(Blocks.blocks(), & &1.number) == new_blocks - end - - test "does not add too old blocks" do - block = insert(:block, number: 100_000) |> Repo.preload([:transactions, [miner: :names], :rewards]) - old_block = insert(:block, number: 1_000) + assert Blocks.full?() - Blocks.update(block) - Blocks.update(old_block) - - assert Blocks.blocks() == [block] + assert Enum.map(Blocks.all(), & &1.number) == new_blocks end test "adds missing element" do @@ -55,30 +49,13 @@ defmodule Explorer.Chain.Cache.BlocksTest do Blocks.update(block1) Blocks.update(block2) - assert Enum.count(Blocks.blocks()) == 2 + assert Blocks.size() == 2 block3 = insert(:block, number: 6) Blocks.update(block3) - assert Enum.map(Blocks.blocks(), & &1.number) == [10, 6, 4] - end - end - - describe "rewrite_cache/1" do - test "updates cache" do - block = insert(:block) - - Blocks.update(block) - - block1 = insert(:block) |> Repo.preload([:transactions, [miner: :names], :rewards]) - block2 = insert(:block) |> Repo.preload([:transactions, [miner: :names], :rewards]) - - new_blocks = [block1, block2] - - Blocks.rewrite_cache(new_blocks) - - assert Blocks.blocks() == [block2, block1] + assert Enum.map(Blocks.all(), & &1.number) == [10, 6, 4] end end end diff --git a/apps/explorer/test/explorer/market/market_history_cache_test.exs b/apps/explorer/test/explorer/market/market_history_cache_test.exs index 6dbd15fe7f..1ce5ba16f1 100644 --- a/apps/explorer/test/explorer/market/market_history_cache_test.exs +++ b/apps/explorer/test/explorer/market/market_history_cache_test.exs @@ -9,8 +9,8 @@ defmodule Explorer.Market.MarketHistoryCacheTest do Supervisor.restart_child(Explorer.Supervisor, {ConCache, MarketHistoryCache.cache_name()}) on_exit(fn -> - Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()}) - Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()}) + Supervisor.terminate_child(Explorer.Supervisor, Explorer.Chain.Cache.Blocks.child_id()) + Supervisor.restart_child(Explorer.Supervisor, Explorer.Chain.Cache.Blocks.child_id()) end) :ok diff --git a/apps/explorer/test/explorer/market/market_test.exs b/apps/explorer/test/explorer/market/market_test.exs index 881e1dccc8..44342b3996 100644 --- a/apps/explorer/test/explorer/market/market_test.exs +++ b/apps/explorer/test/explorer/market/market_test.exs @@ -6,12 +6,12 @@ defmodule Explorer.MarketTest do alias Explorer.Repo setup do - Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()}) - Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()}) + Supervisor.terminate_child(Explorer.Supervisor, Explorer.Chain.Cache.Blocks.child_id()) + Supervisor.restart_child(Explorer.Supervisor, Explorer.Chain.Cache.Blocks.child_id()) on_exit(fn -> - Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()}) - Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()}) + Supervisor.terminate_child(Explorer.Supervisor, Explorer.Chain.Cache.Blocks.child_id()) + Supervisor.restart_child(Explorer.Supervisor, Explorer.Chain.Cache.Blocks.child_id()) end) :ok diff --git a/apps/explorer/test/support/data_case.ex b/apps/explorer/test/support/data_case.ex index e159891987..fa87839725 100644 --- a/apps/explorer/test/support/data_case.ex +++ b/apps/explorer/test/support/data_case.ex @@ -40,10 +40,10 @@ defmodule Explorer.DataCase do end Explorer.Chain.Cache.BlockNumber.setup() - Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()}) - Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Blocks.cache_name()}) - Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Transactions.cache_name()}) - Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Chain.Cache.Transactions.cache_name()}) + Supervisor.terminate_child(Explorer.Supervisor, Explorer.Chain.Cache.Blocks.child_id()) + Supervisor.restart_child(Explorer.Supervisor, Explorer.Chain.Cache.Blocks.child_id()) + Supervisor.terminate_child(Explorer.Supervisor, Explorer.Chain.Cache.Transactions.child_id()) + Supervisor.restart_child(Explorer.Supervisor, Explorer.Chain.Cache.Transactions.child_id()) :ok end diff --git a/apps/indexer/lib/indexer/block/fetcher.ex b/apps/indexer/lib/indexer/block/fetcher.ex index 4155538e76..6a4eb3661b 100644 --- a/apps/indexer/lib/indexer/block/fetcher.ex +++ b/apps/indexer/lib/indexer/block/fetcher.ex @@ -189,7 +189,7 @@ defmodule Indexer.Block.Fetcher do BlockNumber.update(max_block.number) BlockNumber.update(min_block.number) - BlocksCache.update_blocks(blocks) + BlocksCache.update(blocks) end defp update_transactions_cache(transactions) do