Current section

Files

Jump to
mongodb_driver lib mongo server_description.ex
Raw

lib/mongo/server_description.ex

defmodule Mongo.ServerDescription do
@moduledoc false
# see https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-discovery-and-monitoring.rst#serverdescription
@type type :: :standalone | :mongos | :possible_primary | :rs_primary |
:rs_secondary | :rs_arbiter | :rs_other | :rs_ghost | :unknown
@type t :: %{
address: String.t | nil,
error: String.t | nil,
round_trip_time: non_neg_integer | nil,
last_write_date: DateTime.t,
op_time: BSON.ObjectId.t | nil,
type: type,
min_wire_version: non_neg_integer,
max_wire_version: non_neg_integer,
me: String.t | nil,
hosts: [String.t],
passives: [String.t],
arbiters: [String.t],
tag_set: %{String.t => String.t},
set_name: String.t | nil,
set_version: non_neg_integer | nil,
election_id: BSON.ObjectId.t | nil,
primary: String.t | nil,
last_update_time: non_neg_integer
}
def defaults(map \\ %{}) do
Map.merge(%{
address: "localhost:27017",
error: nil,
round_trip_time: nil,
last_write_date: nil,
op_time: nil,
type: :unknown,
min_wire_version: 0,
max_wire_version: 0,
me: nil,
hosts: [],
passives: [],
arbiters: [],
tag_set: %{},
set_name: nil,
set_version: nil,
election_id: nil,
primary: nil,
last_update_time: 0
}, map)
end
def from_is_master_error(last_server_description, error) do
defaults(%{
address: last_server_description.address,
error: error
})
end
# see https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-discovery-and-monitoring.rst#parsing-an-ismaster-response
def from_is_master(last_description, rtt, finish_time, is_master_reply) do
last_rtt = last_description.round_trip_time || rtt
defaults(%{
address: last_description.address,
round_trip_time: round(0.2 * rtt + 0.8 * last_rtt),
type: determine_server_type(is_master_reply),
last_write_date: get_in(is_master_reply,
["lastWrite", "lastWriteDate"]),
op_time: get_in(is_master_reply, ["lastWrite", "opTime"]),
last_update_time: finish_time,
min_wire_version: is_master_reply["minWireVersion"] || 0,
max_wire_version: is_master_reply["maxWireVersion"] || 0,
me: is_master_reply["me"],
hosts: (is_master_reply["hosts"] || []) |> Enum.map(&String.downcase/1),
passives: (is_master_reply["passives"] || [])
|> Enum.map(&String.downcase/1),
arbiters: (is_master_reply["arbiters"] || [])
|> Enum.map(&String.downcase/1),
tag_set: is_master_reply["tags"] || %{},
set_name: is_master_reply["setName"],
set_version: is_master_reply["setVersion"],
election_id: is_master_reply["electionId"],
primary: is_master_reply["primary"]
})
end
# see https://github.com/mongodb/specifications/blob/master/source/server-discovery-and-monitoring/server-discovery-and-monitoring.rst#type
defp determine_server_type(%{"ok" => n}) when n != 1, do: :unknown
defp determine_server_type(%{"msg" => "isdbgrid"}), do: :mongos
defp determine_server_type(%{"isreplicaset" => true}), do: :rs_ghost
defp determine_server_type(%{"setName" => set_name} = is_master_reply) when set_name != nil do
case is_master_reply do
%{"ismaster" => true} ->
:rs_primary
%{"secondary" => true} ->
:rs_secondary
%{"arbiterOnly" => true} ->
:rs_arbiter
_ ->
:rs_other
end
end
defp determine_server_type(_), do: :standalone
end