• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / supavisor / 19370957114

14 Nov 2025 04:30PM UTC coverage: 62.682% (+1.4%) from 61.246%
19370957114

Pull #744

github

web-flow
Merge fd252a012 into 0224a24c8
Pull Request #744: fix(defrag): improve statems, caching, logs, circuit breaking

592 of 785 new or added lines in 22 files covered. (75.41%)

18 existing lines in 5 files now uncovered.

1809 of 2886 relevant lines covered (62.68%)

4508.83 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

41.3
/lib/supavisor/handler_helpers.ex
1
defmodule Supavisor.HandlerHelpers do
2
  @moduledoc false
3

4
  require Supavisor.Protocol.Server, as: Server
5

6
  @spec sock_send(Supavisor.sock(), iodata()) :: :ok | {:error, term()}
7
  def sock_send({mod, sock}, data) do
8
    mod.send(sock, data)
38,956✔
9
  end
10

11
  @spec sock_close(Supavisor.sock() | nil | {any(), nil}) :: :ok | {:error, term()}
12
  def sock_close(nil), do: :ok
×
13
  def sock_close({_, nil}), do: :ok
×
14

15
  def sock_close({mod, sock}), do: mod.close(sock)
251✔
16

17
  @spec setopts(Supavisor.sock(), term()) :: :ok | {:error, term()}
18
  def setopts({mod, sock}, opts) do
19
    mod = if mod == :gen_tcp, do: :inet, else: mod
6,426✔
20
    mod.setopts(sock, opts)
6,426✔
21
  end
22

23
  @spec active_once(Supavisor.sock()) :: :ok | {:error, term}
UNCOV
24
  def active_once(sock), do: setopts(sock, active: :once)
×
25

26
  @spec activate(Supavisor.sock()) :: :ok | {:error, term}
27
  def activate(sock), do: setopts(sock, active: true)
6,305✔
28

29
  @spec try_ssl_handshake(Supavisor.tcp_sock(), boolean) ::
30
          {:ok, Supavisor.sock()} | {:error, term()}
31
  def try_ssl_handshake(sock, true) do
32
    case sock_send(sock, Server.ssl_request()) do
×
33
      :ok -> ssl_recv(sock)
×
34
      error -> error
×
35
    end
36
  end
37

38
  def try_ssl_handshake(sock, false), do: {:ok, sock}
×
39

40
  @spec ssl_recv(Supavisor.tcp_sock()) :: {:ok, Supavisor.ssl_sock()} | {:error, term}
41
  def ssl_recv({:gen_tcp, sock} = s) do
42
    case :gen_tcp.recv(sock, 1, 15_000) do
×
43
      {:ok, <<?S>>} -> ssl_connect(s)
×
44
      {:ok, <<?N>>} -> {:ok, s}
×
45
      {:error, _} = error -> error
×
46
    end
47
  end
48

49
  @spec ssl_connect(Supavisor.tcp_sock(), pos_integer) ::
50
          {:ok, Supavisor.ssl_sock()} | {:error, term}
51
  def ssl_connect({:gen_tcp, sock}, timeout \\ 5000) do
52
    opts = [verify: :verify_none]
×
53

54
    case :ssl.connect(sock, opts, timeout) do
×
55
      {:ok, ssl_sock} -> {:ok, {:ssl, ssl_sock}}
×
56
      {:error, reason} -> {:error, reason}
×
57
    end
58
  end
59

60
  @spec send_error(Supavisor.sock(), String.t(), String.t()) :: :ok | {:error, term()}
61
  def send_error(sock, code, message) do
UNCOV
62
    data = Server.error_message(code, message)
×
UNCOV
63
    sock_send(sock, data)
×
64
  end
65

66
  @spec try_get_sni(Supavisor.sock()) :: String.t() | nil
67
  def try_get_sni({:ssl, sock}) do
68
    case :ssl.connection_information(sock, [:sni_hostname]) do
×
69
      {:ok, [sni_hostname: sni]} -> List.to_string(sni)
×
70
      _ -> nil
×
71
    end
72
  end
73

74
  def try_get_sni(_), do: nil
615✔
75

76
  @spec reset_active_count(%{sock: Supavisor.sock()}) :: 0
77
  def reset_active_count(%{sock: sock}) do
NEW
78
    activate(sock)
×
79
    0
80
  end
81

82
  @spec parse_user_info(map) ::
83
          {:cluster | :single, {String.t() | nil, String.t(), String.t() | nil}}
84
  def parse_user_info(%{"user" => user, "options" => %{"reference" => ref}} = payload) do
1✔
85
    # TODO: parse ref for cluster
86
    {:single, {user, ref, payload["database"]}}
87
  end
88

89
  def parse_user_info(%{"user" => user} = payload) do
90
    db_name = payload["database"]
622✔
91

92
    case :binary.split(user, ".cluster.") do
622✔
93
      [user] ->
94
        case :binary.matches(user, ".") do
621✔
95
          [] ->
3✔
96
            {:single, {user, nil, db_name}}
97

98
          matches ->
99
            {pos, 1} = List.last(matches)
618✔
100
            <<name::size(pos)-binary, ?., external_id::binary>> = user
618✔
101
            {:single, {name, external_id, db_name}}
102
        end
103

104
      [user, tenant] ->
1✔
105
        {:cluster, {user, tenant, db_name}}
106
    end
107
  end
108

109
  @doc """
110
  Takes an allow list of CIDR ranges and filtres them for ranges which contain the address
111
  to test.
112

113
  If the IP address of the socket is not found an empty list is returned.
114

115
  ## Examples
116

117
    iex> Supavisor.HandlerHelpers.filter_cidrs(["0.0.0.0/0", "::/0"], {127, 0, 0, 1})
118
    ["0.0.0.0/0"]
119

120
    iex> Supavisor.HandlerHelpers.filter_cidrs(["71.209.249.38/32"], {71, 209, 249, 39})
121
    []
122

123
    iex> Supavisor.HandlerHelpers.filter_cidrs(["0.0.0.0/0", "::/0"], {8193, 3512, 34211, 0, 0, 35374, 880, 29492})
124
    ["::/0"]
125

126
    iex> Supavisor.HandlerHelpers.filter_cidrs(["0.0.0.0/0", "::/0"], :error)
127
    []
128

129
  """
130

131
  @spec filter_cidrs(list(), :inet.ip_address() | any()) :: list()
132
  def filter_cidrs(allow_list, addr) when is_list(allow_list) and is_tuple(addr) do
133
    for range <- allow_list,
617✔
134
        range |> InetCidr.parse_cidr!() |> InetCidr.contains?(addr) do
135
      range
136
    end
137
  end
138

139
  def filter_cidrs(allow_list, _addr) when is_list(allow_list) do
1✔
140
    []
141
  end
142

143
  @spec addr_from_sock(Supavisor.sock()) :: {:ok, :inet.ip_address()} | :error
144
  def addr_from_sock({:gen_tcp, port}) do
145
    case :inet.peername(port) do
615✔
146
      {:ok, {:local, _}} ->
×
147
        :error
148

149
      {:ok, {:undefined, _}} ->
×
150
        :error
151

152
      {:ok, {:unspec, _}} ->
×
153
        :error
154

155
      {:ok, {addr, _port}} ->
614✔
156
        {:ok, addr}
157

158
      {:error, _} ->
1✔
159
        :error
160
    end
161
  end
162

163
  def addr_from_sock({:ssl, port}) do
164
    case :ssl.peername(port) do
×
165
      {:ok, {addr, _port}} ->
×
166
        {:ok, addr}
167

168
      {:error, _} ->
×
169
        :error
170
    end
171
  end
172
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc