From 5ad64e9dd3553082cc70bb0fbe207527d8296bff Mon Sep 17 00:00:00 2001 From: d-velev Date: Wed, 25 Oct 2017 12:27:59 +0300 Subject: [PATCH 1/3] [GH-#77] Peers.Worker module modified, check_peers() is called every minute --- apps/aecore/lib/aecore.ex | 2 +- apps/aecore/lib/aecore/peers/scheduler.ex | 24 +++++++++ apps/aecore/lib/aecore/peers/worker.ex | 50 +++++++++++-------- .../lib/aecore/peers/worker/supervisor.ex | 5 +- .../utils/blockchain/block_validation.ex | 1 - apps/aecore/test/aecore_peers_test.exs | 2 +- 6 files changed, 57 insertions(+), 27 deletions(-) create mode 100644 apps/aecore/lib/aecore/peers/scheduler.ex diff --git a/apps/aecore/lib/aecore.ex b/apps/aecore/lib/aecore.ex index 83a46ed6..c1465e21 100644 --- a/apps/aecore/lib/aecore.ex +++ b/apps/aecore/lib/aecore.ex @@ -9,7 +9,7 @@ defmodule Aecore do supervisor(Aecore.Chain.Worker.Supervisor, []), supervisor(Aecore.Miner.Worker.Supervisor, []), supervisor(Aecore.Txs.Pool.Worker.Supervisor, []), - supervisor(Aecore.Peers.Worker, []) + supervisor(Aecore.Peers.Worker.Supervisor, []) ] Supervisor.start_link(children, strategy: :one_for_one) diff --git a/apps/aecore/lib/aecore/peers/scheduler.ex b/apps/aecore/lib/aecore/peers/scheduler.ex new file mode 100644 index 00000000..93b482b6 --- /dev/null +++ b/apps/aecore/lib/aecore/peers/scheduler.ex @@ -0,0 +1,24 @@ +defmodule Aecore.Peers.Scheduler do + use GenServer + + alias Aecore.Peers.Worker, as: Peers + + def start_link do + GenServer.start_link(__MODULE__, %{}) + end + + def init(state) do + schedule_work() + {:ok, state} + end + + def handle_info(:work, state) do + Peers.check_peers() + schedule_work() + {:noreply, state} + end + + defp schedule_work() do + Process.send_after(self(), :work, 60_000) + end +end diff --git a/apps/aecore/lib/aecore/peers/worker.ex b/apps/aecore/lib/aecore/peers/worker.ex index ab933dcd..2af46480 100644 --- a/apps/aecore/lib/aecore/peers/worker.ex +++ b/apps/aecore/lib/aecore/peers/worker.ex @@ -10,7 +10,7 @@ defmodule Aecore.Peers.Worker do alias Aecore.Utils.Blockchain.BlockValidation def start_link do - GenServer.start_link(__MODULE__, [], name: __MODULE__) + GenServer.start_link(__MODULE__, %{}, name: __MODULE__) end def init(initial_peers) do @@ -32,7 +32,7 @@ defmodule Aecore.Peers.Worker do GenServer.call(__MODULE__, :check_peers) end - @spec all_peers() :: list() + @spec all_peers() :: map() def all_peers() do GenServer.call(__MODULE__, :all_peers) end @@ -45,36 +45,42 @@ defmodule Aecore.Peers.Worker do end def handle_call({:add_peer,uri}, _from, peers) do - if(!Enum.member?(peers,uri)) do - case(Client.get_info(uri)) do - {:ok, info} -> - if(Map.get(info,:genesis_block_hash) == genesis_block_header_hash()) do - {:reply, :ok, [uri | peers]} - else - {:reply, {:error, "Genesis header hash not valid"}, peers} - end - :error -> - {:reply, :error, peers} - end - else - {:reply, {:error, "Peer already in list"}, peers} + case(Client.get_info(uri)) do + {:ok, info} -> + if(Map.get(info,:genesis_block_hash) == genesis_block_header_hash()) do + updated_peers = Map.put(peers, uri, info.current_block_hash) + {:reply, :ok, updated_peers} + else + {:reply, {:error, "Genesis header hash not valid"}, peers} + end + :error -> + {:reply, :error, peers} end end def handle_call({:remove_peer, uri}, _from, peers) do - if(Enum.member?(peers,uri)) do - {:reply, :ok, List.delete(peers, uri)} + if(Map.has_key?(peers, uri)) do + {:reply, :ok, Map.delete(peers, uri)} else {:reply, {:error, "Peer not found"}, peers} end end def handle_call(:check_peers, _from, peers) do - updated_peers = Enum.filter(peers, fn(peer) -> - {status, info} = Client.get_info(peer) - :ok == status && - Map.get(info, :genesis_block_hash) == genesis_block_header_hash() - end) + filtered_peers = :maps.filter(fn(peer, _) -> + {status, info} = Client.get_info(peer) + :ok == status && + Map.get(info, :genesis_block_hash) == genesis_block_header_hash() + end, peers) + updated_peers = + for {peer, current_block_hash} <- filtered_peers, into: %{} do + {_, info} = Client.get_info(peer) + if(info.current_block_hash != current_block_hash) do + {peer, info.current_block_hash} + else + {peer, current_block_hash} + end + end {:reply, :ok, updated_peers} end diff --git a/apps/aecore/lib/aecore/peers/worker/supervisor.ex b/apps/aecore/lib/aecore/peers/worker/supervisor.ex index 3991db1b..3faa1178 100644 --- a/apps/aecore/lib/aecore/peers/worker/supervisor.ex +++ b/apps/aecore/lib/aecore/peers/worker/supervisor.ex @@ -1,4 +1,4 @@ -defmodule Aecore.Peers.Supervisor do +defmodule Aecore.Peers.Worker.Supervisor do use Supervisor def start_link() do @@ -7,7 +7,8 @@ defmodule Aecore.Peers.Supervisor do def init(:ok) do children = [ - worker(Aecore.Peers.Worker, []) + worker(Aecore.Peers.Worker, []), + worker(Aecore.Peers.Scheduler, []) ] supervise(children, strategy: :one_for_one) diff --git a/apps/aecore/lib/aecore/utils/blockchain/block_validation.ex b/apps/aecore/lib/aecore/utils/blockchain/block_validation.ex index 2687e1f7..de2a3c06 100644 --- a/apps/aecore/lib/aecore/utils/blockchain/block_validation.ex +++ b/apps/aecore/lib/aecore/utils/blockchain/block_validation.ex @@ -7,7 +7,6 @@ defmodule Aecore.Utils.Blockchain.BlockValidation do alias Aecore.Structures.Header alias Aecore.Structures.SignedTx alias Aecore.Chain.ChainState - alias Aecore.Chain.Worker, as: Chain @spec validate_block!(Block.block(), Block.block(), map()) :: {:error, term()} | :ok def validate_block!(new_block, previous_block, chain_state) do diff --git a/apps/aecore/test/aecore_peers_test.exs b/apps/aecore/test/aecore_peers_test.exs index 548e426d..cf7b41e2 100644 --- a/apps/aecore/test/aecore_peers_test.exs +++ b/apps/aecore/test/aecore_peers_test.exs @@ -11,7 +11,7 @@ defmodule AecorePeersTest do test "add peer, get all peers, check peers and remove the peer" do assert :ok = Peers.add_peer("localhost:4000") - assert {:error, "Peer already in list"} = Peers.add_peer("localhost:4000") + Peers.add_peer("localhost:4000") assert Enum.count(Peers.all_peers) == 1 assert :ok = Peers.check_peers assert :ok = Peers.remove_peer("localhost:4000") From 179a87dc10febbf49d697d268e1c44e1691dcff6 Mon Sep 17 00:00:00 2001 From: d-velev Date: Wed, 25 Oct 2017 14:33:19 +0300 Subject: [PATCH 2/3] [GH-#77] Time between check_peers() calls is now a module attribute of the Scheduler module --- apps/aecore/lib/aecore/peers/scheduler.ex | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/aecore/lib/aecore/peers/scheduler.ex b/apps/aecore/lib/aecore/peers/scheduler.ex index 93b482b6..34a2d108 100644 --- a/apps/aecore/lib/aecore/peers/scheduler.ex +++ b/apps/aecore/lib/aecore/peers/scheduler.ex @@ -3,6 +3,8 @@ defmodule Aecore.Peers.Scheduler do alias Aecore.Peers.Worker, as: Peers + @check_time 60_000 + def start_link do GenServer.start_link(__MODULE__, %{}) end @@ -19,6 +21,6 @@ defmodule Aecore.Peers.Scheduler do end defp schedule_work() do - Process.send_after(self(), :work, 60_000) + Process.send_after(self(), :work, @check_time) end end From ea6a8a70fcccc581d0f2fa514fe2b838010bb164 Mon Sep 17 00:00:00 2001 From: d-velev Date: Wed, 25 Oct 2017 15:05:24 +0300 Subject: [PATCH 3/3] [GH-#77] Map.get() is no longer used in the Peers.Worker module, doc for the check_peers() function --- apps/aecore/lib/aecore/peers/worker.ex | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/aecore/lib/aecore/peers/worker.ex b/apps/aecore/lib/aecore/peers/worker.ex index 2af46480..d09c5bdb 100644 --- a/apps/aecore/lib/aecore/peers/worker.ex +++ b/apps/aecore/lib/aecore/peers/worker.ex @@ -47,7 +47,7 @@ defmodule Aecore.Peers.Worker do def handle_call({:add_peer,uri}, _from, peers) do case(Client.get_info(uri)) do {:ok, info} -> - if(Map.get(info,:genesis_block_hash) == genesis_block_header_hash()) do + if(info.genesis_block_hash == genesis_block_header_hash()) do updated_peers = Map.put(peers, uri, info.current_block_hash) {:reply, :ok, updated_peers} else @@ -66,11 +66,16 @@ defmodule Aecore.Peers.Worker do end end + @doc """ + Filters the peers map by checking if the response status from a GET /info + request is :ok and if the genesis block hash is the same as the one + in the current node. After that the current block hash for every peer + is updated if the one in the latest GET /info request is different. + """ def handle_call(:check_peers, _from, peers) do filtered_peers = :maps.filter(fn(peer, _) -> {status, info} = Client.get_info(peer) - :ok == status && - Map.get(info, :genesis_block_hash) == genesis_block_header_hash() + :ok == status && info.genesis_block_hash == genesis_block_header_hash() end, peers) updated_peers = for {peer, current_block_hash} <- filtered_peers, into: %{} do