Current section
Files
Jump to
Current section
Files
lib/mongo/pbkdf2_cache.ex
defmodule Mongo.PBKDF2Cache do @moduledoc false use GenServer @name __MODULE__ def start_link do GenServer.start_link(__MODULE__, [], name: @name) end def pbkdf2(password, salt, iterations) do GenServer.call(@name, {password, salt, iterations}) end def init([]) do {:ok, %{pending: %{}, cache: %{}}} end def handle_call(key, from, s) do cond do salted_password = s.cache[key] -> {:reply, salted_password, s} list = s.pending[key] -> {:noreply, put_in(s.pending[key], [from|list])} true -> run_task(key) {:noreply, put_in(s.pending[key], [from])} end end def handle_info({ref, {key, result}}, s) when is_reference(ref) do Enum.each(s.pending[key], fn from -> GenServer.reply(from, result) end) s = update_in(s.pending, &Map.delete(&1, key)) s = put_in(s.cache[key], result) {:noreply, s} end def handle_info({:DOWN, _ref, :process, _pid, :normal}, s) do {:noreply, s} end defp run_task({password, salt, iterations} = key) do Task.async(fn -> result = Mongo.PBKDF2.generate(password, salt, iterations: iterations, length: 20, digest: :sha) {key, result} end) endend