Land #192: Remove credits and debits

pull/206/head
Luke Imhoff 7 years ago committed by GitHub
commit a0cdf8ea69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      apps/explorer/lib/explorer/chain.ex
  2. 9
      apps/explorer/lib/explorer/chain/address.ex
  3. 38
      apps/explorer/lib/explorer/chain/credit.ex
  4. 38
      apps/explorer/lib/explorer/chain/debit.ex
  5. 49
      apps/explorer/priv/repo/migrations/20180224004300_create_credit_debit_materialized_view.exs
  6. 83
      apps/explorer/test/explorer/chain/credit_test.exs
  7. 82
      apps/explorer/test/explorer/chain/debit_test.exs
  8. 4
      apps/explorer_web/test/explorer_web/controllers/address_controller_test.exs
  9. 5
      apps/explorer_web/test/explorer_web/features/viewing_transactions_test.exs
  10. 2
      coveralls.json

@ -387,8 +387,7 @@ defmodule Explorer.Chain do
query =
from(
address in Address,
where: address.hash == ^hash,
preload: [:credit, :debit]
where: address.hash == ^hash
)
query

@ -5,7 +5,7 @@ defmodule Explorer.Chain.Address do
use Explorer.Schema
alias Explorer.Chain.{Credit, Debit, Hash, Wei}
alias Explorer.Chain.{Hash, Wei}
@optional_attrs ~w()a
@required_attrs ~w(hash)a
@ -18,8 +18,6 @@ defmodule Explorer.Chain.Address do
@typedoc """
* `fetched_balance` - The last fetched balance from Parity
* `balance_fetched_at` - the last time `balance` was fetched
* `credit` - accumulation of all credits to the address `hash`
* `debit` - accumulation of all debits to the address `hash`
* `hash` - the hash of the address's public key
* `inserted_at` - when this address was inserted
* `updated_at` when this address was last updated
@ -27,8 +25,6 @@ defmodule Explorer.Chain.Address do
@type t :: %__MODULE__{
fetched_balance: Wei.t(),
balance_fetched_at: DateTime.t(),
credit: %Ecto.Association.NotLoaded{} | Credit.t() | nil,
debit: %Ecto.Association.NotLoaded{} | Debit.t() | nil,
hash: Hash.Truncated.t(),
inserted_at: DateTime.t(),
updated_at: DateTime.t()
@ -40,9 +36,6 @@ defmodule Explorer.Chain.Address do
field(:balance_fetched_at, Timex.Ecto.DateTime)
timestamps()
has_one(:credit, Credit)
has_one(:debit, Debit)
end
def balance_changeset(%__MODULE__{} = address, attrs) do

@ -1,38 +0,0 @@
defmodule Explorer.Chain.Credit do
@moduledoc """
A materialized view representing the credits to an address.
"""
use Explorer.Schema
alias Ecto.Adapters.SQL
alias Explorer.Chain.{Address, Hash, Wei}
alias Explorer.Repo
@typedoc """
* `address` - address that was the `to_address`
* `address_hash` - foreign key for `address`
* `count` - the number of credits to `address`
* `value` - sum of all credit values.
"""
@type t :: %__MODULE__{
address: %Ecto.Association.NotLoaded{} | Address.t(),
address_hash: Hash.Truncated.t(),
count: non_neg_integer,
value: Decimal.t()
}
@primary_key false
schema "credits" do
field(:count, :integer)
field(:value, Wei)
timestamps()
belongs_to(:address, Address, foreign_key: :address_hash, references: :hash, type: Hash.Truncated)
end
def refresh do
SQL.query!(Repo, "REFRESH MATERIALIZED VIEW CONCURRENTLY credits;", [], timeout: 120_000)
end
end

@ -1,38 +0,0 @@
defmodule Explorer.Chain.Debit do
@moduledoc """
A materialized view representing the debits from an address.
"""
use Explorer.Schema
alias Ecto.Adapters.SQL
alias Explorer.Chain.{Address, Hash, Wei}
alias Explorer.Repo
@typedoc """
* `address` - address that was the `from_address`
* `address_hash` - foreign key for `address`
* `count` - the number of debits to `address`
* `value` - sum of all debit values.
"""
@type t :: %__MODULE__{
address: %Ecto.Association.NotLoaded{} | Address.t(),
address_hash: Hash.Truncated.t(),
count: non_neg_integer,
value: Decimal.t()
}
@primary_key false
schema "debits" do
field(:count, :integer)
field(:value, Wei)
timestamps()
belongs_to(:address, Address, foreign_key: :address_hash, references: :hash, type: Hash.Truncated)
end
def refresh do
SQL.query!(Repo, "REFRESH MATERIALIZED VIEW CONCURRENTLY debits;", [], timeout: 120_000)
end
end

@ -1,49 +0,0 @@
defmodule Explorer.Repo.Migrations.UpdateCreditDebitMaterializedView do
use Ecto.Migration
def down do
execute("DROP MATERIALIZED VIEW IF EXISTS credits;")
execute("DROP MATERIALIZED VIEW IF EXISTS debits;")
end
def up do
execute("DROP MATERIALIZED VIEW IF EXISTS credits;")
execute("DROP MATERIALIZED VIEW IF EXISTS debits;")
execute("""
CREATE MATERIALIZED VIEW credits AS
SELECT addresses.hash AS address_hash,
COALESCE(SUM(transactions.value), 0) AS value,
COUNT(transactions.to_address_hash) AS count,
COALESCE(MIN(transactions.inserted_at), NOW()) AS inserted_at,
COALESCE(MAX(transactions.inserted_at), NOW()) AS updated_at
FROM addresses
INNER JOIN transactions ON transactions.to_address_hash = addresses.hash
INNER JOIN receipts ON receipts.transaction_hash = transactions.hash AND receipts.status = 1
GROUP BY addresses.hash
;
""")
execute("""
CREATE MATERIALIZED VIEW debits AS
SELECT addresses.hash AS address_hash,
COALESCE(SUM(transactions.value), 0) AS value,
COUNT(transactions.from_address_hash) AS count,
COALESCE(MIN(transactions.inserted_at), NOW()) AS inserted_at,
COALESCE(MAX(transactions.inserted_at), NOW()) AS updated_at
FROM addresses
INNER JOIN transactions ON transactions.from_address_hash = addresses.hash
INNER JOIN receipts ON receipts.transaction_hash = transactions.hash AND receipts.status = 1
GROUP BY addresses.hash
;
""")
create(unique_index(:credits, :address_hash))
create(index(:credits, :inserted_at))
create(index(:credits, :updated_at))
create(unique_index(:debits, :address_hash))
create(index(:debits, :inserted_at))
create(index(:debits, :updated_at))
end
end

@ -1,83 +0,0 @@
defmodule Explorer.Chain.CreditTest do
use Explorer.DataCase
alias Explorer.Chain.{Credit, Wei}
describe "Repo.all/1" do
test "returns no rows when there are no addresses" do
assert Repo.all(Credit) == []
end
test "returns nothing when an address has no transactions" do
insert(:address)
Credit.refresh()
assert Repo.one(Credit) == nil
end
test "returns a credit when there is an address with a receipt" do
recipient = insert(:address)
sender = insert(:address)
block = insert(:block)
transaction =
insert(
:transaction,
block_hash: block.hash,
index: 0,
to_address_hash: recipient.hash,
from_address_hash: sender.hash
)
insert(:receipt, status: :ok, transaction_hash: transaction.hash, transaction_index: transaction.index)
Credit.refresh()
credits = Credit |> Repo.all()
assert credits |> Enum.count() == 1
end
test "returns no credits to the sender" do
recipient = insert(:address)
sender = insert(:address)
block = insert(:block)
transaction =
insert(
:transaction,
block_hash: block.hash,
index: 0,
value: 21,
to_address_hash: recipient.hash,
from_address_hash: sender.hash
)
insert(:receipt, transaction_hash: transaction.hash, transaction_index: transaction.index, status: :ok)
address_hash = sender.hash
Credit.refresh()
credit = Credit |> where(address_hash: ^address_hash) |> Repo.one()
assert credit == nil
end
test "returns a credit to the recipient" do
recipient = insert(:address)
sender = insert(:address)
block = insert(:block)
transaction =
insert(
:transaction,
block_hash: block.hash,
index: 0,
value: 21,
to_address_hash: recipient.hash,
from_address_hash: sender.hash
)
insert(:receipt, status: :ok, transaction_hash: transaction.hash, transaction_index: transaction.index)
address_hash = recipient.hash
Credit.refresh()
credit = Credit |> where(address_hash: ^address_hash) |> Repo.one()
assert credit.value == %Wei{value: Decimal.new(21)}
end
end
end

@ -1,82 +0,0 @@
defmodule Explorer.Chain.DebitTest do
use Explorer.DataCase
alias Explorer.Chain.{Debit, Wei}
describe "Repo.all/1" do
test "returns no rows when there are no addresses" do
assert Repo.all(Debit) == []
end
test "returns nothing when an address has no transactions" do
insert(:address)
Debit.refresh()
assert Repo.one(Debit) == nil
end
test "returns a debit when there is an address with a receipt" do
recipient = insert(:address)
sender = insert(:address)
block = insert(:block)
transaction =
insert(
:transaction,
block_hash: block.hash,
index: 0,
to_address_hash: recipient.hash,
from_address_hash: sender.hash
)
insert(:receipt, transaction_hash: transaction.hash, transaction_index: transaction.index, status: :ok)
Debit.refresh()
debits = Debit |> Repo.all()
assert debits |> Enum.count() == 1
end
test "returns a debit against the sender" do
recipient = insert(:address)
sender = insert(:address)
block = insert(:block)
transaction =
insert(
:transaction,
block_hash: block.hash,
index: 0,
value: 21,
to_address_hash: recipient.hash,
from_address_hash: sender.hash
)
insert(:receipt, transaction_hash: transaction.hash, transaction_index: transaction.index, status: :ok)
address_hash = sender.hash
Debit.refresh()
debit = Debit |> where(address_hash: ^address_hash) |> Repo.one()
assert debit.value == %Wei{value: Decimal.new(21)}
end
test "returns no debits against the recipient" do
recipient = insert(:address)
sender = insert(:address)
block = insert(:block)
transaction =
insert(
:transaction,
block_hash: block.hash,
index: 0,
value: 21,
to_address_hash: recipient.hash,
from_address_hash: sender.hash
)
insert(:receipt, transaction_hash: transaction.hash, transaction_index: transaction.index, status: :ok)
address_hash = recipient.hash
Debit.refresh()
debit = Debit |> where(address_hash: ^address_hash) |> Repo.one()
assert debit == nil
end
end
end

@ -1,13 +1,9 @@
defmodule ExplorerWeb.AddressControllerTest do
use ExplorerWeb.ConnCase
alias Explorer.Chain.{Credit, Debit}
describe "GET show/3" do
test "redirects to addresses/:address_id/transactions", %{conn: conn} do
insert(:address, hash: "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed")
Credit.refresh()
Debit.refresh()
conn = get(conn, "/en/addresses/0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed")

@ -3,7 +3,7 @@ defmodule ExplorerWeb.ViewingTransactionsTest do
use ExplorerWeb.FeatureCase, async: true
alias Explorer.Chain.{Credit, Debit, Wei}
alias Explorer.Chain.Wei
alias ExplorerWeb.{AddressPage, HomePage, TransactionListPage, TransactionLogsPage, TransactionPage}
setup do
@ -54,9 +54,6 @@ defmodule ExplorerWeb.ViewingTransactionsTest do
internal = insert(:internal_transaction, transaction_hash: internal_receipt.transaction_hash)
Credit.refresh()
Debit.refresh()
{:ok,
%{
pending: pending,

@ -1,7 +1,7 @@
{
"coverage_options": {
"treat_no_relevant_lines_as_covered": true,
"minimum_coverage": 91.6
"minimum_coverage": 91.9
},
"terminal_options": {
"file_column_width": 120

Loading…
Cancel
Save