parent
f04fe57690
commit
74512a094f
@ -0,0 +1,114 @@ |
||||
defmodule Explorer.Counters.AddressTransactionsCounter do |
||||
@moduledoc """ |
||||
Caches Address transactions counter. |
||||
""" |
||||
use GenServer |
||||
|
||||
alias Explorer.Chain |
||||
|
||||
@cache_name :address_transactions_counter |
||||
@last_update_key "last_update" |
||||
@cache_period Application.get_env(:explorer, __MODULE__)[:period] |
||||
|
||||
@ets_opts [ |
||||
:set, |
||||
:named_table, |
||||
:public, |
||||
read_concurrency: true |
||||
] |
||||
|
||||
config = Application.get_env(:explorer, Explorer.Counters.AddressesCounter) |
||||
@enable_consolidation Keyword.get(config, :enable_consolidation) |
||||
|
||||
@spec start_link(term()) :: GenServer.on_start() |
||||
def start_link(_) do |
||||
GenServer.start_link(__MODULE__, :ok, name: __MODULE__) |
||||
end |
||||
|
||||
@impl true |
||||
def init(_args) do |
||||
create_cache_table() |
||||
|
||||
{:ok, %{consolidate?: enable_consolidation?()}, {:continue, :ok}} |
||||
end |
||||
|
||||
@impl true |
||||
def handle_continue(:ok, %{consolidate?: true} = state) do |
||||
{:noreply, state} |
||||
end |
||||
|
||||
@impl true |
||||
def handle_continue(:ok, state) do |
||||
{:noreply, state} |
||||
end |
||||
|
||||
@impl true |
||||
def handle_info(:consolidate, state) do |
||||
{:noreply, state} |
||||
end |
||||
|
||||
def fetch(address) do |
||||
if cache_expired?() do |
||||
Task.async(fn -> |
||||
update_cache(address) |
||||
end) |
||||
end |
||||
|
||||
address_hash_string = get_address_hash_string(address) |
||||
fetch_from_cache("hash_#{address_hash_string}") |
||||
end |
||||
|
||||
def cache_name, do: @cache_name |
||||
|
||||
def updated_at_key, do: @last_update_key |
||||
|
||||
defp cache_expired? do |
||||
updated_at = fetch_from_cache(@last_update_key) |
||||
|
||||
cond do |
||||
is_nil(updated_at) -> true |
||||
current_time() - updated_at > @cache_period -> true |
||||
true -> false |
||||
end |
||||
end |
||||
|
||||
defp update_cache(address) do |
||||
put_into_cache(@last_update_key, current_time()) |
||||
|
||||
new_data = Chain.address_to_transaction_count(address) |
||||
address_hash_string = get_address_hash_string(address) |
||||
put_into_cache("hash_#{address_hash_string}", new_data) |
||||
end |
||||
|
||||
defp fetch_from_cache(key) do |
||||
case :ets.lookup(@cache_name, key) do |
||||
[{_, value}] -> |
||||
value |
||||
|
||||
[] -> |
||||
nil |
||||
end |
||||
end |
||||
|
||||
defp put_into_cache(key, value) do |
||||
:ets.insert(@cache_name, {key, value}) |
||||
end |
||||
|
||||
defp get_address_hash_string(address) do |
||||
Base.encode16(address.hash.bytes, case: :lower) |
||||
end |
||||
|
||||
defp current_time do |
||||
utc_now = DateTime.utc_now() |
||||
|
||||
DateTime.to_unix(utc_now, :millisecond) |
||||
end |
||||
|
||||
def create_cache_table do |
||||
if :ets.whereis(@cache_name) == :undefined do |
||||
:ets.new(@cache_name, @ets_opts) |
||||
end |
||||
end |
||||
|
||||
def enable_consolidation?, do: @enable_consolidation |
||||
end |
Loading…
Reference in new issue