From ad9c070675bdabd08f81206d415a4e851644a877 Mon Sep 17 00:00:00 2001 From: Stamates Date: Mon, 6 Aug 2018 11:17:33 -0400 Subject: [PATCH 01/10] Rename from homepage to chain --- .../assets/__tests__/pages/chain.js | 2 +- .../assets/css/components/_animations.scss | 6 ++-- apps/explorer_web/assets/js/pages/chain.js | 2 +- .../explorer_web/channels/block_channel.ex | 4 +-- .../templates/chain/_block.html.eex | 2 +- .../pages/{home_page.ex => chain_page.ex} | 2 +- .../features/viewing_addresses_test.exs | 6 ++-- .../features/viewing_blocks_test.exs | 26 +++++++------- .../features/viewing_transactions_test.exs | 36 +++++++++---------- 9 files changed, 43 insertions(+), 43 deletions(-) rename apps/explorer_web/test/explorer_web/features/pages/{home_page.ex => chain_page.ex} (96%) diff --git a/apps/explorer_web/assets/__tests__/pages/chain.js b/apps/explorer_web/assets/__tests__/pages/chain.js index 86c84ad572..81e2939c5e 100644 --- a/apps/explorer_web/assets/__tests__/pages/chain.js +++ b/apps/explorer_web/assets/__tests__/pages/chain.js @@ -7,7 +7,7 @@ test('RECEIVED_NEW_BLOCK', () => { const action = { type: 'RECEIVED_NEW_BLOCK', msg: { - homepageBlockHtml: 'new block' + chainBlockHtml: 'new block' } } const output = reducer(state, action) diff --git a/apps/explorer_web/assets/css/components/_animations.scss b/apps/explorer_web/assets/css/components/_animations.scss index 22cd004011..ecb700e84d 100644 --- a/apps/explorer_web/assets/css/components/_animations.scss +++ b/apps/explorer_web/assets/css/components/_animations.scss @@ -3,7 +3,7 @@ 100% {opacity: 1;} } -@keyframes fade-up-blocks-homepage { +@keyframes fade-up-blocks-chain { 0% { flex-basis: 0%; width: 0%; @@ -45,10 +45,10 @@ animation: fade-in 1s ease-out forwards; } -.fade-up-blocks-homepage { +.fade-up-blocks-chain { will-change: transform, opacity, width; max-height: 98px; - animation: fade-up-blocks-homepage 0.6s cubic-bezier(0.455, 0.03, 0.515, 0.955); + animation: fade-up-blocks-chain 0.6s cubic-bezier(0.455, 0.03, 0.515, 0.955); } .fade-up { diff --git a/apps/explorer_web/assets/js/pages/chain.js b/apps/explorer_web/assets/js/pages/chain.js index 20b9772fe8..aa3e1c2aed 100644 --- a/apps/explorer_web/assets/js/pages/chain.js +++ b/apps/explorer_web/assets/js/pages/chain.js @@ -25,7 +25,7 @@ export function reducer (state = initialState, action) { } case 'RECEIVED_NEW_BLOCK': { return Object.assign({}, state, { - newBlock: action.msg.homepageBlockHtml + newBlock: action.msg.chainBlockHtml }) } case 'RECEIVED_NEW_TRANSACTION_BATCH': { diff --git a/apps/explorer_web/lib/explorer_web/channels/block_channel.ex b/apps/explorer_web/lib/explorer_web/channels/block_channel.ex index 24ca952827..bb060c52c1 100644 --- a/apps/explorer_web/lib/explorer_web/channels/block_channel.ex +++ b/apps/explorer_web/lib/explorer_web/channels/block_channel.ex @@ -24,7 +24,7 @@ defmodule ExplorerWeb.BlockChannel do block: block ) - rendered_homepage_block = + rendered_chain_block = View.render_to_string( ChainView, "_block.html", @@ -33,7 +33,7 @@ defmodule ExplorerWeb.BlockChannel do ) push(socket, "new_block", %{ - homepage_block_html: rendered_homepage_block, + chain_block_html: rendered_chain_block, block_html: rendered_block, blockNumber: block.number }) diff --git a/apps/explorer_web/lib/explorer_web/templates/chain/_block.html.eex b/apps/explorer_web/lib/explorer_web/templates/chain/_block.html.eex index 062f5ce51b..dcc4f2e9f1 100644 --- a/apps/explorer_web/lib/explorer_web/templates/chain/_block.html.eex +++ b/apps/explorer_web/lib/explorer_web/templates/chain/_block.html.eex @@ -1,4 +1,4 @@ -
+
<%= link(@block, to: block_path(ExplorerWeb.Endpoint, :show, @locale, @block), class: "tile-title") %>
diff --git a/apps/explorer_web/test/explorer_web/features/pages/home_page.ex b/apps/explorer_web/test/explorer_web/features/pages/chain_page.ex similarity index 96% rename from apps/explorer_web/test/explorer_web/features/pages/home_page.ex rename to apps/explorer_web/test/explorer_web/features/pages/chain_page.ex index f9e799788c..df7d2ed47e 100644 --- a/apps/explorer_web/test/explorer_web/features/pages/home_page.ex +++ b/apps/explorer_web/test/explorer_web/features/pages/chain_page.ex @@ -1,4 +1,4 @@ -defmodule ExplorerWeb.HomePage do +defmodule ExplorerWeb.ChainPage do @moduledoc false use Wallaby.DSL diff --git a/apps/explorer_web/test/explorer_web/features/viewing_addresses_test.exs b/apps/explorer_web/test/explorer_web/features/viewing_addresses_test.exs index 74b4b0ca75..9f458e46e6 100644 --- a/apps/explorer_web/test/explorer_web/features/viewing_addresses_test.exs +++ b/apps/explorer_web/test/explorer_web/features/viewing_addresses_test.exs @@ -3,7 +3,7 @@ defmodule ExplorerWeb.ViewingAddressesTest do alias Explorer.Chain alias Explorer.Chain.{Address, Wei} - alias ExplorerWeb.{AddressPage, HomePage, Notifier} + alias ExplorerWeb.{AddressPage, ChainPage, Notifier} setup do block = insert(:block) @@ -34,8 +34,8 @@ defmodule ExplorerWeb.ViewingAddressesTest do address = insert(:address) session - |> HomePage.visit_page() - |> HomePage.search(to_string(address.hash)) + |> ChainPage.visit_page() + |> ChainPage.search(to_string(address.hash)) |> assert_has(AddressPage.detail_hash(address)) end diff --git a/apps/explorer_web/test/explorer_web/features/viewing_blocks_test.exs b/apps/explorer_web/test/explorer_web/features/viewing_blocks_test.exs index 91a46da008..fa3fc4f6b2 100644 --- a/apps/explorer_web/test/explorer_web/features/viewing_blocks_test.exs +++ b/apps/explorer_web/test/explorer_web/features/viewing_blocks_test.exs @@ -1,7 +1,7 @@ defmodule ExplorerWeb.ViewingBlocksTest do use ExplorerWeb.FeatureCase, async: true - alias ExplorerWeb.{BlockListPage, BlockPage, HomePage, Notifier} + alias ExplorerWeb.{BlockListPage, BlockPage, ChainPage, Notifier} setup do timestamp = Timex.now() |> Timex.shift(hours: -1) @@ -20,33 +20,33 @@ defmodule ExplorerWeb.ViewingBlocksTest do {:ok, first_shown_block: newest_block, last_shown_block: oldest_block} end - test "viewing blocks on the home page", %{session: session} do + test "viewing blocks on the chain page", %{session: session} do session - |> HomePage.visit_page() - |> assert_has(HomePage.blocks(count: 4)) + |> ChainPage.visit_page() + |> assert_has(ChainPage.blocks(count: 4)) end - test "viewing new blocks via live update on homepage", %{session: session, last_shown_block: last_shown_block} do + test "viewing new blocks via live update on chain", %{session: session, last_shown_block: last_shown_block} do session - |> HomePage.visit_page() - |> assert_has(HomePage.blocks(count: 4)) + |> ChainPage.visit_page() + |> assert_has(ChainPage.blocks(count: 4)) block = insert(:block, number: 42) Notifier.handle_event({:chain_event, :blocks, [block]}) session - |> assert_has(HomePage.blocks(count: 4)) - |> assert_has(HomePage.block(block)) - |> refute_has(HomePage.block(last_shown_block)) + |> assert_has(ChainPage.blocks(count: 4)) + |> assert_has(ChainPage.block(block)) + |> refute_has(ChainPage.block(last_shown_block)) end - test "search for blocks from home page", %{session: session} do + test "search for blocks from chain page", %{session: session} do block = insert(:block, number: 42) session - |> HomePage.visit_page() - |> HomePage.search(to_string(block.number)) + |> ChainPage.visit_page() + |> ChainPage.search(to_string(block.number)) |> assert_has(BlockPage.detail_number(block)) end diff --git a/apps/explorer_web/test/explorer_web/features/viewing_transactions_test.exs b/apps/explorer_web/test/explorer_web/features/viewing_transactions_test.exs index cbfc679c4e..f70b9ea13e 100644 --- a/apps/explorer_web/test/explorer_web/features/viewing_transactions_test.exs +++ b/apps/explorer_web/test/explorer_web/features/viewing_transactions_test.exs @@ -4,7 +4,7 @@ defmodule ExplorerWeb.ViewingTransactionsTest do use ExplorerWeb.FeatureCase, async: true alias Explorer.Chain.Wei - alias ExplorerWeb.{AddressPage, HomePage, Notifier, TransactionListPage, TransactionLogsPage, TransactionPage} + alias ExplorerWeb.{AddressPage, ChainPage, Notifier, TransactionListPage, TransactionLogsPage, TransactionPage} setup do block = @@ -67,25 +67,25 @@ defmodule ExplorerWeb.ViewingTransactionsTest do transaction = insert(:transaction, input: "0x736f636b73") session - |> HomePage.visit_page() - |> HomePage.search(to_string(transaction.hash)) + |> ChainPage.visit_page() + |> ChainPage.search(to_string(transaction.hash)) |> assert_has(TransactionPage.detail_hash(transaction)) end describe "viewing transaction lists" do - test "transactions on the homepage", %{session: session} do + test "transactions on the chain", %{session: session} do session - |> HomePage.visit_page() - |> assert_has(HomePage.transactions(count: 5)) + |> ChainPage.visit_page() + |> assert_has(ChainPage.transactions(count: 5)) end - test "viewing new transactions via live update on the homepage", %{ + test "viewing new transactions via live update on the chain", %{ session: session, last_shown_transaction: last_shown_transaction } do session - |> HomePage.visit_page() - |> assert_has(HomePage.transactions(count: 5)) + |> ChainPage.visit_page() + |> assert_has(ChainPage.transactions(count: 5)) transaction = :transaction @@ -95,12 +95,12 @@ defmodule ExplorerWeb.ViewingTransactionsTest do Notifier.handle_event({:chain_event, :transactions, [transaction.hash]}) session - |> assert_has(HomePage.transactions(count: 5)) - |> assert_has(HomePage.transaction(transaction)) - |> refute_has(HomePage.transaction(last_shown_transaction)) + |> assert_has(ChainPage.transactions(count: 5)) + |> assert_has(ChainPage.transaction(transaction)) + |> refute_has(ChainPage.transaction(last_shown_transaction)) end - test "count of non-loaded transactions on homepage live update when batch overflow", %{session: session} do + test "count of non-loaded transactions on chain live update when batch overflow", %{session: session} do transaction_hashes = 30 |> insert_list(:transaction) @@ -108,15 +108,15 @@ defmodule ExplorerWeb.ViewingTransactionsTest do |> Enum.map(& &1.hash) session - |> HomePage.visit_page() - |> assert_has(HomePage.transactions(count: 5)) + |> ChainPage.visit_page() + |> assert_has(ChainPage.transactions(count: 5)) Notifier.handle_event({:chain_event, :transactions, transaction_hashes}) assert_has(session, AddressPage.non_loaded_transaction_count("30")) end - test "contract creation is shown for to_address on home page", %{session: session} do + test "contract creation is shown for to_address on chain page", %{session: session} do contract_address = insert(:contract_address) transaction = @@ -131,8 +131,8 @@ defmodule ExplorerWeb.ViewingTransactionsTest do |> with_contract_creation(contract_address) session - |> HomePage.visit_page() - |> assert_has(HomePage.contract_creation(internal_transaction)) + |> ChainPage.visit_page() + |> assert_has(ChainPage.contract_creation(internal_transaction)) end test "viewing the default transactions tab", %{ From e81dc2fd340fe9c11f6efc6b4637b050015163c3 Mon Sep 17 00:00:00 2001 From: Stamates Date: Mon, 6 Aug 2018 11:42:02 -0400 Subject: [PATCH 02/10] Setup chain page feature test and move related tests from other contexts --- .../explorer_web/features/pages/chain_page.ex | 4 + .../features/viewing_addresses_test.exs | 11 +- .../features/viewing_blocks_test.exs | 32 +--- .../features/viewing_chain_test.exs | 144 ++++++++++++++++++ .../features/viewing_transactions_test.exs | 73 +-------- 5 files changed, 151 insertions(+), 113 deletions(-) create mode 100644 apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs diff --git a/apps/explorer_web/test/explorer_web/features/pages/chain_page.ex b/apps/explorer_web/test/explorer_web/features/pages/chain_page.ex index df7d2ed47e..ba5d49ea9f 100644 --- a/apps/explorer_web/test/explorer_web/features/pages/chain_page.ex +++ b/apps/explorer_web/test/explorer_web/features/pages/chain_page.ex @@ -19,6 +19,10 @@ defmodule ExplorerWeb.ChainPage do css("[data-test='contract-creation'] [data-address-hash='#{hash}']") end + def non_loaded_transaction_count(count) do + css("[data-selector='channel-batching-count']", text: count) + end + def search(session, text) do session |> fill_in(css("[data-test='search_input']"), with: text) diff --git a/apps/explorer_web/test/explorer_web/features/viewing_addresses_test.exs b/apps/explorer_web/test/explorer_web/features/viewing_addresses_test.exs index 9f458e46e6..0dc9025acf 100644 --- a/apps/explorer_web/test/explorer_web/features/viewing_addresses_test.exs +++ b/apps/explorer_web/test/explorer_web/features/viewing_addresses_test.exs @@ -3,7 +3,7 @@ defmodule ExplorerWeb.ViewingAddressesTest do alias Explorer.Chain alias Explorer.Chain.{Address, Wei} - alias ExplorerWeb.{AddressPage, ChainPage, Notifier} + alias ExplorerWeb.{AddressPage, Notifier} setup do block = insert(:block) @@ -30,15 +30,6 @@ defmodule ExplorerWeb.ViewingAddressesTest do }} end - test "search for address", %{session: session} do - address = insert(:address) - - session - |> ChainPage.visit_page() - |> ChainPage.search(to_string(address.hash)) - |> assert_has(AddressPage.detail_hash(address)) - end - test "viewing address overview information", %{session: session} do address = insert(:address, fetched_balance: 500) diff --git a/apps/explorer_web/test/explorer_web/features/viewing_blocks_test.exs b/apps/explorer_web/test/explorer_web/features/viewing_blocks_test.exs index fa3fc4f6b2..8dd4690d9b 100644 --- a/apps/explorer_web/test/explorer_web/features/viewing_blocks_test.exs +++ b/apps/explorer_web/test/explorer_web/features/viewing_blocks_test.exs @@ -1,7 +1,7 @@ defmodule ExplorerWeb.ViewingBlocksTest do use ExplorerWeb.FeatureCase, async: true - alias ExplorerWeb.{BlockListPage, BlockPage, ChainPage, Notifier} + alias ExplorerWeb.{BlockListPage, BlockPage, Notifier} setup do timestamp = Timex.now() |> Timex.shift(hours: -1) @@ -20,36 +20,6 @@ defmodule ExplorerWeb.ViewingBlocksTest do {:ok, first_shown_block: newest_block, last_shown_block: oldest_block} end - test "viewing blocks on the chain page", %{session: session} do - session - |> ChainPage.visit_page() - |> assert_has(ChainPage.blocks(count: 4)) - end - - test "viewing new blocks via live update on chain", %{session: session, last_shown_block: last_shown_block} do - session - |> ChainPage.visit_page() - |> assert_has(ChainPage.blocks(count: 4)) - - block = insert(:block, number: 42) - - Notifier.handle_event({:chain_event, :blocks, [block]}) - - session - |> assert_has(ChainPage.blocks(count: 4)) - |> assert_has(ChainPage.block(block)) - |> refute_has(ChainPage.block(last_shown_block)) - end - - test "search for blocks from chain page", %{session: session} do - block = insert(:block, number: 42) - - session - |> ChainPage.visit_page() - |> ChainPage.search(to_string(block.number)) - |> assert_has(BlockPage.detail_number(block)) - end - test "show block detail page", %{session: session} do block = insert(:block, number: 42) diff --git a/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs b/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs new file mode 100644 index 0000000000..aef4615426 --- /dev/null +++ b/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs @@ -0,0 +1,144 @@ +defmodule ExplorerWeb.ViewingChainTest do + @moduledoc false + + use ExplorerWeb.FeatureCase, async: true + + alias ExplorerWeb.{AddressPage, BlockPage, ChainPage, Notifier, TransactionPage} + + setup do + [oldest_block | _] = Enum.map(1..4, &insert(:block, number: &1)) + + block = insert(:block, number: 5) + + [oldest_transaction | _] = + 4 + |> insert_list(:transaction) + |> with_block(block) + + :transaction + |> insert() + |> with_block(block) + + {:ok, + %{ + last_shown_block: oldest_block, + last_shown_transaction: oldest_transaction + }} + end + + describe "viewing addresses" do + test "search for address", %{session: session} do + address = insert(:address) + + session + |> ChainPage.visit_page() + |> ChainPage.search(to_string(address.hash)) + |> assert_has(AddressPage.detail_hash(address)) + end + end + + describe "viewing blocks" do + test "search for blocks from chain page", %{session: session} do + block = insert(:block, number: 6) + + session + |> ChainPage.visit_page() + |> ChainPage.search(to_string(block.number)) + |> assert_has(BlockPage.detail_number(block)) + end + + test "blocks list", %{session: session} do + session + |> ChainPage.visit_page() + |> assert_has(ChainPage.blocks(count: 4)) + end + + test "viewing new blocks via live update", %{session: session, last_shown_block: last_shown_block} do + session + |> ChainPage.visit_page() + |> assert_has(ChainPage.blocks(count: 4)) + + block = insert(:block, number: 6) + + Notifier.handle_event({:chain_event, :blocks, [block]}) + + session + |> assert_has(ChainPage.blocks(count: 4)) + |> assert_has(ChainPage.block(block)) + |> refute_has(ChainPage.block(last_shown_block)) + end + end + + describe "viewing transactions" do + test "search for transactions", %{session: session} do + transaction = insert(:transaction) + + session + |> ChainPage.visit_page() + |> ChainPage.search(to_string(transaction.hash)) + |> assert_has(TransactionPage.detail_hash(transaction)) + end + + test "transactions list", %{session: session} do + session + |> ChainPage.visit_page() + |> assert_has(ChainPage.transactions(count: 5)) + end + + test "viewing new transactions via live update", %{ + session: session, + last_shown_transaction: last_shown_transaction + } do + session + |> ChainPage.visit_page() + |> assert_has(ChainPage.transactions(count: 5)) + + transaction = + :transaction + |> insert() + |> with_block() + + Notifier.handle_event({:chain_event, :transactions, [transaction.hash]}) + + session + |> assert_has(ChainPage.transactions(count: 5)) + |> assert_has(ChainPage.transaction(transaction)) + |> refute_has(ChainPage.transaction(last_shown_transaction)) + end + + test "count of non-loaded transactions live update when batch overflow", %{session: session} do + transaction_hashes = + 30 + |> insert_list(:transaction) + |> with_block() + |> Enum.map(& &1.hash) + + session + |> ChainPage.visit_page() + |> assert_has(ChainPage.transactions(count: 5)) + + Notifier.handle_event({:chain_event, :transactions, transaction_hashes}) + + assert_has(session, ChainPage.non_loaded_transaction_count("30")) + end + + test "contract creation is shown for to_address", %{session: session} do + contract_address = insert(:contract_address) + + transaction = + :transaction + |> insert(to_address: nil) + |> with_contract_creation(contract_address) + |> with_block() + + internal_transaction = + :internal_transaction_create + |> insert(transaction: transaction, index: 0) + |> with_contract_creation(contract_address) + + session + |> ChainPage.visit_page() + |> assert_has(ChainPage.contract_creation(internal_transaction)) + end + end +end diff --git a/apps/explorer_web/test/explorer_web/features/viewing_transactions_test.exs b/apps/explorer_web/test/explorer_web/features/viewing_transactions_test.exs index f70b9ea13e..6ea47cca30 100644 --- a/apps/explorer_web/test/explorer_web/features/viewing_transactions_test.exs +++ b/apps/explorer_web/test/explorer_web/features/viewing_transactions_test.exs @@ -4,7 +4,7 @@ defmodule ExplorerWeb.ViewingTransactionsTest do use ExplorerWeb.FeatureCase, async: true alias Explorer.Chain.Wei - alias ExplorerWeb.{AddressPage, ChainPage, Notifier, TransactionListPage, TransactionLogsPage, TransactionPage} + alias ExplorerWeb.{AddressPage, Notifier, TransactionListPage, TransactionLogsPage, TransactionPage} setup do block = @@ -63,78 +63,7 @@ defmodule ExplorerWeb.ViewingTransactionsTest do }} end - test "search for transactions", %{session: session} do - transaction = insert(:transaction, input: "0x736f636b73") - - session - |> ChainPage.visit_page() - |> ChainPage.search(to_string(transaction.hash)) - |> assert_has(TransactionPage.detail_hash(transaction)) - end - describe "viewing transaction lists" do - test "transactions on the chain", %{session: session} do - session - |> ChainPage.visit_page() - |> assert_has(ChainPage.transactions(count: 5)) - end - - test "viewing new transactions via live update on the chain", %{ - session: session, - last_shown_transaction: last_shown_transaction - } do - session - |> ChainPage.visit_page() - |> assert_has(ChainPage.transactions(count: 5)) - - transaction = - :transaction - |> insert() - |> with_block() - - Notifier.handle_event({:chain_event, :transactions, [transaction.hash]}) - - session - |> assert_has(ChainPage.transactions(count: 5)) - |> assert_has(ChainPage.transaction(transaction)) - |> refute_has(ChainPage.transaction(last_shown_transaction)) - end - - test "count of non-loaded transactions on chain live update when batch overflow", %{session: session} do - transaction_hashes = - 30 - |> insert_list(:transaction) - |> with_block() - |> Enum.map(& &1.hash) - - session - |> ChainPage.visit_page() - |> assert_has(ChainPage.transactions(count: 5)) - - Notifier.handle_event({:chain_event, :transactions, transaction_hashes}) - - assert_has(session, AddressPage.non_loaded_transaction_count("30")) - end - - test "contract creation is shown for to_address on chain page", %{session: session} do - contract_address = insert(:contract_address) - - transaction = - :transaction - |> insert(to_address: nil) - |> with_contract_creation(contract_address) - |> with_block() - - internal_transaction = - :internal_transaction_create - |> insert(transaction: transaction, index: 0) - |> with_contract_creation(contract_address) - - session - |> ChainPage.visit_page() - |> assert_has(ChainPage.contract_creation(internal_transaction)) - end - test "viewing the default transactions tab", %{ session: session, first_shown_transaction: transaction, From ef75a9dbcc59c8af402e97dd97aeb56b4ceef48a Mon Sep 17 00:00:00 2001 From: Stamates Date: Mon, 6 Aug 2018 13:30:56 -0400 Subject: [PATCH 03/10] Remove unused transaction_velocity statistic --- .../explorer/lib/explorer/chain/statistics.ex | 19 ------------------- .../test/explorer/chain/statistics_test.exs | 8 -------- 2 files changed, 27 deletions(-) diff --git a/apps/explorer/lib/explorer/chain/statistics.ex b/apps/explorer/lib/explorer/chain/statistics.ex index 80a7c8be21..cffa528805 100644 --- a/apps/explorer/lib/explorer/chain/statistics.ex +++ b/apps/explorer/lib/explorer/chain/statistics.ex @@ -19,22 +19,11 @@ defmodule Explorer.Chain.Statistics do ) t """ - @transaction_velocity_query """ - SELECT count(transactions.inserted_at) - FROM transactions - WHERE transactions.inserted_at > NOW() - interval '1 minute' - """ - @typedoc """ The number of `t:Explorer.Chain.Block.t/0` mined/validated per minute. """ @type blocks_per_minute :: non_neg_integer() - @typedoc """ - The number of `t:Explorer.Chain.Transaction.t/0` mined/validated per minute. - """ - @type transactions_per_minute :: non_neg_integer() - @typedoc """ * `average_time` - the average time it took to mine/validate the last <= 100 `t:Explorer.Chain.Block.t/0` * `blocks` - the last <= 5 `t:Explorer.Chain.Block.t/0` @@ -51,7 +40,6 @@ defmodule Explorer.Chain.Statistics do blocks: [Block.t()], number: Block.block_number(), timestamp: :calendar.datetime(), - transaction_velocity: transactions_per_minute(), transactions: [Transaction.t()] } @@ -59,7 +47,6 @@ defmodule Explorer.Chain.Statistics do blocks: [], number: -1, timestamp: nil, - transaction_velocity: 0, transactions: [] def fetch do @@ -84,7 +71,6 @@ defmodule Explorer.Chain.Statistics do %__MODULE__{ average_time: query_duration(@average_time_query), blocks: Repo.all(blocks), - transaction_velocity: query_value(@transaction_velocity_query), transactions: transactions } |> put_max_numbered_block() @@ -104,11 +90,6 @@ defmodule Explorer.Chain.Statistics do end end - defp query_value(query, args \\ []) do - results = SQL.query!(Repo, query, args) - results.rows |> List.first() |> List.first() - end - defp query_duration(query) do results = SQL.query!(Repo, query, []) diff --git a/apps/explorer/test/explorer/chain/statistics_test.exs b/apps/explorer/test/explorer/chain/statistics_test.exs index 4a4544880e..45b7197920 100644 --- a/apps/explorer/test/explorer/chain/statistics_test.exs +++ b/apps/explorer/test/explorer/chain/statistics_test.exs @@ -45,14 +45,6 @@ defmodule Explorer.Chain.StatisticsTest do } = Statistics.fetch() end - test "returns the number of transactions inserted in the last minute" do - old_inserted_at = Timex.shift(DateTime.utc_now(), days: -1) - insert(:transaction, inserted_at: old_inserted_at) - insert(:transaction) - - assert %Statistics{transaction_velocity: 1} = Statistics.fetch() - end - test "returns the last five blocks" do insert_list(5, :block) From 88174b36170e6a86636cad91917951b1c849fb20 Mon Sep 17 00:00:00 2001 From: Stamates Date: Mon, 6 Aug 2018 14:51:08 -0400 Subject: [PATCH 04/10] Setup tests for live update of avg_block_time and number of addresses --- .../templates/chain/show.html.eex | 8 ++--- .../explorer_web/features/pages/chain_page.ex | 8 +++++ .../features/viewing_chain_test.exs | 33 +++++++++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex b/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex index 15ee6be8ae..1d92f3f44c 100644 --- a/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex +++ b/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex @@ -27,8 +27,8 @@ <%= gettext "Average block time" %> - - <%= @chain.average_time |> Timex.format_duration(:humanized) %> + + <%= Timex.format_duration(@chain.average_time, :humanized) %>
@@ -43,8 +43,8 @@ <%= gettext "Wallet addresses" %> - - <%= @address_estimated_count |> Cldr.Number.to_string!(format: "#,###") %> + + <%= Cldr.Number.to_string!(@address_estimated_count, format: "#,###") %>
diff --git a/apps/explorer_web/test/explorer_web/features/pages/chain_page.ex b/apps/explorer_web/test/explorer_web/features/pages/chain_page.ex index ba5d49ea9f..2e00e754a4 100644 --- a/apps/explorer_web/test/explorer_web/features/pages/chain_page.ex +++ b/apps/explorer_web/test/explorer_web/features/pages/chain_page.ex @@ -7,6 +7,14 @@ defmodule ExplorerWeb.ChainPage do alias Explorer.Chain.{Block, InternalTransaction, Transaction} + def address_count(count) do + css("[data-selector='address-count']", text: Integer.to_string(count)) + end + + def average_time(average_time) do + css("[data-selector='average-block-time']", text: Integer.to_string(average_time)) + end + def block(%Block{number: number}) do css("[data-selector='chain-block'][data-block-number='#{number}']") end diff --git a/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs b/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs index aef4615426..2b6bec110e 100644 --- a/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs +++ b/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs @@ -3,6 +3,7 @@ defmodule ExplorerWeb.ViewingChainTest do use ExplorerWeb.FeatureCase, async: true + alias Explorer.Chain alias ExplorerWeb.{AddressPage, BlockPage, ChainPage, Notifier, TransactionPage} setup do @@ -26,6 +27,38 @@ defmodule ExplorerWeb.ViewingChainTest do }} end + describe "statistics" do + test "average block time live updates", %{session: session} do + time = DateTime.utc_now() + for x <- 100..0 do + insert(:block, timestamp: Timex.shift(time, seconds: -5 * x - 100_000), number: x + 100) + end + + session + |> ChainPage.visit_page() + |> assert_has(ChainPage.average_time(5)) + + for x <- 100..0 do + insert(:block, timestamp: Timex.shift(time, seconds: -10 * x), number: x + 300) + end + + assert_has(session, ChainPage.average_time(10)) + end + + test "address count live updates", %{session: session} do + count = Chain.address_estimated_count() + + session + |> ChainPage.visit_page() + |> assert_has(ChainPage.address_count(count)) + + address = insert(:address) + Notifier.handle_event({:chain_event, :addresses, [address]}) + + assert_has(session, ChainPage.address_count(count + 1)) + end + end + describe "viewing addresses" do test "search for address", %{session: session} do address = insert(:address) From faa53be558ded6fc312135c44df2c7e761dae958 Mon Sep 17 00:00:00 2001 From: Stamates Date: Mon, 6 Aug 2018 15:46:38 -0400 Subject: [PATCH 05/10] Eliminate unused statistics context and gen_server and move statistics function into Chain context. --- apps/explorer/config/config.exs | 2 - apps/explorer/config/test.exs | 2 - apps/explorer/lib/explorer/application.ex | 1 - apps/explorer/lib/explorer/chain.ex | 25 ++++ .../explorer/lib/explorer/chain/statistics.ex | 104 --------------- .../lib/explorer/chain/statistics/server.ex | 77 ----------- .../explorer/chain/statistics/server_test.exs | 120 ------------------ .../test/explorer/chain/statistics_test.exs | 68 ---------- .../controllers/chain_controller.ex | 32 ++++- .../templates/chain/show.html.eex | 6 +- .../controllers/chain_controller_test.exs | 8 +- .../explorer_web/features/pages/chain_page.ex | 4 +- .../features/viewing_chain_test.exs | 26 ++-- 13 files changed, 73 insertions(+), 402 deletions(-) delete mode 100644 apps/explorer/lib/explorer/chain/statistics.ex delete mode 100644 apps/explorer/lib/explorer/chain/statistics/server.ex delete mode 100644 apps/explorer/test/explorer/chain/statistics/server_test.exs delete mode 100644 apps/explorer/test/explorer/chain/statistics_test.exs diff --git a/apps/explorer/config/config.exs b/apps/explorer/config/config.exs index cd3303320f..751929b65c 100644 --- a/apps/explorer/config/config.exs +++ b/apps/explorer/config/config.exs @@ -14,8 +14,6 @@ config :explorer, config :explorer, Explorer.Integrations.EctoLogger, query_time_ms_threshold: 2_000 -config :explorer, Explorer.Chain.Statistics.Server, enabled: true - config :explorer, Explorer.ExchangeRates, enabled: true config :explorer, Explorer.Market.History.Cataloger, enabled: true diff --git a/apps/explorer/config/test.exs b/apps/explorer/config/test.exs index 82f3cad908..5b7d3ce164 100644 --- a/apps/explorer/config/test.exs +++ b/apps/explorer/config/test.exs @@ -13,8 +13,6 @@ config :explorer, Explorer.Repo, pool_timeout: 10_000, ownership_timeout: 60_000 -config :explorer, Explorer.Chain.Statistics.Server, enabled: false - config :explorer, Explorer.ExchangeRates, enabled: false config :explorer, Explorer.Market.History.Cataloger, enabled: false diff --git a/apps/explorer/lib/explorer/application.ex b/apps/explorer/lib/explorer/application.ex index f10f2e7115..3b51056942 100644 --- a/apps/explorer/lib/explorer/application.ex +++ b/apps/explorer/lib/explorer/application.ex @@ -24,7 +24,6 @@ defmodule Explorer.Application do defp configurable_children do [ - configure(Explorer.Chain.Statistics.Server), configure(Explorer.ExchangeRates), configure(Explorer.Market.History.Cataloger) ] diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index 3e0133ad4b..8d94dee0ff 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -188,6 +188,31 @@ defmodule Explorer.Chain do |> Repo.all() end + + @doc """ + The average time it took to mine/validate the last <= 100 `t:Explorer.Chain.Block.t/0` + """ + @spec average_block_time() :: non_neg_integer() + def average_block_time() do + {:ok, %Postgrex.Result{rows: [[rows]]}} = + SQL.query( + Repo, + """ + SELECT coalesce(avg(difference), interval '0 seconds') + FROM ( + SELECT b.timestamp - lag(b.timestamp) over (order by b.timestamp) as difference + FROM (SELECT * FROM blocks ORDER BY number DESC LIMIT 101) b + LIMIT 100 OFFSET 1 + ) t + """, + [] + ) + + {:ok, value} = Timex.Ecto.Time.load(rows) + + value + end + @doc """ The `t:Explorer.Chain.Address.t/0` `balance` in `unit`. """ diff --git a/apps/explorer/lib/explorer/chain/statistics.ex b/apps/explorer/lib/explorer/chain/statistics.ex deleted file mode 100644 index cffa528805..0000000000 --- a/apps/explorer/lib/explorer/chain/statistics.ex +++ /dev/null @@ -1,104 +0,0 @@ -defmodule Explorer.Chain.Statistics do - @moduledoc """ - Represents statistics about the chain. - """ - - import Ecto.Query - - alias Ecto.Adapters.SQL - alias Explorer.{Chain, PagingOptions, Repo} - alias Explorer.Chain.{Block, Transaction} - alias Timex.Duration - - @average_time_query """ - SELECT coalesce(avg(difference), interval '0 seconds') - FROM ( - SELECT b.timestamp - lag(b.timestamp) over (order by b.timestamp) as difference - FROM (SELECT * FROM blocks ORDER BY number DESC LIMIT 101) b - LIMIT 100 OFFSET 1 - ) t - """ - - @typedoc """ - The number of `t:Explorer.Chain.Block.t/0` mined/validated per minute. - """ - @type blocks_per_minute :: non_neg_integer() - - @typedoc """ - * `average_time` - the average time it took to mine/validate the last <= 100 `t:Explorer.Chain.Block.t/0` - * `blocks` - the last <= 5 `t:Explorer.Chain.Block.t/0` - (`t:Explorer.Chain.Block.t/0` `timestamp`) and when it was inserted into the databasse - (`t:Explorer.Chain.Block.t/0` `inserted_at`) - * `number` - the latest `t:Explorer.Chain.Block.t/0` `number` - `t:Explorer.Chain.Block.t/0` - * `timestamp` - when the last `t:Explorer.Chain.Block.t/0` was mined/validated - * `transaction_velocity` - the number of `t:Explorer.Chain.Block.t/0` mined/validated in the last minute - * `transactions` - the last <= 5 `t:Explorer.Chain.Transaction.t/0` - """ - @type t :: %__MODULE__{ - average_time: Duration.t(), - blocks: [Block.t()], - number: Block.block_number(), - timestamp: :calendar.datetime(), - transactions: [Transaction.t()] - } - - defstruct average_time: %Duration{seconds: 0, megaseconds: 0, microseconds: 0}, - blocks: [], - number: -1, - timestamp: nil, - transactions: [] - - def fetch do - blocks = - from( - block in Block, - order_by: [desc: block.number], - preload: [:miner, :transactions], - limit: 4 - ) - - transactions = - Chain.recent_collated_transactions( - necessity_by_association: %{ - block: :required, - from_address: :required, - to_address: :optional - }, - paging_options: %PagingOptions{page_size: 5} - ) - - %__MODULE__{ - average_time: query_duration(@average_time_query), - blocks: Repo.all(blocks), - transactions: transactions - } - |> put_max_numbered_block() - end - - defp put_max_numbered_block(state) do - case Chain.max_numbered_block() do - {:ok, %Block{number: number, timestamp: timestamp}} -> - %__MODULE__{ - state - | number: number, - timestamp: timestamp - } - - {:error, :not_found} -> - state - end - end - - defp query_duration(query) do - results = SQL.query!(Repo, query, []) - - {:ok, value} = - results.rows - |> List.first() - |> List.first() - |> Timex.Ecto.Time.load() - - value - end -end diff --git a/apps/explorer/lib/explorer/chain/statistics/server.ex b/apps/explorer/lib/explorer/chain/statistics/server.ex deleted file mode 100644 index a2ed3c58e6..0000000000 --- a/apps/explorer/lib/explorer/chain/statistics/server.ex +++ /dev/null @@ -1,77 +0,0 @@ -defmodule Explorer.Chain.Statistics.Server do - @moduledoc "Stores the latest chain statistics." - - use GenServer - - require Logger - - alias Explorer.Chain.Statistics - - @interval 1_000 - - defstruct statistics: %Statistics{}, - task: nil - - def child_spec(_) do - Supervisor.Spec.worker(__MODULE__, [[refresh: true]]) - end - - @spec fetch() :: Statistics.t() - def fetch do - GenServer.call(__MODULE__, :fetch) - end - - def start_link(opts \\ []) do - GenServer.start_link(__MODULE__, opts, name: __MODULE__) - end - - @impl GenServer - def init(options) when is_list(options) do - if Keyword.get(options, :refresh, true) do - send(self(), :refresh) - end - - {:ok, %__MODULE__{}} - end - - @impl GenServer - - def handle_info(:refresh, %__MODULE__{task: task} = state) do - new_state = - case task do - nil -> - %__MODULE__{state | task: Task.Supervisor.async_nolink(Explorer.TaskSupervisor, Statistics, :fetch, [])} - - _ -> - state - end - - {:noreply, new_state} - end - - def handle_info({ref, %Statistics{} = statistics}, %__MODULE__{task: %Task{ref: ref}} = state) do - Process.demonitor(ref, [:flush]) - Process.send_after(self(), :refresh, @interval) - - {:noreply, %__MODULE__{state | statistics: statistics, task: nil}} - end - - def handle_info({:DOWN, ref, :process, pid, reason}, %__MODULE__{task: %Task{pid: pid, ref: ref}} = state) do - Logger.error(fn -> "#{inspect(Statistics)}.fetch failed and could not be cached: #{inspect(reason)}" end) - - Process.send_after(self(), :refresh, @interval) - - {:noreply, %__MODULE__{state | task: nil}} - end - - @impl GenServer - def handle_call(:fetch, _, %__MODULE__{statistics: %Statistics{} = statistics} = state), - do: {:reply, statistics, state} - - @impl GenServer - def terminate(_, %__MODULE__{task: nil}), do: :ok - - def terminate(_, %__MODULE__{task: task}) do - Task.shutdown(task) - end -end diff --git a/apps/explorer/test/explorer/chain/statistics/server_test.exs b/apps/explorer/test/explorer/chain/statistics/server_test.exs deleted file mode 100644 index 251bf01e0f..0000000000 --- a/apps/explorer/test/explorer/chain/statistics/server_test.exs +++ /dev/null @@ -1,120 +0,0 @@ -defmodule Explorer.Chain.Statistics.ServerTest do - use Explorer.DataCase, async: false - - import ExUnit.CaptureLog - - alias Explorer.Chain.Statistics - alias Explorer.Chain.Statistics.Server - - # shutdown: "owner exited with: shutdown" error from polluting logs when tests are successful - @moduletag :capture_log - - describe "child_spec/1" do - test "it defines a child_spec/1 that works with supervisors" do - insert(:block) - - assert {:ok, pid} = start_supervised(Server) - - %Server{task: %Task{pid: pid}} = :sys.get_state(pid) - ref = Process.monitor(pid) - - assert_receive {:DOWN, ^ref, :process, ^pid, _} - end - end - - describe "init/1" do - test "returns a new chain when not told to refresh" do - empty_statistics = %Statistics{} - - assert {:ok, %Server{statistics: ^empty_statistics}} = Server.init(refresh: false) - end - - test "returns a new Statistics when told to refresh" do - empty_statistics = %Statistics{} - - assert {:ok, %Server{statistics: ^empty_statistics}} = Server.init(refresh: true) - end - - test "refreshes when told to refresh" do - {:ok, _} = Server.init([]) - - assert_receive :refresh, 2_000 - end - end - - describe "handle_info/2" do - setup :state - - test "returns the original statistics when sent a :refresh message", %{ - state: %Server{statistics: statistics} = state - } do - assert {:noreply, %Server{statistics: ^statistics, task: task}} = Server.handle_info(:refresh, state) - - Task.await(task) - end - - test "launches a Statistics.fetch Task update when sent a :refresh message", %{state: state} do - assert {:noreply, %Server{task: %Task{} = task}} = Server.handle_info(:refresh, state) - - assert %Statistics{} = Task.await(task) - end - - test "stores successful Task in state", %{state: state} do - # so that `statistics` from Task will be different - insert(:block) - - assert {:noreply, %Server{task: %Task{ref: ref}} = refresh_state} = Server.handle_info(:refresh, state) - - assert_receive {^ref, %Statistics{} = message_statistics} = message - - assert {:noreply, %Server{statistics: ^message_statistics, task: nil}} = - Server.handle_info(message, refresh_state) - - refute message_statistics == state.statistics - end - - test "logs crashed Task", %{state: state} do - assert {:noreply, %Server{task: %Task{pid: pid, ref: ref}} = refresh_state} = Server.handle_info(:refresh, state) - - Process.exit(pid, :boom) - - assert_receive {:DOWN, ^ref, :process, ^pid, :boom} = message - - captured_log = - capture_log(fn -> - assert {:noreply, %Server{task: nil}} = Server.handle_info(message, refresh_state) - end) - - assert captured_log =~ "Explorer.Chain.Statistics.fetch failed and could not be cached: :boom" - end - end - - describe "handle_call/3" do - test "replies with statistics when sent a :fetch message" do - original = Statistics.fetch() - state = %Server{statistics: original} - - assert {:reply, ^original, ^state} = Server.handle_call(:fetch, self(), state) - end - end - - describe "terminate/2" do - setup :state - - test "cleans up in-progress tasks when terminated", %{state: state} do - assert {:noreply, %Server{task: %Task{pid: pid}} = refresh_state} = Server.handle_info(:refresh, state) - - second_ref = Process.monitor(pid) - - Server.terminate(:boom, refresh_state) - - assert_receive {:DOWN, ^second_ref, :process, ^pid, :shutdown} - end - end - - defp state(_) do - {:ok, state} = Server.init([]) - - %{state: state} - end -end diff --git a/apps/explorer/test/explorer/chain/statistics_test.exs b/apps/explorer/test/explorer/chain/statistics_test.exs deleted file mode 100644 index 45b7197920..0000000000 --- a/apps/explorer/test/explorer/chain/statistics_test.exs +++ /dev/null @@ -1,68 +0,0 @@ -defmodule Explorer.Chain.StatisticsTest do - use Explorer.DataCase - - alias Explorer.Chain.Statistics - alias Timex.Duration - - describe "fetch/0" do - test "returns -1 for the number when there are no blocks" do - assert %Statistics{number: -1} = Statistics.fetch() - end - - test "returns the highest block number when there is a block" do - insert(:block, number: 1) - - max_number = 100 - insert(:block, number: max_number) - - assert %Statistics{number: ^max_number} = Statistics.fetch() - end - - test "returns the latest block timestamp" do - time = DateTime.utc_now() - insert(:block, timestamp: time) - - statistics = Statistics.fetch() - - assert Timex.diff(statistics.timestamp, time, :seconds) == 0 - end - - test "returns the average time between blocks for the last 100 blocks" do - time = DateTime.utc_now() - - insert(:block, timestamp: Timex.shift(time, seconds: -1000)) - - for x <- 100..0 do - insert(:block, timestamp: Timex.shift(time, seconds: -5 * x)) - end - - assert %Statistics{ - average_time: %Duration{ - seconds: 5, - megaseconds: 0, - microseconds: 0 - } - } = Statistics.fetch() - end - - test "returns the last five blocks" do - insert_list(5, :block) - - statistics = Statistics.fetch() - - assert statistics.blocks |> Enum.count() == 4 - end - - test "returns the last five transactions with blocks" do - Enum.map(0..5, fn _ -> - :transaction - |> insert() - |> with_block() - end) - - statistics = Statistics.fetch() - - assert statistics.transactions |> Enum.count() == 5 - end - end -end diff --git a/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex b/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex index ab8ab89445..ffdc2bd1c4 100644 --- a/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex +++ b/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex @@ -1,30 +1,48 @@ defmodule ExplorerWeb.ChainController do use ExplorerWeb, :controller - alias Explorer.Chain.{Address, Block, Statistics, Transaction} + alias Explorer.{PagingOptions, Repo} + alias Explorer.Chain + alias Explorer.Chain.{Address, Block, Transaction} alias Explorer.ExchangeRates.Token alias Explorer.Market - alias ExplorerWeb.Chain def show(conn, _params) do - transaction_estimated_count = Explorer.Chain.transaction_estimated_count() - address_estimated_count = Explorer.Chain.address_estimated_count() + transaction_estimated_count = Chain.transaction_estimated_count() + address_estimated_count = Chain.address_estimated_count() + + transactions = + Chain.recent_collated_transactions( + necessity_by_association: %{ + block: :required, + from_address: :required, + to_address: :optional + }, + paging_options: %PagingOptions{page_size: 5} + ) + + blocks = + [paging_options: %PagingOptions{page_size: 4}] + |> Chain.list_blocks() + |> Repo.preload([:miner, :transactions]) render( conn, "show.html", address_estimated_count: address_estimated_count, - chain: Statistics.fetch(), + average_block_time: Chain.average_block_time(), + blocks: blocks, exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(), market_history_data: Market.fetch_recent_history(30), - transaction_estimated_count: transaction_estimated_count + transaction_estimated_count: transaction_estimated_count, + transactions: transactions ) end def search(conn, %{"q" => query}) do query |> String.trim() - |> Chain.from_param() + |> ExplorerWeb.Chain.from_param() |> case do {:ok, item} -> redirect_search_results(conn, item) diff --git a/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex b/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex index 1d92f3f44c..ed19477357 100644 --- a/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex +++ b/apps/explorer_web/lib/explorer_web/templates/chain/show.html.eex @@ -28,7 +28,7 @@ <%= gettext "Average block time" %> - <%= Timex.format_duration(@chain.average_time, :humanized) %> + <%= Timex.format_duration(@average_block_time, :humanized) %>
@@ -57,7 +57,7 @@ <%= link(gettext("View All Blocks →"), to: block_path(ExplorerWeb.Endpoint, :index, Gettext.get_locale), class: "button button--secondary button--xsmall float-right") %>

<%= gettext "Blocks" %>

- <%= for block <- @chain.blocks do %> + <%= for block <- @blocks do %> <%= render ExplorerWeb.ChainView, "_block.html", locale: @locale, block: block %> <% end %>
@@ -74,7 +74,7 @@ <%= link(gettext("View All Transactions →"), to: transaction_path(ExplorerWeb.Endpoint, :index, Gettext.get_locale), class: "button button--secondary button--xsmall float-right") %>

<%= gettext "Transactions" %>

- <%= for transaction <- @chain.transactions do %> + <%= for transaction <- @transactions do %> <%= render ExplorerWeb.TransactionView, "_tile.html", locale: @locale, transaction: transaction %> <% end %> diff --git a/apps/explorer_web/test/explorer_web/controllers/chain_controller_test.exs b/apps/explorer_web/test/explorer_web/controllers/chain_controller_test.exs index 8b46530a01..98c0be9085 100644 --- a/apps/explorer_web/test/explorer_web/controllers/chain_controller_test.exs +++ b/apps/explorer_web/test/explorer_web/controllers/chain_controller_test.exs @@ -22,7 +22,7 @@ defmodule ExplorerWeb.ChainControllerTest do insert(:block, %{number: 23}) conn = get(conn, "/en") - assert(List.first(conn.assigns.chain.blocks).number == 23) + assert(List.first(conn.assigns.blocks).number == 23) end test "excludes all but the most recent five blocks", %{conn: conn} do @@ -30,7 +30,7 @@ defmodule ExplorerWeb.ChainControllerTest do insert_list(5, :block) conn = get(conn, "/en") - refute(Enum.member?(conn.assigns.chain.blocks, old_block)) + refute(Enum.member?(conn.assigns.blocks, old_block)) end test "only returns transactions with an associated block", %{conn: conn} do @@ -43,7 +43,7 @@ defmodule ExplorerWeb.ChainControllerTest do conn = get(conn, "/en") - transaction_hashes = Enum.map(conn.assigns.chain.transactions, fn transaction -> transaction.hash end) + transaction_hashes = Enum.map(conn.assigns.transactions, fn transaction -> transaction.hash end) assert(Enum.member?(transaction_hashes, associated.hash)) refute(Enum.member?(transaction_hashes, unassociated.hash)) @@ -57,7 +57,7 @@ defmodule ExplorerWeb.ChainControllerTest do conn = get(conn, "/en") - assert(List.first(conn.assigns.chain.transactions).hash == transaction.hash) + assert(List.first(conn.assigns.transactions).hash == transaction.hash) end test "returns market history data", %{conn: conn} do diff --git a/apps/explorer_web/test/explorer_web/features/pages/chain_page.ex b/apps/explorer_web/test/explorer_web/features/pages/chain_page.ex index 2e00e754a4..bd08da570c 100644 --- a/apps/explorer_web/test/explorer_web/features/pages/chain_page.ex +++ b/apps/explorer_web/test/explorer_web/features/pages/chain_page.ex @@ -5,7 +5,7 @@ defmodule ExplorerWeb.ChainPage do import Wallaby.Query, only: [css: 1, css: 2] - alias Explorer.Chain.{Block, InternalTransaction, Transaction} + alias Explorer.Chain.{Block, Transaction} def address_count(count) do css("[data-selector='address-count']", text: Integer.to_string(count)) @@ -23,7 +23,7 @@ defmodule ExplorerWeb.ChainPage do css("[data-selector='chain-block']", count: count) end - def contract_creation(%InternalTransaction{created_contract_address_hash: hash}) do + def contract_creation(%Transaction{created_contract_address_hash: hash}) do css("[data-test='contract-creation'] [data-address-hash='#{hash}']") end diff --git a/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs b/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs index 2b6bec110e..ce0753d66a 100644 --- a/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs +++ b/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs @@ -7,9 +7,9 @@ defmodule ExplorerWeb.ViewingChainTest do alias ExplorerWeb.{AddressPage, BlockPage, ChainPage, Notifier, TransactionPage} setup do - [oldest_block | _] = Enum.map(1..4, &insert(:block, number: &1)) + [oldest_block | _] = Enum.map(401..404, &insert(:block, number: &1)) - block = insert(:block, number: 5) + block = insert(:block, number: 405) [oldest_transaction | _] = 4 @@ -22,6 +22,7 @@ defmodule ExplorerWeb.ViewingChainTest do {:ok, %{ + block: block, last_shown_block: oldest_block, last_shown_transaction: oldest_transaction }} @@ -120,6 +121,7 @@ defmodule ExplorerWeb.ViewingChainTest do test "viewing new transactions via live update", %{ session: session, + block: block, last_shown_transaction: last_shown_transaction } do session @@ -129,7 +131,7 @@ defmodule ExplorerWeb.ViewingChainTest do transaction = :transaction |> insert() - |> with_block() + |> with_block(block) Notifier.handle_event({:chain_event, :transactions, [transaction.hash]}) @@ -139,11 +141,11 @@ defmodule ExplorerWeb.ViewingChainTest do |> refute_has(ChainPage.transaction(last_shown_transaction)) end - test "count of non-loaded transactions live update when batch overflow", %{session: session} do + test "count of non-loaded transactions live update when batch overflow", %{session: session, block: block} do transaction_hashes = 30 |> insert_list(:transaction) - |> with_block() + |> with_block(block) |> Enum.map(& &1.hash) session @@ -155,23 +157,23 @@ defmodule ExplorerWeb.ViewingChainTest do assert_has(session, ChainPage.non_loaded_transaction_count("30")) end - test "contract creation is shown for to_address", %{session: session} do + test "contract creation is shown for to_address", %{session: session, block: block} do contract_address = insert(:contract_address) transaction = :transaction |> insert(to_address: nil) |> with_contract_creation(contract_address) - |> with_block() + |> with_block(block) - internal_transaction = - :internal_transaction_create - |> insert(transaction: transaction, index: 0) - |> with_contract_creation(contract_address) + # internal_transaction = + # :internal_transaction_create + # |> insert(transaction: transaction, index: 0) + # |> with_contract_creation(contract_address) session |> ChainPage.visit_page() - |> assert_has(ChainPage.contract_creation(internal_transaction)) + |> assert_has(ChainPage.contract_creation(transaction)) end end end From 5c50e08fd16b81fa4f52c69a8ec4becddb443f5e Mon Sep 17 00:00:00 2001 From: Stamates Date: Mon, 6 Aug 2018 16:44:22 -0400 Subject: [PATCH 06/10] Live update average_block_time --- apps/explorer_web/assets/js/pages/chain.js | 6 ++++++ .../lib/explorer_web/channels/block_channel.ex | 3 ++- apps/explorer_web/lib/explorer_web/notifier.ex | 6 +++++- .../explorer_web/features/pages/chain_page.ex | 4 ++-- .../features/viewing_chain_test.exs | 17 +++++++++++------ 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/apps/explorer_web/assets/js/pages/chain.js b/apps/explorer_web/assets/js/pages/chain.js index aa3e1c2aed..aea629f7de 100644 --- a/apps/explorer_web/assets/js/pages/chain.js +++ b/apps/explorer_web/assets/js/pages/chain.js @@ -10,6 +10,7 @@ import { batchChannel, initRedux } from '../utils' const BATCH_THRESHOLD = 10 export const initialState = { + averageBlockTime: null, batchCountAccumulator: 0, newBlock: null, newTransactions: [], @@ -25,6 +26,7 @@ export function reducer (state = initialState, action) { } case 'RECEIVED_NEW_BLOCK': { return Object.assign({}, state, { + averageBlockTime: action.msg.averageBlockTime, newBlock: action.msg.chainBlockHtml }) } @@ -67,12 +69,16 @@ router.when('', { exactPathMatch: true }).then(({ locale }) => initRedux(reducer ) }, render (state, oldState) { + const $averageBlockTime = $('[data-selector="average-block-time"]') const $blockList = $('[data-selector="chain-block-list"]') const $channelBatching = $('[data-selector="channel-batching-message"]') const $channelBatchingCount = $('[data-selector="channel-batching-count"]') const $transactionsList = $('[data-selector="transactions-list"]') const $transactionCount = $('[data-selector="transaction-count"]') + if (oldState.averageBlockTime !== state.averageBlockTime) { + $averageBlockTime.empty().append(state.averageBlockTime) + } if (oldState.newBlock !== state.newBlock) { $blockList.children().last().remove() $blockList.prepend(state.newBlock) diff --git a/apps/explorer_web/lib/explorer_web/channels/block_channel.ex b/apps/explorer_web/lib/explorer_web/channels/block_channel.ex index bb060c52c1..9a6d7d51d7 100644 --- a/apps/explorer_web/lib/explorer_web/channels/block_channel.ex +++ b/apps/explorer_web/lib/explorer_web/channels/block_channel.ex @@ -13,7 +13,7 @@ defmodule ExplorerWeb.BlockChannel do {:ok, %{}, socket} end - def handle_out("new_block", %{block: block}, socket) do + def handle_out("new_block", %{block: block, average_block_time: average_block_time}, socket) do Gettext.put_locale(ExplorerWeb.Gettext, socket.assigns.locale) rendered_block = @@ -33,6 +33,7 @@ defmodule ExplorerWeb.BlockChannel do ) push(socket, "new_block", %{ + average_block_time: Timex.format_duration(average_block_time, :humanized), chain_block_html: rendered_chain_block, block_html: rendered_block, blockNumber: block.number diff --git a/apps/explorer_web/lib/explorer_web/notifier.ex b/apps/explorer_web/lib/explorer_web/notifier.ex index 81ea019d59..7f2f129680 100644 --- a/apps/explorer_web/lib/explorer_web/notifier.ex +++ b/apps/explorer_web/lib/explorer_web/notifier.ex @@ -40,7 +40,11 @@ defmodule ExplorerWeb.Notifier do defp broadcast_block(block) do preloaded_block = Repo.preload(block, [:miner, :transactions]) - Endpoint.broadcast("blocks:new_block", "new_block", %{block: preloaded_block}) + + Endpoint.broadcast("blocks:new_block", "new_block", %{ + block: preloaded_block, + average_block_time: Chain.average_block_time() + }) end defp broadcast_transaction(transaction) do diff --git a/apps/explorer_web/test/explorer_web/features/pages/chain_page.ex b/apps/explorer_web/test/explorer_web/features/pages/chain_page.ex index bd08da570c..dc7673647c 100644 --- a/apps/explorer_web/test/explorer_web/features/pages/chain_page.ex +++ b/apps/explorer_web/test/explorer_web/features/pages/chain_page.ex @@ -11,8 +11,8 @@ defmodule ExplorerWeb.ChainPage do css("[data-selector='address-count']", text: Integer.to_string(count)) end - def average_time(average_time) do - css("[data-selector='average-block-time']", text: Integer.to_string(average_time)) + def average_block_time(average_block_time) do + css("[data-selector='average-block-time']", text: average_block_time) end def block(%Block{number: number}) do diff --git a/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs b/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs index ce0753d66a..167c0e2b16 100644 --- a/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs +++ b/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs @@ -32,18 +32,23 @@ defmodule ExplorerWeb.ViewingChainTest do test "average block time live updates", %{session: session} do time = DateTime.utc_now() for x <- 100..0 do - insert(:block, timestamp: Timex.shift(time, seconds: -5 * x - 100_000), number: x + 100) + insert(:block, timestamp: Timex.shift(time, seconds: -5 * x), number: x + 500) end session |> ChainPage.visit_page() - |> assert_has(ChainPage.average_time(5)) + |> assert_has(ChainPage.average_block_time("5 seconds")) - for x <- 100..0 do - insert(:block, timestamp: Timex.shift(time, seconds: -10 * x), number: x + 300) - end + block = + 100..0 + |> Enum.map(fn(index) -> + insert(:block, timestamp: Timex.shift(time, seconds: -10 * index), number: index + 800) + end) + |> hd() + + Notifier.handle_event({:chain_event, :blocks, [block]}) - assert_has(session, ChainPage.average_time(10)) + assert_has(session, ChainPage.average_block_time("10 seconds")) end test "address count live updates", %{session: session} do From 1e43456b0e1667c3aeb0a8774e90ea99532b8046 Mon Sep 17 00:00:00 2001 From: Stamates Date: Mon, 6 Aug 2018 17:27:42 -0400 Subject: [PATCH 07/10] Wireup live update of address count --- apps/explorer_web/assets/js/pages/chain.js | 16 ++++++- .../explorer_web/channels/address_channel.ex | 48 +++++++++++-------- .../explorer_web/lib/explorer_web/notifier.ex | 2 + 3 files changed, 45 insertions(+), 21 deletions(-) diff --git a/apps/explorer_web/assets/js/pages/chain.js b/apps/explorer_web/assets/js/pages/chain.js index aea629f7de..62c3ebc44e 100644 --- a/apps/explorer_web/assets/js/pages/chain.js +++ b/apps/explorer_web/assets/js/pages/chain.js @@ -10,6 +10,7 @@ import { batchChannel, initRedux } from '../utils' const BATCH_THRESHOLD = 10 export const initialState = { + addressCount: null, averageBlockTime: null, batchCountAccumulator: 0, newBlock: null, @@ -24,6 +25,11 @@ export function reducer (state = initialState, action) { transactionCount: numeral(action.transactionCount).value() }) } + case 'RECEIVED_NEW_ADDRESS_COUNT': { + return Object.assign({}, state, { + addressCount: action.msg.count + }) + } case 'RECEIVED_NEW_BLOCK': { return Object.assign({}, state, { averageBlockTime: action.msg.averageBlockTime, @@ -53,8 +59,12 @@ export function reducer (state = initialState, action) { router.when('', { exactPathMatch: true }).then(({ locale }) => initRedux(reducer, { main (store) { - const blocksChannel = socket.channel(`blocks:new_block`) numeral.locale(locale) + const addressesChannel = socket.channel(`addresses:new_address`) + addressesChannel.join() + addressesChannel.on('count', msg => store.dispatch({ type: 'RECEIVED_NEW_ADDRESS_COUNT', msg: humps.camelizeKeys(msg) })) + + const blocksChannel = socket.channel(`blocks:new_block`) store.dispatch({ type: 'PAGE_LOAD', transactionCount: $('[data-selector="transaction-count"]').text() @@ -69,6 +79,7 @@ router.when('', { exactPathMatch: true }).then(({ locale }) => initRedux(reducer ) }, render (state, oldState) { + const $addressCount = $('[data-selector="address-count"]') const $averageBlockTime = $('[data-selector="average-block-time"]') const $blockList = $('[data-selector="chain-block-list"]') const $channelBatching = $('[data-selector="channel-batching-message"]') @@ -76,6 +87,9 @@ router.when('', { exactPathMatch: true }).then(({ locale }) => initRedux(reducer const $transactionsList = $('[data-selector="transactions-list"]') const $transactionCount = $('[data-selector="transaction-count"]') + if (oldState.addressCount !== state.addressCount) { + $addressCount.empty().append(state.addressCount) + } if (oldState.averageBlockTime !== state.averageBlockTime) { $averageBlockTime.empty().append(state.averageBlockTime) } diff --git a/apps/explorer_web/lib/explorer_web/channels/address_channel.ex b/apps/explorer_web/lib/explorer_web/channels/address_channel.ex index b949f54f6e..8a4806e8a2 100644 --- a/apps/explorer_web/lib/explorer_web/channels/address_channel.ex +++ b/apps/explorer_web/lib/explorer_web/channels/address_channel.ex @@ -7,50 +7,58 @@ defmodule ExplorerWeb.AddressChannel do alias ExplorerWeb.{AddressTransactionView, AddressView} alias Phoenix.View - intercept(["balance_update", "transaction"]) + intercept(["balance_update", "count", "transaction"]) def join("addresses:" <> _address_hash, _params, socket) do {:ok, %{}, socket} end - def handle_out("transaction", %{address: address, transaction: transaction}, socket) do + def handle_out( + "balance_update", + %{address: address, exchange_rate: exchange_rate}, + socket + ) do Gettext.put_locale(ExplorerWeb.Gettext, socket.assigns.locale) rendered = View.render_to_string( - AddressTransactionView, - "_transaction.html", + AddressView, + "_balance_card.html", locale: socket.assigns.locale, address: address, - transaction: transaction + exchange_rate: exchange_rate ) - push(socket, "transaction", %{ - to_address_hash: to_string(transaction.to_address_hash), - from_address_hash: to_string(transaction.from_address_hash), - transaction_html: rendered - }) - + push(socket, "balance", %{balance: rendered}) {:noreply, socket} end - def handle_out( - "balance_update", - %{address: address, exchange_rate: exchange_rate}, - socket - ) do + def handle_out("count", %{count: count}, socket) do + Gettext.put_locale(ExplorerWeb.Gettext, socket.assigns.locale) + + push(socket, "count", %{count: Cldr.Number.to_string!(count, format: "#,###")}) + + {:noreply, socket} + end + + def handle_out("transaction", %{address: address, transaction: transaction}, socket) do Gettext.put_locale(ExplorerWeb.Gettext, socket.assigns.locale) rendered = View.render_to_string( - AddressView, - "_balance_card.html", + AddressTransactionView, + "_transaction.html", locale: socket.assigns.locale, address: address, - exchange_rate: exchange_rate + transaction: transaction ) - push(socket, "balance", %{balance: rendered}) + push(socket, "transaction", %{ + to_address_hash: to_string(transaction.to_address_hash), + from_address_hash: to_string(transaction.from_address_hash), + transaction_html: rendered + }) + {:noreply, socket} end end diff --git a/apps/explorer_web/lib/explorer_web/notifier.ex b/apps/explorer_web/lib/explorer_web/notifier.ex index 7f2f129680..037f014aef 100644 --- a/apps/explorer_web/lib/explorer_web/notifier.ex +++ b/apps/explorer_web/lib/explorer_web/notifier.ex @@ -9,6 +9,8 @@ defmodule ExplorerWeb.Notifier do alias ExplorerWeb.Endpoint def handle_event({:chain_event, :addresses, addresses}) do + Endpoint.broadcast("addresses:new_address", "count", %{count: Chain.address_estimated_count()}) + addresses |> Stream.reject(fn %Address{fetched_balance: fetched_balance} -> is_nil(fetched_balance) end) |> Enum.each(&broadcast_balance/1) From 36949da03b6194bc137f19ecb78df4759e226b2d Mon Sep 17 00:00:00 2001 From: Stamates Date: Mon, 6 Aug 2018 17:31:06 -0400 Subject: [PATCH 08/10] Add FakeAdapter to replace reltuple count query during testing --- apps/explorer_web/config/test.exs | 2 ++ .../lib/explorer_web/controllers/chain_controller.ex | 5 +++-- apps/explorer_web/lib/explorer_web/notifier.ex | 4 +++- .../test/explorer_web/features/viewing_chain_test.exs | 3 +-- apps/explorer_web/test/support/fake_adapter.ex | 8 ++++++++ 5 files changed, 17 insertions(+), 5 deletions(-) create mode 100644 apps/explorer_web/test/support/fake_adapter.ex diff --git a/apps/explorer_web/config/test.exs b/apps/explorer_web/config/test.exs index dc2523f19b..70bf70dcda 100644 --- a/apps/explorer_web/config/test.exs +++ b/apps/explorer_web/config/test.exs @@ -11,3 +11,5 @@ config :explorer_web, ExplorerWeb.Endpoint, # Configure wallaby config :wallaby, screenshot_on_failure: true + +config :explorer_web, :fake_adapter, ExplorerWeb.FakeAdapter diff --git a/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex b/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex index ffdc2bd1c4..51ccb85e30 100644 --- a/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex +++ b/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex @@ -7,9 +7,10 @@ defmodule ExplorerWeb.ChainController do alias Explorer.ExchangeRates.Token alias Explorer.Market + @address_count_module Application.get_env(:explorer_web, :fake_adapter) || Chain + def show(conn, _params) do transaction_estimated_count = Chain.transaction_estimated_count() - address_estimated_count = Chain.address_estimated_count() transactions = Chain.recent_collated_transactions( @@ -29,7 +30,7 @@ defmodule ExplorerWeb.ChainController do render( conn, "show.html", - address_estimated_count: address_estimated_count, + address_estimated_count: @address_count_module.address_estimated_count(), average_block_time: Chain.average_block_time(), blocks: blocks, exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(), diff --git a/apps/explorer_web/lib/explorer_web/notifier.ex b/apps/explorer_web/lib/explorer_web/notifier.ex index 037f014aef..1bb0164619 100644 --- a/apps/explorer_web/lib/explorer_web/notifier.ex +++ b/apps/explorer_web/lib/explorer_web/notifier.ex @@ -8,8 +8,10 @@ defmodule ExplorerWeb.Notifier do alias Explorer.ExchangeRates.Token alias ExplorerWeb.Endpoint + @address_count_module Application.get_env(:explorer_web, :fake_adapter) || Chain + def handle_event({:chain_event, :addresses, addresses}) do - Endpoint.broadcast("addresses:new_address", "count", %{count: Chain.address_estimated_count()}) + Endpoint.broadcast("addresses:new_address", "count", %{count: @address_count_module.address_estimated_count()}) addresses |> Stream.reject(fn %Address{fetched_balance: fetched_balance} -> is_nil(fetched_balance) end) diff --git a/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs b/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs index 167c0e2b16..ae4abe36d9 100644 --- a/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs +++ b/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs @@ -3,7 +3,6 @@ defmodule ExplorerWeb.ViewingChainTest do use ExplorerWeb.FeatureCase, async: true - alias Explorer.Chain alias ExplorerWeb.{AddressPage, BlockPage, ChainPage, Notifier, TransactionPage} setup do @@ -52,7 +51,7 @@ defmodule ExplorerWeb.ViewingChainTest do end test "address count live updates", %{session: session} do - count = Chain.address_estimated_count() + count = ExplorerWeb.FakeAdapter.address_estimated_count() session |> ChainPage.visit_page() diff --git a/apps/explorer_web/test/support/fake_adapter.ex b/apps/explorer_web/test/support/fake_adapter.ex new file mode 100644 index 0000000000..b9d8ff0397 --- /dev/null +++ b/apps/explorer_web/test/support/fake_adapter.ex @@ -0,0 +1,8 @@ +defmodule ExplorerWeb.FakeAdapter do + alias Explorer.Chain.Address + alias Explorer.Repo + + def address_estimated_count() do + Repo.aggregate(Address, :count, :hash) + end +end From ac166adac926c5a4e1605c2f363911b6c6eca76e Mon Sep 17 00:00:00 2001 From: Stamates Date: Tue, 7 Aug 2018 10:52:06 -0400 Subject: [PATCH 09/10] Remove unused Chain.address_count function and format/credo appeasement --- apps/explorer/lib/explorer/chain.ex | 24 +++---------------- apps/explorer_web/assets/js/pages/chain.js | 4 ++-- .../explorer_web/channels/address_channel.ex | 2 +- .../controllers/chain_controller.ex | 3 +-- .../explorer_web/lib/explorer_web/notifier.ex | 2 +- .../features/viewing_chain_test.exs | 3 ++- .../explorer_web/test/support/fake_adapter.ex | 2 +- 7 files changed, 11 insertions(+), 29 deletions(-) diff --git a/apps/explorer/lib/explorer/chain.ex b/apps/explorer/lib/explorer/chain.ex index 8d94dee0ff..12da6c602e 100644 --- a/apps/explorer/lib/explorer/chain.ex +++ b/apps/explorer/lib/explorer/chain.ex @@ -69,7 +69,7 @@ defmodule Explorer.Chain do Estimated count of addresses """ - @spec address_estimated_count() :: non_neg_integer() + @spec address_estimated_count :: non_neg_integer() def address_estimated_count do %Postgrex.Result{rows: [[rows]]} = SQL.query!(Repo, "SELECT reltuples::BIGINT AS estimate FROM pg_class WHERE relname='addresses'") @@ -188,12 +188,11 @@ defmodule Explorer.Chain do |> Repo.all() end - @doc """ The average time it took to mine/validate the last <= 100 `t:Explorer.Chain.Block.t/0` """ - @spec average_block_time() :: non_neg_integer() - def average_block_time() do + @spec average_block_time :: %Timex.Duration{} + def average_block_time do {:ok, %Postgrex.Result{rows: [[rows]]}} = SQL.query( Repo, @@ -652,23 +651,6 @@ defmodule Explorer.Chain do Import.all(options) end - @doc """ - The number of `t:Explorer.Chain.Address.t/0`. - - iex> insert_list(2, :address) - iex> Explorer.Chain.address_count() - 2 - - When there are no `t:Explorer.Chain.Address.t/0`, the count is `0`. - - iex> Explorer.Chain.address_count() - 0 - - """ - def address_count do - Repo.aggregate(Address, :count, :hash) - end - @doc """ The number of `t:Explorer.Chain.InternalTransaction.t/0`. diff --git a/apps/explorer_web/assets/js/pages/chain.js b/apps/explorer_web/assets/js/pages/chain.js index 62c3ebc44e..364f1bfe6a 100644 --- a/apps/explorer_web/assets/js/pages/chain.js +++ b/apps/explorer_web/assets/js/pages/chain.js @@ -88,10 +88,10 @@ router.when('', { exactPathMatch: true }).then(({ locale }) => initRedux(reducer const $transactionCount = $('[data-selector="transaction-count"]') if (oldState.addressCount !== state.addressCount) { - $addressCount.empty().append(state.addressCount) + $addressCount.empty().append(state.addressCount) } if (oldState.averageBlockTime !== state.averageBlockTime) { - $averageBlockTime.empty().append(state.averageBlockTime) + $averageBlockTime.empty().append(state.averageBlockTime) } if (oldState.newBlock !== state.newBlock) { $blockList.children().last().remove() diff --git a/apps/explorer_web/lib/explorer_web/channels/address_channel.ex b/apps/explorer_web/lib/explorer_web/channels/address_channel.ex index 8a4806e8a2..1c24c8d706 100644 --- a/apps/explorer_web/lib/explorer_web/channels/address_channel.ex +++ b/apps/explorer_web/lib/explorer_web/channels/address_channel.ex @@ -40,7 +40,7 @@ defmodule ExplorerWeb.AddressChannel do {:noreply, socket} end - + def handle_out("transaction", %{address: address, transaction: transaction}, socket) do Gettext.put_locale(ExplorerWeb.Gettext, socket.assigns.locale) diff --git a/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex b/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex index 51ccb85e30..7dc10c9cbd 100644 --- a/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex +++ b/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex @@ -1,8 +1,7 @@ defmodule ExplorerWeb.ChainController do use ExplorerWeb, :controller - alias Explorer.{PagingOptions, Repo} - alias Explorer.Chain + alias Explorer.{Chain, PagingOptions, Repo} alias Explorer.Chain.{Address, Block, Transaction} alias Explorer.ExchangeRates.Token alias Explorer.Market diff --git a/apps/explorer_web/lib/explorer_web/notifier.ex b/apps/explorer_web/lib/explorer_web/notifier.ex index 1bb0164619..9d122dc4f6 100644 --- a/apps/explorer_web/lib/explorer_web/notifier.ex +++ b/apps/explorer_web/lib/explorer_web/notifier.ex @@ -48,7 +48,7 @@ defmodule ExplorerWeb.Notifier do Endpoint.broadcast("blocks:new_block", "new_block", %{ block: preloaded_block, average_block_time: Chain.average_block_time() - }) + }) end defp broadcast_transaction(transaction) do diff --git a/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs b/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs index ae4abe36d9..fbafc9c0c6 100644 --- a/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs +++ b/apps/explorer_web/test/explorer_web/features/viewing_chain_test.exs @@ -30,6 +30,7 @@ defmodule ExplorerWeb.ViewingChainTest do describe "statistics" do test "average block time live updates", %{session: session} do time = DateTime.utc_now() + for x <- 100..0 do insert(:block, timestamp: Timex.shift(time, seconds: -5 * x), number: x + 500) end @@ -40,7 +41,7 @@ defmodule ExplorerWeb.ViewingChainTest do block = 100..0 - |> Enum.map(fn(index) -> + |> Enum.map(fn index -> insert(:block, timestamp: Timex.shift(time, seconds: -10 * index), number: index + 800) end) |> hd() diff --git a/apps/explorer_web/test/support/fake_adapter.ex b/apps/explorer_web/test/support/fake_adapter.ex index b9d8ff0397..b92b353557 100644 --- a/apps/explorer_web/test/support/fake_adapter.ex +++ b/apps/explorer_web/test/support/fake_adapter.ex @@ -2,7 +2,7 @@ defmodule ExplorerWeb.FakeAdapter do alias Explorer.Chain.Address alias Explorer.Repo - def address_estimated_count() do + def address_estimated_count do Repo.aggregate(Address, :count, :hash) end end From aef79428677ad28f953a53b48bf8491abcbba85f Mon Sep 17 00:00:00 2001 From: Stamates Date: Tue, 7 Aug 2018 13:10:08 -0400 Subject: [PATCH 10/10] Move FakeAdapter switch out of module attribute --- .../explorer_web/controllers/chain_controller.ex | 16 ++++++++-------- apps/explorer_web/lib/explorer_web/notifier.ex | 5 ++--- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex b/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex index 7dc10c9cbd..b8399fa651 100644 --- a/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex +++ b/apps/explorer_web/lib/explorer_web/controllers/chain_controller.ex @@ -6,9 +6,14 @@ defmodule ExplorerWeb.ChainController do alias Explorer.ExchangeRates.Token alias Explorer.Market - @address_count_module Application.get_env(:explorer_web, :fake_adapter) || Chain - def show(conn, _params) do + address_count_module = Application.get_env(:explorer_web, :fake_adapter) || Chain + + blocks = + [paging_options: %PagingOptions{page_size: 4}] + |> Chain.list_blocks() + |> Repo.preload([:miner, :transactions]) + transaction_estimated_count = Chain.transaction_estimated_count() transactions = @@ -21,15 +26,10 @@ defmodule ExplorerWeb.ChainController do paging_options: %PagingOptions{page_size: 5} ) - blocks = - [paging_options: %PagingOptions{page_size: 4}] - |> Chain.list_blocks() - |> Repo.preload([:miner, :transactions]) - render( conn, "show.html", - address_estimated_count: @address_count_module.address_estimated_count(), + address_estimated_count: address_count_module.address_estimated_count(), average_block_time: Chain.average_block_time(), blocks: blocks, exchange_rate: Market.get_exchange_rate(Explorer.coin()) || Token.null(), diff --git a/apps/explorer_web/lib/explorer_web/notifier.ex b/apps/explorer_web/lib/explorer_web/notifier.ex index 9d122dc4f6..717c1d2a54 100644 --- a/apps/explorer_web/lib/explorer_web/notifier.ex +++ b/apps/explorer_web/lib/explorer_web/notifier.ex @@ -8,10 +8,9 @@ defmodule ExplorerWeb.Notifier do alias Explorer.ExchangeRates.Token alias ExplorerWeb.Endpoint - @address_count_module Application.get_env(:explorer_web, :fake_adapter) || Chain - def handle_event({:chain_event, :addresses, addresses}) do - Endpoint.broadcast("addresses:new_address", "count", %{count: @address_count_module.address_estimated_count()}) + address_count_module = Application.get_env(:explorer_web, :fake_adapter) || Chain + Endpoint.broadcast("addresses:new_address", "count", %{count: address_count_module.address_estimated_count()}) addresses |> Stream.reject(fn %Address{fetched_balance: fetched_balance} -> is_nil(fetched_balance) end)