analytics/lib/plausible/shield/country_rule_cache.ex

66 lines
1.5 KiB
Elixir

defmodule Plausible.Shield.CountryRuleCache do
@moduledoc """
Allows retrieving Country Rules by domain and country code
"""
alias Plausible.Shield.CountryRule
import Ecto.Query
use Plausible.Cache
@cache_name :country_blocklist_by_domain
@cached_schema_fields ~w(
id
country_code
action
)a
@impl true
def name(), do: @cache_name
@impl true
def child_id(), do: :cache_country_blocklist
@impl true
def count_all() do
Plausible.Repo.aggregate(CountryRule, :count)
end
@impl true
def base_db_query() do
from rule in CountryRule,
inner_join: s in assoc(rule, :site),
select: {
s.domain,
s.domain_changed_from,
%{struct(rule, ^@cached_schema_fields) | from_cache?: true}
}
end
@impl true
def get_from_source({domain, country_code}) do
query =
base_db_query()
|> where([rule, site], rule.country_code == ^country_code and site.domain == ^domain)
case Plausible.Repo.one(query) do
{_, _, rule = %CountryRule{}} -> %CountryRule{rule | from_cache?: false}
_any -> nil
end
end
@impl true
def unwrap_cache_keys(items) do
Enum.reduce(items, [], fn
{domain, nil, object}, acc ->
[{{domain, String.upcase(object.country_code)}, object} | acc]
{domain, domain_changed_from, object}, acc ->
[
{{domain, String.upcase(object.country_code)}, object},
{{domain_changed_from, String.upcase(object.country_code)}, object} | acc
]
end)
end
end