Cache blocks and transactions in the chain statistics genserver

pull/3/head
Doc Ritezel 7 years ago
parent d537280366
commit b819733bf2
  1. 22
      lib/explorer/chain.ex
  2. 13
      lib/explorer/servers/chain_statistics.ex
  3. 25
      lib/explorer_web/controllers/chain_controller.ex
  4. 4
      lib/explorer_web/templates/chain/show.html.eex
  5. 16
      test/explorer/chain_test.exs
  6. 9
      test/explorer_web/controllers/chain_controller_test.exs

@ -7,7 +7,8 @@ defmodule Explorer.Chain do
alias Ecto.Adapters.SQL alias Ecto.Adapters.SQL
alias Explorer.Block alias Explorer.Block
alias Explorer.Repo alias Explorer.Transaction
alias Explorer.Repo, as: Repo
alias Timex.Duration alias Timex.Duration
defstruct [ defstruct [
@ -18,7 +19,9 @@ defmodule Explorer.Chain do
transaction_count: 0, transaction_count: 0,
skipped_blocks: 0, skipped_blocks: 0,
block_velocity: 0, block_velocity: 0,
transaction_velocity: 0 transaction_velocity: 0,
blocks: [],
transactions: []
] ]
@average_time_query """ @average_time_query """
@ -68,6 +71,17 @@ defmodule Explorer.Chain do
""" """
def fetch do def fetch do
blocks = from block in Block,
order_by: [desc: block.number],
preload: :transactions,
limit: 5
transactions = from transaction in Transaction,
join: block in assoc(transaction, :block),
order_by: [desc: block.number],
preload: [block: block],
limit: 5
last_block = Block |> Block.latest() |> limit(1) |> Repo.one() last_block = Block |> Block.latest() |> limit(1) |> Repo.one()
latest_block = last_block || Block.null latest_block = last_block || Block.null
%Explorer.Chain{ %Explorer.Chain{
@ -78,7 +92,9 @@ defmodule Explorer.Chain do
skipped_blocks: query_value(@skipped_blocks_query, [latest_block.number]), skipped_blocks: query_value(@skipped_blocks_query, [latest_block.number]),
lag: query_duration(@lag_query), lag: query_duration(@lag_query),
block_velocity: query_value(@block_velocity_query), block_velocity: query_value(@block_velocity_query),
transaction_velocity: query_value(@transaction_velocity_query) transaction_velocity: query_value(@transaction_velocity_query),
blocks: Repo.all(blocks),
transactions: Repo.all(transactions)
} }
end end

@ -10,17 +10,16 @@ defmodule Explorer.Servers.ChainStatistics do
def fetch do def fetch do
case GenServer.whereis(__MODULE__) do case GenServer.whereis(__MODULE__) do
nil -> Chain.fetch() nil -> Chain.fetch()
pid -> GenServer.call(pid, :fetch) _ -> GenServer.call(__MODULE__, :fetch)
end end
end end
def start_link, do: start_link(%Chain{})
def start_link(%Chain{} = chain) do
GenServer.start_link(__MODULE__, chain, name: __MODULE__)
end
def init(chain) do def start_link, do: start_link(nil)
def start_link(_), do: GenServer.start_link(__MODULE__, nil, name: __MODULE__)
def init(_) do
refresh() refresh()
{:ok, chain} {:ok, %Chain{}}
end end
def refresh, do: refresh(@interval) def refresh, do: refresh(@interval)

@ -1,32 +1,9 @@
defmodule ExplorerWeb.ChainController do defmodule ExplorerWeb.ChainController do
use ExplorerWeb, :controller use ExplorerWeb, :controller
import Ecto.Query
alias Explorer.Block
alias Explorer.BlockForm
alias Explorer.Servers.ChainStatistics alias Explorer.Servers.ChainStatistics
alias Explorer.Repo.NewRelic, as: Repo
alias Explorer.Transaction
def show(conn, _params) do def show(conn, _params) do
blocks = from block in Block, render(conn, "show.html", chain: ChainStatistics.fetch())
order_by: [desc: block.number],
preload: :transactions,
limit: 5
transactions = from transaction in Transaction,
join: block in assoc(transaction, :block),
order_by: [desc: block.number],
preload: [block: block],
limit: 5
render(
conn,
"show.html",
blocks: blocks |> Repo.all() |> Enum.map(&BlockForm.build/1),
transactions: transactions |> Repo.all(),
chain: ChainStatistics.fetch()
)
end end
end end

@ -64,7 +64,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<%= for block <- @blocks do %> <%= for block <- @chain.blocks do %>
<tr class="blocks__row"> <tr class="blocks__row">
<td class="blocks__column blocks__column--height"><%= link(block.number, to: block_path(@conn, :show, @conn.assigns.locale, block.number), class: "blocks__link") %></td> <td class="blocks__column blocks__column--height"><%= link(block.number, to: block_path(@conn, :show, @conn.assigns.locale, block.number), class: "blocks__link") %></td>
<td class="blocks__column blocks__column--age"><%= block.timestamp |> Timex.from_now %></td> <td class="blocks__column blocks__column--age"><%= block.timestamp |> Timex.from_now %></td>
@ -91,7 +91,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<%= for transaction <- @transactions do %> <%= for transaction <- @chain.transactions do %>
<tr class="transactions__row"> <tr class="transactions__row">
<td class="transactions__column transactions__column--hash"> <td class="transactions__column transactions__column--hash">
<div class="transactions__hash-container" title="<%= transaction.hash %>"> <div class="transactions__hash-container" title="<%= transaction.hash %>">

@ -80,5 +80,21 @@ defmodule Explorer.ChainTest do
chain = Chain.fetch() chain = Chain.fetch()
assert chain.transaction_velocity == 1 assert chain.transaction_velocity == 1
end end
test "returns the last five blocks" do
insert_list(6, :block)
chain = Chain.fetch()
assert chain.blocks |> Enum.count() == 5
end
test "returns the last five transactions with blocks" do
block = insert(:block)
insert_list(6, :transaction)
|> Enum.map(fn (transaction) ->
insert(:block_transaction, block: block, transaction: transaction)
end)
chain = Chain.fetch()
assert chain.transactions |> Enum.count() == 5
end
end end
end end

@ -22,7 +22,7 @@ defmodule ExplorerWeb.ChainControllerTest do
insert(:block, %{number: 23}) insert(:block, %{number: 23})
conn = get conn, "/en" conn = get conn, "/en"
assert(List.first(conn.assigns.blocks).number == 23) assert(List.first(conn.assigns.chain.blocks).number == 23)
end end
test "excludes all but the most recent five blocks", %{conn: conn} do test "excludes all but the most recent five blocks", %{conn: conn} do
@ -30,7 +30,7 @@ defmodule ExplorerWeb.ChainControllerTest do
insert_list(5, :block) insert_list(5, :block)
conn = get conn, "/en" conn = get conn, "/en"
refute(Enum.member?(conn.assigns.blocks, old_block)) refute(Enum.member?(conn.assigns.chain.blocks, old_block))
end end
test "only returns transactions with an associated block", %{conn: conn} do test "only returns transactions with an associated block", %{conn: conn} do
@ -38,7 +38,8 @@ defmodule ExplorerWeb.ChainControllerTest do
insert(:transaction, id: 10, hash: "0xDECAFBAD") |> with_block(block) |> with_addresses(%{to: "0xsleepypuppy", from: "0xilovefrogs"}) insert(:transaction, id: 10, hash: "0xDECAFBAD") |> with_block(block) |> with_addresses(%{to: "0xsleepypuppy", from: "0xilovefrogs"})
insert(:transaction, id: 30) insert(:transaction, id: 30)
conn = get conn, "/en" conn = get conn, "/en"
transaction_ids = conn.assigns.transactions |> Enum.map(fn (transaction) -> transaction.id end) transaction_ids = conn.assigns.chain.transactions
|> Enum.map(fn (transaction) -> transaction.id end)
assert(Enum.member?(transaction_ids, 10)) assert(Enum.member?(transaction_ids, 10))
refute(Enum.member?(transaction_ids, 30)) refute(Enum.member?(transaction_ids, 30))
@ -49,7 +50,7 @@ defmodule ExplorerWeb.ChainControllerTest do
insert(:transaction, hash: "0xDECAFBAD") |> with_block(block) |> with_addresses(%{to: "0xsleepypuppy", from: "0xilovefrogs"}) insert(:transaction, hash: "0xDECAFBAD") |> with_block(block) |> with_addresses(%{to: "0xsleepypuppy", from: "0xilovefrogs"})
conn = get conn, "/en" conn = get conn, "/en"
assert(List.first(conn.assigns.transactions).hash == "0xDECAFBAD") assert(List.first(conn.assigns.chain.transactions).hash == "0xDECAFBAD")
end end
end end
end end

Loading…
Cancel
Save