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

supabase / supavisor / 19370957114

14 Nov 2025 04:30PM UTC coverage: 62.682% (+1.4%) from 61.246%
19370957114

Pull #744

github

web-flow
Merge fd252a012 into 0224a24c8
Pull Request #744: fix(defrag): improve statems, caching, logs, circuit breaking

592 of 785 new or added lines in 22 files covered. (75.41%)

18 existing lines in 5 files now uncovered.

1809 of 2886 relevant lines covered (62.68%)

4508.83 hits per line

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

60.0
/lib/supavisor/secret_janitor.ex
1
defmodule Supavisor.SecretJanitor do
2
  @moduledoc """
3
  Periodically cleans up upstream secrets for terminated pools.
4
  """
5

6
  use GenServer
7
  require Logger
8

9
  @cleanup_interval :timer.hours(1)
10

11
  def start_link(_opts) do
NEW
12
    GenServer.start_link(__MODULE__, [], name: __MODULE__)
×
13
  end
14

15
  @impl true
16
  def init(_opts) do
NEW
17
    schedule_cleanup()
×
18
    {:ok, %{}}
19
  end
20

21
  @impl true
22
  def handle_info(:cleanup, state) do
NEW
23
    cleanup_orphaned_secrets()
×
NEW
24
    schedule_cleanup()
×
25
    {:noreply, state}
26
  end
27

28
  @doc """
29
  Cleans up orphaned upstream secrets for terminated pools.
30
  Public for testing purposes.
31
  """
32
  def cleanup_orphaned_secrets do
33
    active_pools = get_active_pools()
2✔
34
    cached_secrets = get_cached_upstream_secrets_with_infinite_ttl()
2✔
35

36
    orphaned = MapSet.difference(cached_secrets, active_pools)
2✔
37

38
    if MapSet.size(orphaned) > 0 do
2✔
39
      Enum.each(orphaned, fn {tenant, user} ->
1✔
40
        Logger.info("SecretJanitor: Cleaning orphaned secret for #{tenant}/#{user}")
1✔
41
        Supavisor.SecretCache.clean_upstream_secrets(tenant, user)
1✔
42
      end)
43
    end
44

45
    Logger.notice("SecretJanitor: Cleaned #{MapSet.size(orphaned)} orphaned secrets")
2✔
46
  end
47

48
  defp schedule_cleanup do
NEW
49
    Process.send_after(self(), :cleanup, @cleanup_interval)
×
50
  end
51

52
  defp get_active_pools do
53
    Registry.select(Supavisor.Registry.Tenants, [
54
      {
55
        {{:manager, {{:_, :"$1"}, :"$2", :_, :_, :_}}, :_, :_},
56
        [],
57
        [{{:"$1", :"$2"}}]
58
      }
59
    ])
60
    |> MapSet.new()
2✔
61
  end
62

63
  defp get_cached_upstream_secrets_with_infinite_ttl do
64
    case Cachex.keys(Supavisor.Cache) do
2✔
65
      {:ok, keys} ->
66
        keys
67
        |> Enum.filter(fn
68
          {:secrets_for_upstream_auth, _tenant, _user} = key ->
69
            Cachex.ttl(Supavisor.Cache, key) == {:ok, nil}
3✔
70

NEW
71
          _ ->
×
72
            false
73
        end)
74
        |> MapSet.new(fn {:secrets_for_upstream_auth, tenant, user} -> {tenant, user} end)
2✔
75

76
      {:error, reason} ->
NEW
77
        Logger.error("SecretJanitor: Failed to get cache keys: #{inspect(reason)}")
×
NEW
78
        MapSet.new()
×
79
    end
80
  end
81
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

© 2025 Coveralls, Inc