diff --git a/VERSION b/VERSION index 54eae6b4..1b507d18 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.1.38 +1.1.39 diff --git a/lib/supavisor.ex b/lib/supavisor.ex index 29e6b411..cff685ea 100644 --- a/lib/supavisor.ex +++ b/lib/supavisor.ex @@ -1,6 +1,7 @@ defmodule Supavisor do @moduledoc false require Logger + import Cachex.Spec alias Supavisor.Helpers, as: H alias Supavisor.Tenants, as: T alias Supavisor.Manager @@ -160,6 +161,37 @@ defmodule Supavisor do end) end + @spec del_all_cache(String.t()) :: [map()] + def del_all_cache(tenant) do + Logger.info("Deleting all cache for tenant #{tenant}") + + del = fn key, acc -> + result = Cachex.del(Supavisor.Cache, key) + [%{inspect(key) => inspect(result)} | acc] + end + + Supavisor.Cache + |> Cachex.stream!() + |> Enum.reduce([], fn entry(key: key), acc -> + case key do + {:metrics, ^tenant} -> del.(key, acc) + {:secrets, ^tenant, _} -> del.(key, acc) + {:user_cache, _, _, ^tenant, _} -> del.(key, acc) + {:tenant_cache, ^tenant, _} -> del.(key, acc) + _ -> acc + end + end) + end + + @spec del_all_cache_dist(String.t(), pos_integer()) :: [map()] + def del_all_cache_dist(tenant, timeout \\ 15_000) do + Logger.info("Deleting all dist cache for tenant #{tenant}") + + for node <- [node() | Node.list()] do + %{to_string(node) => :erpc.call(node, Supavisor, :del_all_cache, [tenant], timeout)} + end + end + @spec get_local_pool(id) :: map | pid | nil def get_local_pool(id) do match = {{:pool, :_, :_, id}, :"$2", :"$3"} diff --git a/lib/supavisor/syn_handler.ex b/lib/supavisor/syn_handler.ex index 7251351f..9ab5cf75 100644 --- a/lib/supavisor/syn_handler.ex +++ b/lib/supavisor/syn_handler.ex @@ -7,7 +7,7 @@ defmodule Supavisor.SynHandler do def on_process_unregistered( :tenants, - {{_type, tenant}, user, _mode, _db_name} = id, + {{_type, _tenant}, _user, _mode, _db_name} = id, _pid, _meta, reason @@ -16,7 +16,6 @@ defmodule Supavisor.SynHandler do # remove all Prometheus metrics for the specified tenant PromEx.remove_metrics(id) - Supavisor.del_all_cache(tenant, user) end def resolve_registry_conflict( diff --git a/lib/supavisor_web/controllers/tenant_controller.ex b/lib/supavisor_web/controllers/tenant_controller.ex index 8f17d7c9..6c7c82e7 100644 --- a/lib/supavisor_web/controllers/tenant_controller.ex +++ b/lib/supavisor_web/controllers/tenant_controller.ex @@ -111,6 +111,7 @@ defmodule SupavisorWeb.TenantController do end def update(conn, %{"external_id" => id, "tenant" => params}) do + Logger.info("Delete cache dist #{id}: #{inspect(Supavisor.del_all_cache_dist(id))}") cert = H.upstream_cert(params["upstream_tls_ca"]) if params["upstream_ssl"] && params["upstream_verify"] == "peer" && !cert do @@ -169,6 +170,8 @@ defmodule SupavisorWeb.TenantController do def delete(conn, %{"external_id" => id}) do code = if Tenants.delete_tenant_by_external_id(id), do: 204, else: 404 + Logger.info("Delete cache dist #{id}: #{inspect(Supavisor.del_all_cache_dist(id))}") + send_resp(conn, code, "") end @@ -188,6 +191,11 @@ defmodule SupavisorWeb.TenantController do Logger.metadata(project: external_id) result = Supavisor.terminate_global(external_id) |> inspect() Logger.warning("Terminate #{external_id}: #{result}") + + Logger.info( + "Delete cache dist #{external_id}: #{inspect(Supavisor.del_all_cache_dist(external_id))}" + ) + render(conn, "show_terminate.json", result: result) end diff --git a/test/supavisor_web/controllers/tenant_controller_test.exs b/test/supavisor_web/controllers/tenant_controller_test.exs index ae40e3b3..bb9d05f2 100644 --- a/test/supavisor_web/controllers/tenant_controller_test.exs +++ b/test/supavisor_web/controllers/tenant_controller_test.exs @@ -73,8 +73,10 @@ defmodule SupavisorWeb.TenantControllerTest do conn: conn, tenant: %Tenant{external_id: external_id} = _tenant } do + set_cache(external_id) conn = put(conn, Routes.tenant_path(conn, :update, external_id), tenant: @update_attrs) assert %{"external_id" => ^external_id} = json_response(conn, 200)["data"] + check_cache(external_id) conn = get(conn, Routes.tenant_path(conn, :show, external_id)) @@ -108,7 +110,9 @@ defmodule SupavisorWeb.TenantControllerTest do setup [:create_tenant] test "deletes chosen tenant", %{conn: conn, tenant: %Tenant{external_id: external_id}} do + set_cache(external_id) conn = delete(conn, Routes.tenant_path(conn, :delete, external_id)) + check_cache(external_id) assert response(conn, 204) end end @@ -128,4 +132,16 @@ defmodule SupavisorWeb.TenantControllerTest do tenant = tenant_fixture() %{tenant: tenant} end + + defp set_cache(external_id) do + Supavisor.Tenants.get_user_cache(:single, "user", external_id, nil) + Supavisor.Tenants.get_tenant_cache(external_id, nil) + end + + defp check_cache(external_id) do + assert {:ok, nil} = + Cachex.get(Supavisor.Cache, {:user_cache, :single, "user", external_id, nil}) + + assert {:ok, nil} = Cachex.get(Supavisor.Cache, {:tenant_cache, external_id, nil}) + end end