Merge pull request #2862 from poanetwork/vb-coin-total-supply-from-db-api
Coin total supply from DB API endpointab-do-not-remove-token-transfers
commit
29faeff3f1
@ -0,0 +1,53 @@ |
|||||||
|
defmodule Explorer.Chain.Cache.AddressSum do |
||||||
|
@moduledoc """ |
||||||
|
Cache for address sum. |
||||||
|
""" |
||||||
|
|
||||||
|
require Logger |
||||||
|
|
||||||
|
use Explorer.Chain.MapCache, |
||||||
|
name: :address_sum, |
||||||
|
key: :sum, |
||||||
|
key: :async_task, |
||||||
|
ttl_check_interval: Application.get_env(:explorer, __MODULE__)[:ttl_check_interval], |
||||||
|
global_ttl: Application.get_env(:explorer, __MODULE__)[:global_ttl], |
||||||
|
callback: &async_task_on_deletion(&1) |
||||||
|
|
||||||
|
alias Explorer.Chain |
||||||
|
|
||||||
|
defp handle_fallback(:sum) do |
||||||
|
# This will get the task PID if one exists and launch a new task if not |
||||||
|
# See next `handle_fallback` definition |
||||||
|
get_async_task() |
||||||
|
|
||||||
|
{:return, nil} |
||||||
|
end |
||||||
|
|
||||||
|
defp handle_fallback(:async_task) do |
||||||
|
# If this gets called it means an async task was requested, but none exists |
||||||
|
# so a new one needs to be launched |
||||||
|
{:ok, task} = |
||||||
|
Task.start(fn -> |
||||||
|
try do |
||||||
|
result = Chain.fetch_sum_coin_total_supply() |
||||||
|
|
||||||
|
set_sum(result) |
||||||
|
rescue |
||||||
|
e -> |
||||||
|
Logger.debug([ |
||||||
|
"Coudn't update address sum test #{inspect(e)}" |
||||||
|
]) |
||||||
|
end |
||||||
|
|
||||||
|
set_async_task(nil) |
||||||
|
end) |
||||||
|
|
||||||
|
{:update, task} |
||||||
|
end |
||||||
|
|
||||||
|
# By setting this as a `callback` an async task will be started each time the |
||||||
|
# `sum` expires (unless there is one already running) |
||||||
|
defp async_task_on_deletion({:delete, _, :sum}), do: get_async_task() |
||||||
|
|
||||||
|
defp async_task_on_deletion(_data), do: nil |
||||||
|
end |
@ -0,0 +1,56 @@ |
|||||||
|
defmodule Explorer.Chain.Cache.AddressSumTest do |
||||||
|
use Explorer.DataCase |
||||||
|
|
||||||
|
alias Explorer.Chain.Cache.AddressSum |
||||||
|
|
||||||
|
setup do |
||||||
|
Supervisor.terminate_child(Explorer.Supervisor, AddressSum.child_id()) |
||||||
|
Supervisor.restart_child(Explorer.Supervisor, AddressSum.child_id()) |
||||||
|
:ok |
||||||
|
end |
||||||
|
|
||||||
|
test "returns default address sum" do |
||||||
|
result = AddressSum.get_sum() |
||||||
|
|
||||||
|
assert is_nil(result) |
||||||
|
end |
||||||
|
|
||||||
|
test "updates cache if initial value is zero" do |
||||||
|
insert(:address, fetched_coin_balance: 1) |
||||||
|
insert(:address, fetched_coin_balance: 2) |
||||||
|
insert(:address, fetched_coin_balance: 3) |
||||||
|
|
||||||
|
_result = AddressSum.get_sum() |
||||||
|
|
||||||
|
Process.sleep(1000) |
||||||
|
|
||||||
|
updated_value = Decimal.to_integer(AddressSum.get_sum()) |
||||||
|
|
||||||
|
assert updated_value == 6 |
||||||
|
end |
||||||
|
|
||||||
|
test "does not update cache if cache period did not pass" do |
||||||
|
insert(:address, fetched_coin_balance: 1) |
||||||
|
insert(:address, fetched_coin_balance: 2) |
||||||
|
insert(:address, fetched_coin_balance: 3) |
||||||
|
|
||||||
|
_result = AddressSum.get_sum() |
||||||
|
|
||||||
|
Process.sleep(1000) |
||||||
|
|
||||||
|
updated_value = Decimal.to_integer(AddressSum.get_sum()) |
||||||
|
|
||||||
|
assert updated_value == 6 |
||||||
|
|
||||||
|
insert(:address, fetched_coin_balance: 4) |
||||||
|
insert(:address, fetched_coin_balance: 5) |
||||||
|
|
||||||
|
_updated_value = AddressSum.get_sum() |
||||||
|
|
||||||
|
Process.sleep(1000) |
||||||
|
|
||||||
|
updated_value = Decimal.to_integer(AddressSum.get_sum()) |
||||||
|
|
||||||
|
assert updated_value == 6 |
||||||
|
end |
||||||
|
end |
Loading…
Reference in new issue