Skip to content

Commit

Permalink
fix: Improve start counter logic on Connect module (#1190)
Browse files Browse the repository at this point in the history
Improve start counter logic on Connect module
  • Loading branch information
filipecabaco authored Nov 6, 2024
1 parent f3d5d0a commit ae4c675
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 38 deletions.
2 changes: 1 addition & 1 deletion lib/realtime/tenants.ex
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ defmodule Realtime.Tenants do
:notify_private_alpha
:private_only
"""
@spec update_management(String.t(), map()) :: {:ok, Tenant.t()} | {:error, term()}
@spec get_tenant_by_external_id(String.t()) :: Tenant.t() | nil
def update_management(tenant_id, attrs) do
tenant_id
|> Cache.get_tenant_by_external_id()
Expand Down
83 changes: 53 additions & 30 deletions lib/realtime/tenants/connect/start_counters.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,38 @@ defmodule Realtime.Tenants.Connect.StartCounters do
@impl true
def run(acc) do
%{tenant_id: tenant_id} = acc
tenant = Cache.get_tenant_by_external_id(tenant_id)

with {:ok, _} <- start_joins_per_second_counter(tenant),
{:ok, _} <- start_max_events_counter(tenant),
{:ok, _} <- start_db_events_counter(tenant) do
with tenant when not is_nil(tenant) <- Cache.get_tenant_by_external_id(tenant_id),
:ok <- start_joins_per_second_counter(tenant),
:ok <- start_max_events_counter(tenant),
:ok <- start_db_events_counter(tenant) do
{:ok, acc}
else
nil -> {:error, "Tenant not found"}
{:error, reason} -> {:error, reason}
end

{:ok, acc}
end

def start_joins_per_second_counter(tenant) do
%{max_joins_per_second: max_joins_per_second} = tenant
id = Tenants.joins_per_second_key(tenant)
GenCounter.new(id)

RateCounter.new(id,
idle_shutdown: :infinity,
telemetry: %{
event_name: [:channel, :joins],
measurements: %{limit: max_joins_per_second},
metadata: %{tenant: tenant}
}
)
res =
RateCounter.new(id,
idle_shutdown: :infinity,
telemetry: %{
event_name: [:channel, :joins],
measurements: %{limit: max_joins_per_second},
metadata: %{tenant: tenant}
}
)

case res do
{:ok, _} -> :ok
{:error, {:already_started, _}} -> :ok
{:error, reason} -> {:error, reason}
end
end

def start_max_events_counter(tenant) do
Expand All @@ -45,27 +54,41 @@ defmodule Realtime.Tenants.Connect.StartCounters do

GenCounter.new(key)

RateCounter.new(key,
idle_shutdown: :infinity,
telemetry: %{
event_name: [:channel, :events],
measurements: %{limit: max_events_per_second},
metadata: %{tenant: tenant}
}
)
res =
RateCounter.new(key,
idle_shutdown: :infinity,
telemetry: %{
event_name: [:channel, :events],
measurements: %{limit: max_events_per_second},
metadata: %{tenant: tenant}
}
)

case res do
{:ok, _} -> :ok
{:error, {:already_started, _}} -> :ok
{:error, reason} -> {:error, reason}
end
end

def start_db_events_counter(tenant) do
key = Tenants.db_events_per_second_key(tenant)
GenCounter.new(key)

RateCounter.new(key,
idle_shutdown: :infinity,
telemetry: %{
event_name: [:channel, :db_events],
measurements: %{},
metadata: %{tenant: tenant}
}
)
res =
RateCounter.new(key,
idle_shutdown: :infinity,
telemetry: %{
event_name: [:channel, :db_events],
measurements: %{},
metadata: %{tenant: tenant}
}
)

case res do
{:ok, _} -> :ok
{:error, {:already_started, _}} -> :ok
{:error, reason} -> {:error, reason}
end
end
end
2 changes: 1 addition & 1 deletion lib/realtime_web/controllers/tenant_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ defmodule RealtimeWeb.TenantController do
Logger.metadata(external_id: tenant_id, project: tenant_id)

case Tenants.update_management(tenant_id, attrs) do
{:ok, %Tenant{} = tenant} ->
%Tenant{} = tenant ->
render(conn, "show.json", tenant: tenant)

{:error, :tenant_not_found} ->
Expand Down
2 changes: 1 addition & 1 deletion lib/realtime_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ defmodule RealtimeWeb.Router do
pipe_through(:api)

resources("/tenants", TenantController, param: "tenant_id", except: [:edit, :new])
patch("/tenants/:tenant_id", TenantController, :patch)
post("/tenants/:tenant_id/reload", TenantController, :reload)
get("/tenants/:tenant_id/health", TenantController, :health)
patch("/tenants/:tenant_id/management", TenantController, :patch)
end

scope "/api", RealtimeWeb do
Expand Down
3 changes: 2 additions & 1 deletion lib/realtime_web/views/tenant_view.ex
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ defmodule RealtimeWeb.TenantView do
max_events_per_second: tenant.max_events_per_second,
max_joins_per_second: tenant.max_joins_per_second,
inserted_at: tenant.inserted_at,
extensions: tenant.extensions
extensions: tenant.extensions,
private_only: tenant.private_only
}
end
end
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule Realtime.MixProject do
def project do
[
app: :realtime,
version: "2.33.21",
version: "2.33.22",
elixir: "~> 1.16.0",
elixirc_paths: elixirc_paths(Mix.env()),
start_permanent: Mix.env() == :prod,
Expand Down
2 changes: 2 additions & 0 deletions test/realtime/tenants/authorization_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ defmodule Realtime.Tenants.AuthorizationTest do
role: claims.role
})

Realtime.Tenants.Connect.CreatePartitions.run(%{db_conn_pid: db_conn})

on_exit(fn -> Process.exit(db_conn, :normal) end)

%{
Expand Down
11 changes: 8 additions & 3 deletions test/realtime_web/controllers/tenant_controller_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -300,15 +300,20 @@ defmodule RealtimeWeb.TenantControllerTest do
"private_only" => true
}

conn = patch(conn, Routes.tenant_path(conn, :patch, tenant.external_id, tenant: attrs))
conn = patch(conn, Routes.tenant_path(conn, :patch, tenant.external_id), attrs)
data = json_response(conn, 200)["data"]
assert data["max_concurrent_users"] == 300
assert data["max_channels_per_client"] == 150
assert data["max_events_per_second"] == 250
assert data["max_joins_per_second"] == 50
assert data["private_only"] == true

tenant = Tenants.Cache.get_tenant_by_external_id(tenant.external_id)
tenant = Tenants.get_tenant_by_external_id(tenant.external_id)
assert tenant.max_concurrent_users == 300
assert tenant.max_channels_per_client == 150
assert tenant.max_events_per_second == 250
assert tenant.max_joins_per_second == 50
assert tenant.private_only == false
assert tenant.private_only == true
end
end
end
Expand Down

0 comments on commit ae4c675

Please sign in to comment.