@ -1,5 +1,3 @@ |
||||
{ |
||||
presets: [ |
||||
'env' |
||||
] |
||||
"presets": ["@babel/preset-env"] |
||||
} |
||||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 9.5 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 424 B |
After Width: | Height: | Size: 794 B |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 7.2 KiB |
@ -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 |