Skip to content

Commit 380b882

Browse files
fix: match error on Connect (#1536)
--------- Co-authored-by: Eduardo Gurgel Pinho <[email protected]>
1 parent e8a343a commit 380b882

File tree

3 files changed

+83
-26
lines changed

3 files changed

+83
-26
lines changed

lib/realtime/tenants/connect.ex

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,20 +55,24 @@ defmodule Realtime.Tenants.Connect do
5555
| {:error, :tenant_database_unavailable}
5656
| {:error, :initializing}
5757
| {:error, :tenant_database_connection_initializing}
58+
| {:error, :tenant_db_too_many_connections}
5859
| {:error, :rpc_error, term()}
5960
def lookup_or_start_connection(tenant_id, opts \\ []) when is_binary(tenant_id) do
6061
case get_status(tenant_id) do
6162
{:ok, conn} ->
6263
{:ok, conn}
6364

6465
{:error, :tenant_database_unavailable} ->
65-
call_external_node(tenant_id, opts)
66+
{:error, :tenant_database_unavailable}
6667

6768
{:error, :tenant_database_connection_initializing} ->
6869
call_external_node(tenant_id, opts)
6970

7071
{:error, :initializing} ->
7172
{:error, :tenant_database_unavailable}
73+
74+
{:error, :tenant_db_too_many_connections} ->
75+
{:error, :tenant_db_too_many_connections}
7276
end
7377
end
7478

@@ -80,6 +84,7 @@ defmodule Realtime.Tenants.Connect do
8084
| {:error, :tenant_database_unavailable}
8185
| {:error, :initializing}
8286
| {:error, :tenant_database_connection_initializing}
87+
| {:error, :tenant_db_too_many_connections}
8388
def get_status(tenant_id) do
8489
case :syn.lookup(__MODULE__, tenant_id) do
8590
{pid, %{conn: nil}} ->

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ defmodule Realtime.MixProject do
44
def project do
55
[
66
app: :realtime,
7-
version: "2.50.1",
7+
version: "2.50.2",
88
elixir: "~> 1.17.3",
99
elixirc_paths: elixirc_paths(Mix.env()),
1010
start_permanent: Mix.env() == :prod,

test/realtime/tenants/connect_test.exs

Lines changed: 76 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,54 @@ defmodule Realtime.Tenants.ConnectTest do
100100
# This one will succeed
101101
{:ok, _pid} = Connect.lookup_or_start_connection(tenant.external_id)
102102
end
103+
104+
test "too many db connections", %{tenant: tenant} do
105+
extension = %{
106+
"type" => "postgres_cdc_rls",
107+
"settings" => %{
108+
"db_host" => "127.0.0.1",
109+
"db_name" => "postgres",
110+
"db_user" => "supabase_admin",
111+
"db_password" => "postgres",
112+
"poll_interval" => 100,
113+
"poll_max_changes" => 100,
114+
"poll_max_record_bytes" => 1_048_576,
115+
"region" => "us-east-1",
116+
"ssl_enforced" => false,
117+
"db_pool" => 100,
118+
"subcriber_pool_size" => 100,
119+
"subs_pool_size" => 100
120+
}
121+
}
122+
123+
{:ok, tenant} = update_extension(tenant, extension)
124+
125+
parent = self()
126+
127+
# Let's slow down Connect starting
128+
expect(Database, :check_tenant_connection, fn t ->
129+
:timer.sleep(1000)
130+
call_original(Database, :check_tenant_connection, [t])
131+
end)
132+
133+
connect = fn -> send(parent, Connect.lookup_or_start_connection(tenant.external_id)) end
134+
135+
# Start an early connect
136+
spawn(connect)
137+
:timer.sleep(100)
138+
139+
# Start others
140+
spawn(connect)
141+
spawn(connect)
142+
143+
# This one should block and wait for the first Connect
144+
{:error, :tenant_db_too_many_connections} = Connect.lookup_or_start_connection(tenant.external_id)
145+
146+
assert_receive {:error, :tenant_db_too_many_connections}
147+
assert_receive {:error, :tenant_db_too_many_connections}
148+
assert_receive {:error, :tenant_db_too_many_connections}
149+
refute_receive _any
150+
end
103151
end
104152

105153
describe "region rebalancing" do
@@ -263,6 +311,34 @@ defmodule Realtime.Tenants.ConnectTest do
263311
assert {:error, :tenant_suspended} = Connect.lookup_or_start_connection(tenant.external_id)
264312
end
265313

314+
test "tenant not able to connect if database has not enough connections", %{
315+
tenant: tenant
316+
} do
317+
extension = %{
318+
"type" => "postgres_cdc_rls",
319+
"settings" => %{
320+
"db_host" => "127.0.0.1",
321+
"db_name" => "postgres",
322+
"db_user" => "supabase_admin",
323+
"db_password" => "postgres",
324+
"poll_interval" => 100,
325+
"poll_max_changes" => 100,
326+
"poll_max_record_bytes" => 1_048_576,
327+
"region" => "us-east-1",
328+
"ssl_enforced" => false,
329+
"db_pool" => 100,
330+
"subcriber_pool_size" => 100,
331+
"subs_pool_size" => 100
332+
}
333+
}
334+
335+
{:ok, tenant} = update_extension(tenant, extension)
336+
337+
assert capture_log(fn ->
338+
assert {:error, :tenant_db_too_many_connections} = Connect.lookup_or_start_connection(tenant.external_id)
339+
end) =~ ~r/Only \d+ available connections\. At least \d+ connections are required/
340+
end
341+
266342
test "handles tenant suspension and unsuspension in a reactive way", %{tenant: tenant} do
267343
assert {:ok, db_conn} = Connect.lookup_or_start_connection(tenant.external_id)
268344
assert Connect.ready?(tenant.external_id)
@@ -459,30 +535,6 @@ defmodule Realtime.Tenants.ConnectTest do
459535
test "if tenant does not exist, does nothing" do
460536
assert :ok = Connect.shutdown("none")
461537
end
462-
463-
test "tenant not able to connect if database has not enough connections", %{tenant: tenant} do
464-
extension = %{
465-
"type" => "postgres_cdc_rls",
466-
"settings" => %{
467-
"db_host" => "127.0.0.1",
468-
"db_name" => "postgres",
469-
"db_user" => "supabase_admin",
470-
"db_password" => "postgres",
471-
"poll_interval" => 100,
472-
"poll_max_changes" => 100,
473-
"poll_max_record_bytes" => 1_048_576,
474-
"region" => "us-east-1",
475-
"ssl_enforced" => false,
476-
"db_pool" => 100,
477-
"subcriber_pool_size" => 100,
478-
"subs_pool_size" => 100
479-
}
480-
}
481-
482-
{:ok, tenant} = update_extension(tenant, extension)
483-
484-
assert {:error, :tenant_db_too_many_connections} = Connect.lookup_or_start_connection(tenant.external_id)
485-
end
486538
end
487539

488540
describe "registers into local registry" do

0 commit comments

Comments
 (0)