defmodule Elixium.Store.Oracle do use GenServer @moduledoc """ Responsible for reading and writing to a given store on behalf of other processes. This fixes the issue with LevelDB not allowing multiple processes read / write to a store at the same time. """ @doc """ Start an oracle to interface with a given module. Running an oracle with a store will cause it to lock down the store, and no other process will be able to communicate with it until the oracle has died. """ @spec start_link(atom) :: {:ok, pid} | {:error, String.t()} def start_link(store) do GenServer.start_link(__MODULE__, store, name: String.to_atom("#{store}Oracle")) end def init(store_ref) do {:ok, store_ref} end def handle_call({function, options}, _from, store) do response_from_store = apply(store, function, options) {:reply, response_from_store, store} end @doc """ Call a method on the store module of a given oracle. Takes in a reference to a started oracle process, and a tuple with the method name, and a list of options to pass to the method. E.g. Oracle.inquire(oracle, {:load_known_peers, []}) """ @spec inquire(pid, tuple) :: any() def inquire(pid, options) do GenServer.call(pid, options, :infinity) end end