Land #192: Remove credits and debits
commit
a0cdf8ea69
@ -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 |
Loading…
Reference in new issue