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

supabase / supavisor / 25910132761

15 May 2026 09:17AM UTC coverage: 76.904% (+0.1%) from 76.76%
25910132761

Pull #983

github

web-flow
Merge 59eff3a37 into dd2909823
Pull Request #983: chore: report current, permanent, base and previous versions

10 of 26 new or added lines in 2 files covered. (38.46%)

9 existing lines in 7 files now uncovered.

2534 of 3295 relevant lines covered (76.9%)

55940.68 hits per line

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

92.86
/lib/supavisor/client_handler/proxy.ex
1
defmodule Supavisor.ClientHandler.Proxy do
2
  @moduledoc """
3
  Handles proxy connection logic for ClientHandler.
4
  """
5

6
  require Logger
7
  require Supavisor
8

9
  alias Supavisor.ClientHandler.Proxy.Supervisor, as: ProxySupervisor
10

11
  alias Supavisor.Errors.{
12
    MaxConnectionsError,
13
    FailedToStartProxyConnectionError,
14
    ProxySupervisorUnavailableError
15
  }
16

17
  @max_sup_retries 3
18

19
  @type start_error ::
20
          MaxConnectionsError.t()
21
          | FailedToStartProxyConnectionError.t()
22
          | ProxySupervisorUnavailableError.t()
23

24
  @doc """
25
  Starts a proxy DbHandler for the given tenant.
26

27
  Ensures the proxy supervisor tree exists, then starts a DbHandler under it.
28

29
  Retries up to #{@max_sup_retries} times when the supervisor disappears between
30
  lookup and use (race with watchdog shutdown).
31

32
  Returns `{:ok, db_pid}` on success, or one of the errors defined in `start_error()`.
33
  """
34
  @spec start_proxy_connection(
35
          Supavisor.id(),
36
          pos_integer(),
37
          Supavisor.ConnectionParameters.t(),
38
          map(),
39
          map(),
40
          keyword()
41
        ) ::
42
          {:ok, pid()} | {:error, start_error()}
43
  def start_proxy_connection(
44
        id,
45
        max_clients,
46
        connection_params,
47
        tenant_feature_flags,
48
        pool_ranch,
49
        client_opts
50
      ) do
51
    child_spec =
5✔
52
      Supavisor.DbHandler.child_spec(
53
        build_db_handler_args(
54
          id,
55
          connection_params,
56
          tenant_feature_flags,
57
          pool_ranch,
58
          client_opts
59
        )
60
      )
61

62
    do_start_proxy_connection(id, max_clients, child_spec, @max_sup_retries)
5✔
63
  end
64

65
  # This function is public for test purposes, so we can test the logic
66
  # with mock processes, not DbHandlers
67
  @doc false
68
  @spec do_start_proxy_connection(
69
          Supavisor.id(),
70
          max_clients :: pos_integer(),
71
          Supervisor.child_spec(),
72
          attempts_remaining :: non_neg_integer()
73
        ) ::
74
          {:ok, pid()} | {:error, start_error()}
75
  def do_start_proxy_connection(_id, _max_clients, _child_spec, 0) do
99✔
76
    {:error, %ProxySupervisorUnavailableError{}}
77
  end
78

79
  def do_start_proxy_connection(id, max_clients, child_spec, retries) do
10,435✔
80
    with :ok <- ProxySupervisor.ensure_started(id, max_clients),
10,435✔
81
         {:ok, pid} <- ProxySupervisor.start_connection(id, child_spec) do
10,435✔
82
      {:ok, pid}
83
    else
84
      {:error, :max_children} ->
4✔
85
        {:error, MaxConnectionsError.new(:proxy, max_clients)}
86

87
      {:error, :proxy_sup_not_found} ->
UNCOV
88
        do_start_proxy_connection(id, max_clients, child_spec, retries - 1)
×
89

90
      {:error, :failed_to_start} ->
3✔
91
        {:error, %FailedToStartProxyConnectionError{}}
92
    end
93
  catch
94
    :exit, _reason ->
95
      do_start_proxy_connection(id, max_clients, child_spec, retries - 1)
423✔
96
  end
97

98
  @spec build_db_handler_args(
99
          Supavisor.id(),
100
          Supavisor.ConnectionParameters.t(),
101
          map(),
102
          map(),
103
          keyword()
104
        ) :: map()
105
  defp build_db_handler_args(
106
         Supavisor.id(tenant: tenant, user: user) = id,
107
         connection_params,
108
         tenant_feature_flags,
109
         pool_ranch,
110
         client_opts
111
       ) do
112
    proxy_connection_params = %{
5✔
113
      connection_params
114
      | port: pool_ranch.port,
5✔
115
        host: to_charlist(pool_ranch.host),
5✔
116
        ip_version: :inet,
117
        upstream_ssl: false,
118
        upstream_tls_ca: nil,
119
        upstream_verify: nil
120
    }
121

122
    %{
5✔
123
      id: id,
124
      connection_params: proxy_connection_params,
125
      user: user,
126
      tenant: tenant,
127
      tenant_feature_flags: tenant_feature_flags,
128
      replica_type: :write,
129
      mode: :proxy,
130
      proxy: true,
131
      log_level: nil,
132
      client_tls: Keyword.fetch!(client_opts, :client_ssl),
133
      client_jit: Keyword.fetch!(client_opts, :client_jit)
134
    }
135
  end
136
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

© 2026 Coveralls, Inc