A set of utilities for working with the AT Protocol in Elixir.

refactor: update Atex.IdentityResolver.Cache.ETS to use ConCache

ovyerus.com 2ae52bab 47417790

verified
Changed files
+37 -22
lib
atex
identity_resolver
cache
+2
CHANGELOG.md
··· 38 38 39 39 - `mix atex.lexicons` now adds `@moduledoc false` to generated modules to stop 40 40 them from automatically cluttering documentation. 41 + - `Atex.IdentityResolver.Cache.ETS` now uses ConCache instead of ETS directly, 42 + with a 1-hour TTL for cached identity information. 41 43 42 44 ## [0.6.0] - 2025-11-25 43 45
+35 -22
lib/atex/identity_resolver/cache/ets.ex
··· 1 1 defmodule Atex.IdentityResolver.Cache.ETS do 2 + @moduledoc """ 3 + ConCache-based implementation for Identity Resolver caching. 4 + 5 + Stores identity information (DID and handle mappings) with a 1-hour TTL. 6 + Uses two separate cache entries per identity to allow lookups by either DID or handle. 7 + """ 8 + 2 9 alias Atex.IdentityResolver.Identity 3 10 @behaviour Atex.IdentityResolver.Cache 4 11 use Supervisor 5 12 6 - @table :atex_identities 13 + @cache :atex_identities_cache 14 + @ttl_ms :timer.hours(1) 7 15 8 16 def start_link(opts) do 9 - Supervisor.start_link(__MODULE__, opts) 17 + Supervisor.start_link(__MODULE__, opts, name: __MODULE__) 10 18 end 11 19 12 20 @impl Supervisor 13 21 def init(_opts) do 14 - :ets.new(@table, [:set, :public, :named_table]) 15 - Supervisor.init([], strategy: :one_for_one) 22 + children = [ 23 + {ConCache, 24 + [ 25 + name: @cache, 26 + ttl_check_interval: :timer.minutes(5), 27 + global_ttl: @ttl_ms 28 + ]} 29 + ] 30 + 31 + Supervisor.init(children, strategy: :one_for_one) 16 32 end 17 33 18 34 @impl Atex.IdentityResolver.Cache 19 35 @spec insert(Identity.t()) :: Identity.t() 20 36 def insert(identity) do 21 - # TODO: benchmark lookups vs match performance, is it better to use a "composite" key or two inserts? 22 - :ets.insert(@table, {{identity.did, identity.handle}, identity}) 37 + ConCache.put(@cache, {:did, identity.did}, identity) 38 + ConCache.put(@cache, {:handle, identity.handle}, identity) 23 39 identity 24 40 end 25 41 26 42 @impl Atex.IdentityResolver.Cache 27 43 @spec get(String.t()) :: {:ok, Identity.t()} | {:error, atom()} 28 44 def get(identifier) do 29 - lookup(identifier) 45 + case ConCache.get(@cache, {:did, identifier}) do 46 + nil -> 47 + case ConCache.get(@cache, {:handle, identifier}) do 48 + nil -> {:error, :not_found} 49 + identity -> {:ok, identity} 50 + end 51 + 52 + identity -> 53 + {:ok, identity} 54 + end 30 55 end 31 56 32 57 @impl Atex.IdentityResolver.Cache 33 58 @spec delete(String.t()) :: :noop | Identity.t() 34 59 def delete(identifier) do 35 - case lookup(identifier) do 60 + case get(identifier) do 36 61 {:ok, identity} -> 37 - :ets.delete(@table, {identity.did, identity.handle}) 62 + ConCache.delete(@cache, {:did, identity.did}) 63 + ConCache.delete(@cache, {:handle, identity.handle}) 38 64 identity 39 65 40 66 _ -> 41 67 :noop 42 - end 43 - end 44 - 45 - defp lookup(identifier) do 46 - case :ets.match(@table, {{identifier, :_}, :"$1"}) do 47 - [] -> 48 - case :ets.match(@table, {{:_, identifier}, :"$1"}) do 49 - [] -> {:error, :not_found} 50 - [[identity]] -> {:ok, identity} 51 - end 52 - 53 - [[identity]] -> 54 - {:ok, identity} 55 68 end 56 69 end 57 70 end