Skip to content

Commit

Permalink
fix: Add endpoint for realtime configuration management (#1188)
Browse files Browse the repository at this point in the history
  • Loading branch information
filipecabaco authored Nov 6, 2024
1 parent c419fce commit 7c6f2be
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 1 deletion.
14 changes: 14 additions & 0 deletions lib/realtime/api/tenant.ex
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ defmodule Realtime.Api.Tenant do
field(:events_per_second_rolling, :float, virtual: true)
field(:events_per_second_now, :integer, virtual: true)
field(:notify_private_alpha, :boolean, default: false)
field(:private_only, :boolean, default: false)

has_many(:extensions, Realtime.Api.Extensions,
foreign_key: :tenant_external_id,
Expand Down Expand Up @@ -102,4 +103,17 @@ defmodule Realtime.Api.Tenant do
def encrypt_jwt_secret(changeset) do
update_change(changeset, :jwt_secret, &Crypto.encrypt!/1)
end

def management_changeset(tenant, attrs) do
cast(tenant, attrs, [
:max_concurrent_users,
:max_events_per_second,
:max_bytes_per_second,
:max_channels_per_client,
:max_joins_per_second,
:suspend,
:notify_private_alpha,
:private_only
])
end
end
20 changes: 20 additions & 0 deletions lib/realtime/tenants.ex
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,26 @@ defmodule Realtime.Tenants do
|> tap(fn _ -> broadcast_operation_event(:unsuspend_tenant, external_id) end)
end

@doc """
Changes only information regading user managent:
:max_concurrent_users
:max_events_per_second
:max_bytes_per_second
:max_channels_per_client
:max_joins_per_second
:suspend
:notify_private_alpha
:private_only
"""
@spec update_management(String.t(), map()) :: {:ok, Tenant.t()} | {:error, term()}
def update_management(tenant_id, attrs) do
tenant_id
|> Cache.get_tenant_by_external_id()
|> Tenant.management_changeset(attrs)
|> Repo.update!()
|> tap(fn _ -> Cache.distributed_invalidate_tenant_cache(tenant_id) end)
end

defp broadcast_operation_event(action, external_id) do
Phoenix.PubSub.broadcast!(
Realtime.PubSub,
Expand Down
16 changes: 16 additions & 0 deletions lib/realtime_web/controllers/tenant_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -283,4 +283,20 @@ defmodule RealtimeWeb.TenantController do
|> render("not_found.json", tenant: nil)
end
end

def patch(conn, %{"tenant_id" => tenant_id} = attrs) do
Logger.metadata(external_id: tenant_id, project: tenant_id)

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

{:error, :tenant_not_found} ->
Helpers.log_error("TenantNotFound", "Tenant not found")

conn
|> put_status(404)
|> render("not_found.json", tenant: nil)
end
end
end
1 change: 1 addition & 0 deletions lib/realtime_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ 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)
end
Expand Down
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.19",
version: "2.33.20",
elixir: "~> 1.16.0",
elixirc_paths: elixirc_paths(Mix.env()),
start_permanent: Mix.env() == :prod,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
defmodule Realtime.Repo.Migrations.AddPrivateOnlyFlagColumnToTenant do
use Ecto.Migration

def change do
alter table(:tenants) do
add(:private_only, :boolean, default: false, null: false)
end
end
end
16 changes: 16 additions & 0 deletions test/realtime/tenants_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,20 @@ defmodule Realtime.TenantsTest do
assert_receive {:unsuspend_tenant, ^external_id}, 1000
end
end

describe "update_management/2" do
setup do
tenant = tenant_fixture()
topic = "realtime:operations:invalidate_cache"
Phoenix.PubSub.subscribe(Realtime.PubSub, topic)
%{topic: topic, tenant: tenant}
end

test "sets private_only flag to true and invalidates cache" do
%{external_id: external_id} = tenant_fixture(%{private_only: false})
tenant = Tenants.update_management(external_id, %{private_only: true})
assert tenant.private_only == true
assert_receive {:invalidate_cache, ^external_id}, 1000
end
end
end
29 changes: 29 additions & 0 deletions test/realtime_web/controllers/tenant_controller_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,35 @@ defmodule RealtimeWeb.TenantControllerTest do
end
end

describe "update tenant management information" do
setup [:create_tenant]

test "changes management information and returns updated values", %{
conn: conn,
tenant: tenant
} do
with_mock JwtVerification, verify: fn _token, _secret, _jwks -> {:ok, %{}} end do
attrs = %{
"max_concurrent_users" => 300,
"max_channels_per_client" => 150,
"max_events_per_second" => 250,
"max_joins_per_second" => 50,
"private_only" => true
}

conn = patch(conn, Routes.tenant_path(conn, :patch, tenant.external_id, tenant: attrs))
data = json_response(conn, 200)["data"]

tenant = Tenants.Cache.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
end
end
end

defp create_tenant(_) do
%{tenant: tenant_fixture()}
end
Expand Down

0 comments on commit 7c6f2be

Please sign in to comment.