From 2ae52babca22c81760ed8773fdb2f1ce2bf4c99d Mon Sep 17 00:00:00 2001 From: Ashlynne Mitchell Date: Thu, 1 Jan 2026 17:45:33 +1100 Subject: [PATCH] refactor: update Atex.IdentityResolver.Cache.ETS to use ConCache --- CHANGELOG.md | 2 + lib/atex/identity_resolver/cache/ets.ex | 57 +++++++++++++++---------- 2 files changed, 37 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88ae12c..b5e3f66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,8 @@ and this project adheres to - `mix atex.lexicons` now adds `@moduledoc false` to generated modules to stop them from automatically cluttering documentation. +- `Atex.IdentityResolver.Cache.ETS` now uses ConCache instead of ETS directly, + with a 1-hour TTL for cached identity information. ## [0.6.0] - 2025-11-25 diff --git a/lib/atex/identity_resolver/cache/ets.ex b/lib/atex/identity_resolver/cache/ets.ex index 4ac731f..3f104ef 100644 --- a/lib/atex/identity_resolver/cache/ets.ex +++ b/lib/atex/identity_resolver/cache/ets.ex @@ -1,57 +1,70 @@ defmodule Atex.IdentityResolver.Cache.ETS do + @moduledoc """ + ConCache-based implementation for Identity Resolver caching. + + Stores identity information (DID and handle mappings) with a 1-hour TTL. + Uses two separate cache entries per identity to allow lookups by either DID or handle. + """ + alias Atex.IdentityResolver.Identity @behaviour Atex.IdentityResolver.Cache use Supervisor - @table :atex_identities + @cache :atex_identities_cache + @ttl_ms :timer.hours(1) def start_link(opts) do - Supervisor.start_link(__MODULE__, opts) + Supervisor.start_link(__MODULE__, opts, name: __MODULE__) end @impl Supervisor def init(_opts) do - :ets.new(@table, [:set, :public, :named_table]) - Supervisor.init([], strategy: :one_for_one) + children = [ + {ConCache, + [ + name: @cache, + ttl_check_interval: :timer.minutes(5), + global_ttl: @ttl_ms + ]} + ] + + Supervisor.init(children, strategy: :one_for_one) end @impl Atex.IdentityResolver.Cache @spec insert(Identity.t()) :: Identity.t() def insert(identity) do - # TODO: benchmark lookups vs match performance, is it better to use a "composite" key or two inserts? - :ets.insert(@table, {{identity.did, identity.handle}, identity}) + ConCache.put(@cache, {:did, identity.did}, identity) + ConCache.put(@cache, {:handle, identity.handle}, identity) identity end @impl Atex.IdentityResolver.Cache @spec get(String.t()) :: {:ok, Identity.t()} | {:error, atom()} def get(identifier) do - lookup(identifier) + case ConCache.get(@cache, {:did, identifier}) do + nil -> + case ConCache.get(@cache, {:handle, identifier}) do + nil -> {:error, :not_found} + identity -> {:ok, identity} + end + + identity -> + {:ok, identity} + end end @impl Atex.IdentityResolver.Cache @spec delete(String.t()) :: :noop | Identity.t() def delete(identifier) do - case lookup(identifier) do + case get(identifier) do {:ok, identity} -> - :ets.delete(@table, {identity.did, identity.handle}) + ConCache.delete(@cache, {:did, identity.did}) + ConCache.delete(@cache, {:handle, identity.handle}) identity _ -> :noop end end - - defp lookup(identifier) do - case :ets.match(@table, {{identifier, :_}, :"$1"}) do - [] -> - case :ets.match(@table, {{:_, identifier}, :"$1"}) do - [] -> {:error, :not_found} - [[identity]] -> {:ok, identity} - end - - [[identity]] -> - {:ok, identity} - end - end end -- 2.51.2