Current section

Files

Jump to
hyperview lib hyparview messages shuffle_reply.ex
Raw

lib/hyparview/messages/shuffle_reply.ex

defmodule Hyparview.Messages.ShuffleReply do
@moduledoc """
SHUFFLEREPLY message abstraction module
"""
alias __MODULE__
alias Hyparview.Messages.Shuffle
alias Hyparview.View
alias Hyparview.PeerManager
defstruct sender: Node.self(),
nodes: MapSet.new()
@type t :: %ShuffleReply{
sender: Node.t(),
nodes: MapSet.t(Node.t())
}
@doc """
A ShuffleReply message that includes a number of nodes selected at random from
q’s passive view equal to the number of nodes received in the Shuffle request.
shuffle_reply = ShuffleReply.new(view: state.view, shuffle: Shuffle.new())
"""
@spec new(view: View.t(), shuffle: Shuffle.t()) :: t()
def new(options \\ []),
do: %ShuffleReply{nodes: compose_reply_nodes(options), sender: Node.self()}
@doc """
Send a SHUFFLEREPLY message to the SHUFFLE sender
:ok = ShuffleReply.send!(shuffle_reply, :"node1@127.0.0.1")
"""
@spec send!(ShuffleReply.t(), Node.t()) :: :ok
def send!(%ShuffleReply{} = shuffle_reply, shuffle_sender),
do: _ = PeerManager.send_message(shuffle_sender, shuffle_reply)
@spec handle(t(), View.t()) :: View.t()
def handle(%ShuffleReply{nodes: nodes}, view), do: View.trim_and_add_to_passive(view, nodes)
# private functions
@spec compose_reply_nodes(view: View.t(), shuffle: Shuffle.t()) :: MapSet.t(Node.t())
defp compose_reply_nodes(options) do
view = options[:view] || throw(:not_view_given)
shuffle = options[:shuffle] || Shuffle.new()
shuffle_nodes_size = MapSet.size(shuffle.nodes)
view.passive
|> Enum.take_random(shuffle_nodes_size)
|> MapSet.new()
end
end