Skip to content

Commit

Permalink
chore: encapsulate all Database calls through State (#762)
Browse files Browse the repository at this point in the history
* chore: encapsulate all Database calls through State

This also includes retrieving the State from the State plug in all
controllers which were missing it.

* fix: stop fetching blocks once root block is reached

* test: fix integration tests

* refactor: replace gen_collection with Collection implementation

* fix: return proper structure for aex9_search_contract
  • Loading branch information
sborrazas committed Jul 4, 2022
1 parent a3d8621 commit 922f7d8
Show file tree
Hide file tree
Showing 33 changed files with 309 additions and 665 deletions.
17 changes: 12 additions & 5 deletions lib/ae_mdw/aex9.ex
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ defmodule AeMdw.Aex9 do
account_balance_cursor() | nil}
| {:error, Error.t()}
def fetch_account_balances(state, account_pk, cursor, pagination) do
last_gen = DbUtil.last_gen()
last_gen = DbUtil.last_gen(state)
type_height_hash = {:key, last_gen, DbUtil.height_hash(last_gen)}

case deserialize_account_balance_cursor(cursor) do
Expand All @@ -200,7 +200,7 @@ defmodule AeMdw.Aex9 do
Model.aexn_contract(meta_info: {name, symbol, _dec}) =
State.fetch!(state, Model.AexnContract, {:aex9, contract_pk})

tx_idx = DbUtil.read_tx!(call_txi)
tx_idx = DbUtil.read_tx!(state, call_txi)
info = Format.to_raw_map(state, tx_idx)

%{
Expand All @@ -224,16 +224,23 @@ defmodule AeMdw.Aex9 do
end
end

@spec fetch_balance_history(pubkey(), pubkey(), range(), history_cursor(), pagination()) ::
@spec fetch_balance_history(
State.t(),
pubkey(),
pubkey(),
range(),
history_cursor(),
pagination()
) ::
{:ok, history_cursor() | nil, [aex9_balance_history_item()], history_cursor() | nil}
| {:error, Error.t()}
def fetch_balance_history(contract_pk, account_pk, range, cursor, pagination) do
def fetch_balance_history(state, contract_pk, account_pk, range, cursor, pagination) do
with :ok <- validate_aex9(contract_pk),
{:ok, cursor} <- deserialize_history_cursor(cursor) do
{first_gen, last_gen} =
case range do
{:gen, %Range{first: first, last: last}} -> {first, last}
nil -> {0, DbUtil.last_gen()}
nil -> {0, DbUtil.last_gen(state)}
end

streamer = fn
Expand Down
12 changes: 7 additions & 5 deletions lib/ae_mdw/collection.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ defmodule AeMdw.Collection do

alias AeMdw.Database
alias AeMdw.Db.State
alias AeMdw.Util

@type direction() :: Database.direction()
@type limit() :: Database.limit()
@typep table() :: Database.table()
@typep direction() :: Database.direction()
@typep cursor() :: Database.cursor()
@typep limit() :: Database.limit()
@typep key() :: Database.key()
@typep key_boundary() :: {key(), key()} | nil

Expand All @@ -29,7 +28,7 @@ defmodule AeMdw.Collection do
def paginate(stream_fn, {direction, false, limit, has_cursor?}) do
prev_cursor =
if has_cursor? do
case Enum.at(stream_fn.(Util.opposite_dir(direction)), 1) do
case Enum.at(stream_fn.(opposite_dir(direction)), 1) do
nil -> nil
cursor -> {cursor, true}
end
Expand All @@ -47,7 +46,7 @@ defmodule AeMdw.Collection do

def paginate(stream_fn, {direction, true, limit, has_cursor?}) do
{prev_cursor, records, next_cursor} =
paginate(stream_fn, {Util.opposite_dir(direction), false, limit, has_cursor?})
paginate(stream_fn, {opposite_dir(direction), false, limit, has_cursor?})

{reverse_cursor(next_cursor), Enum.reverse(records), reverse_cursor(prev_cursor)}
end
Expand Down Expand Up @@ -179,4 +178,7 @@ defmodule AeMdw.Collection do

defp reverse_cursor(nil), do: nil
defp reverse_cursor({cursor, is_reversed?}), do: {cursor, not is_reversed?}

defp opposite_dir(:backward), do: :forward
defp opposite_dir(:forward), do: :backward
end
83 changes: 14 additions & 69 deletions lib/ae_mdw/db/contract.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,23 @@ defmodule AeMdw.Db.Contract do
alias AeMdw.Collection
alias AeMdw.Contract
alias AeMdw.AexnContracts
alias AeMdw.Database
alias AeMdw.Db.Model
alias AeMdw.Db.Origin
alias AeMdw.Db.Sync
alias AeMdw.Db.State
alias AeMdw.Log
alias AeMdw.Node
alias AeMdw.Node.Db
alias AeMdw.Validate
alias AeMdw.Util

require Ex2ms
require Log
require Model
require Record

import AeMdw.Util, only: [compose: 2, min_bin: 0, max_256bit_bin: 0, max_256bit_int: 0]
import AeMdw.Util, only: [min_bin: 0, max_256bit_bin: 0]
import AeMdwWeb.Helpers.AexnHelper, only: [sort_field_truncate: 1]

import AeMdw.Db.Util

@type rev_aex9_contract_key :: {pos_integer(), String.t(), String.t(), pos_integer()}
@typep pubkey :: Db.pubkey()
@typep state :: State.t()
Expand Down Expand Up @@ -268,10 +265,10 @@ defmodule AeMdw.Db.Contract do
end
end

@spec call_fun_arg_res(pubkey(), integer()) :: Contract.fun_arg_res()
def call_fun_arg_res(contract_pk, call_txi) do
create_txi = Origin.tx_index!(State.new(), {:contract, contract_pk})
m_call = read!(Model.ContractCall, {create_txi, call_txi})
@spec call_fun_arg_res(State.t(), pubkey(), integer()) :: Contract.fun_arg_res()
def call_fun_arg_res(state, contract_pk, call_txi) do
create_txi = Origin.tx_index!(state, {:contract, contract_pk})
m_call = State.fetch!(state, Model.ContractCall, {create_txi, call_txi})

%{
function: Model.contract_call(m_call, :fun),
Expand All @@ -281,43 +278,6 @@ defmodule AeMdw.Db.Contract do
}
end

@spec aex9_search_name(tuple()) :: map()
def aex9_search_name({_, _} = mode),
do: aex9_search_tokens(Model.Aex9Contract, mode)

@spec aex9_search_symbol(tuple()) :: map()
def aex9_search_symbol({_, _} = mode),
do: aex9_search_tokens(Model.Aex9ContractSymbol, mode)

@spec aex9_search_contract_by_id(String.t()) :: {:ok, rev_aex9_contract_key()} | :not_found
def aex9_search_contract_by_id(contract_id) do
with pubkey <- Validate.id!(contract_id),
{:ok, Model.aexn_contract(txi: txi, meta_info: {name, symbol, decimals})} <-
Database.fetch(AexnContract, {:aex9, pubkey}) do
{:ok, {txi, name, symbol, decimals}}
end
end

@spec aex9_search_tokens(atom(), tuple()) :: map()
def aex9_search_tokens(table, {:prefix, prefix}),
do: aex9_search_tokens(table, prefix, prefix_tester(prefix))

def aex9_search_tokens(table, {:exact, exact}),
do: aex9_search_tokens(table, exact, &(&1 == exact))

@spec aex9_search_tokens(atom(), any(), any()) :: map()
def aex9_search_tokens(table, value, key_tester) do
gen_collect(
table,
{value, "", 0, 0},
compose(key_tester, &elem(&1, 0)),
&next/2,
fn -> [] end,
fn v, l -> [v | l] end,
&Enum.reverse/1
)
end

@spec aex9_search_transfers(
State.t(),
{:from, pubkey()}
Expand Down Expand Up @@ -354,21 +314,14 @@ defmodule AeMdw.Db.Contract do
|> Enum.dedup()
end

@spec aex9_search_contract(pubkey(), integer()) :: map()
def aex9_search_contract(account_pk, last_txi) do
gen_collect(
Model.Aex9AccountPresence,
{account_pk, last_txi, <<max_256bit_int()::256>>},
fn {acc_pk, _, _} -> acc_pk == account_pk end,
&prev/2,
fn -> %{} end,
fn {_, txi, ct_pk}, accum ->
Map.update(accum, ct_pk, [txi], fn txi_list ->
[txi | txi_list]
end)
end,
& &1
)
@spec aex9_search_contract(State.t(), pubkey(), integer()) :: map()
def aex9_search_contract(state, account_pk, last_txi) do
state
|> Collection.stream(Model.Aex9AccountPresence, {account_pk, last_txi, Util.min_int()})
|> Stream.take_while(&match?({^account_pk, _txi, _contract_pk}, &1))
|> Enum.reduce(%{}, fn {_account_pk, txi, contract_pk}, acc ->
Map.update(acc, contract_pk, [txi], &[txi | &1])
end)
end

@spec update_aex9_state(State.t(), pubkey(), block_index(), txi()) :: State.t()
Expand Down Expand Up @@ -412,14 +365,6 @@ defmodule AeMdw.Db.Contract do
end
end

defp prefix_tester(""),
do: fn _any -> true end

defp prefix_tester(prefix) do
len = byte_size(prefix)
&(byte_size(&1) >= len && :binary.part(&1, 0, len) == prefix)
end

defp write_aex9_records(state, txi, i, [from_pk, to_pk, <<amount::256>>]) do
m_transfer = Model.aex9_transfer(index: {from_pk, txi, to_pk, amount, i})
m_rev_transfer = Model.rev_aex9_transfer(index: {to_pk, txi, from_pk, amount, i})
Expand Down
Loading

0 comments on commit 922f7d8

Please sign in to comment.