Packages
cluster_load_balancer
1.0.0
Load balance resources in your Elixir cluster (like WebSockets after a rolling deploy)
Current section
Files
Jump to
Current section
Files
lib/cluster_load_balancer/collection.ex
defmodule ClusterLoadBalancer.Collection do
@moduledoc false
defmodule Result do
@moduledoc false
@enforce_keys [:tick, :count, :rand]
defstruct @enforce_keys
end
@enforce_keys [:expected_results_count, :self_result, :tick, :topic]
defstruct @enforce_keys ++ [collected: []]
def init(topic, tick, node_count, self_result = %Result{}) do
%__MODULE__{expected_results_count: node_count, self_result: self_result, tick: tick, topic: topic}
end
def init_result(tick, count, rand) do
%Result{tick: tick, count: count, rand: rand}
end
def add_result(state = %__MODULE__{collected: collected, tick: state_tick}, result = %Result{tick: tick}) when state_tick == tick do
new_collected = [result | collected]
%{state | collected: new_collected}
end
def add_result(state, _), do: state
def finalized?(%{expected_results_count: expected_count, collected: collected}) do
length(collected) == expected_count
end
def participant_count(%{expected_results_count: count}), do: count + 1
def self_has_highest_count?(%{self_result: self, collected: collected}) do
Enum.all?(collected, fn other ->
self.count > other.count || (self.count == other.count && self.rand > other.rand)
end)
end
def self_count(%{self_result: self}) do
self.count
end
def average_count(%{self_result: self, collected: collected}) do
collected
|> Enum.map(& &1.count)
|> Enum.sum()
|> Kernel.+(self.count)
|> Kernel./(length(collected) + 1)
end
end