defmodule RNS.IdentityStore do @moduledoc """ Manages an ets table that stores all identities and their ratchets. """ @spec child_spec(any()) :: map() def child_spec(_args) do %{ id: __MODULE__, start: {__MODULE__, :start_link, []} } end @spec start_link() :: {:ok, pid()} def start_link() do pid = spawn_link(__MODULE__, :init, []) {:ok, pid} end # Client @doc "Find an identity in the store using its hash." @spec fetch(RNS.Identity.hash()) :: {:ok, RNS.Identity.t()} | {:error, :not_found} def fetch(identity_hash) do case :ets.lookup(:identities, identity_hash) do [identity] -> # Check if the identity has expired, if it has, remove it. if RNS.Identity.expired?(identity) do delete(RNS.Identity.hash(identity)) {:error, :not_found} else {:ok, identity} end [] -> {:error, :not_found} end end @doc """ Put an identity into the store. TODO: If the identity is already in the store, verify it IS the same and update it(ratchets). """ @spec put(RNS.Identity.t()) :: boolean() def put(identity) do :ets.insert(:identities, identity) end @doc "Delete an identity from the store using its hash." @spec delete(RNS.Identity.hash()) :: boolean() def delete(identity_hash) do :ets.delete(:identities, identity_hash) end # Callbacks @spec init() :: :ok def init() do :ets.new(:identities, [ {:read_concurrency, true}, {:write_concurrency, true}, {:keypos, RNS.Identity.hash_position() + 1}, :public, :named_table ]) Process.sleep(:infinity) end end