defmodule Mongo.Error do defexception [:message, :code, :host, type: :mongo] @type t :: %__MODULE__{ message: String.t(), code: number, host: String.t() } def message(e) do code = if e.code, do: " #{e.code}" "#{e.message}#{code}" end def exception(tag: :tcp, action: action, reason: reason, host: host) do formatted_reason = :inet.format_error(reason) %__MODULE__{ message: "#{host} tcp #{action}: #{formatted_reason} - #{inspect(reason)}", type: :network } end def exception(tag: :ssl, action: action, reason: reason, host: host) do formatted_reason = :ssl.format_error(reason) %__MODULE__{ message: "#{host} ssl #{action}: #{formatted_reason} - #{inspect(reason)}", type: :network } end def exception(message: message, code: code) do %__MODULE__{message: message, code: code} end def exception(message: message) do %__MODULE__{message: message} end @retryable_error_codes [ # HostUnreachable 6, # HostNotFound 7, # NetworkTimeout 89, # ShutdownInProgress 91, # PrimarySteppedDown 189, # SocketException 9001, # NotMaster 10107, # InterruptedAtShutdown 11600, # InterruptedDueToReplStateChange 11602, # NotMasterNoSlaveOk 13435, # NotMasterOrSecondary 13436 ] def retryable(%__MODULE__{code: code}) when code in @retryable_error_codes, do: true def retryable(%__MODULE__{message: message}) do message =~ ~r/not master|node is recovering/ end end defmodule Mongo.WriteError do defexception [:n, :ok, :write_errors] @type t :: %__MODULE__{ n: integer(), ok: integer(), write_errors: [map()] } def message(e) do "n: #{e.n}, ok: #{e.ok}, write_errors: #{inspect(e.write_errors)}" end end