src/parthenon_schema_server.erl

-module(parthenon_schema_server).

-behaviour(gen_server).

%% API
-export([
    start_link/0,
    add_schema/2,
    get_schema/1
]).

%% gen_server callbacks
-export([
    init/1,
    handle_call/3,
    handle_cast/2,
    handle_info/2,
    terminate/2
]).

-record(state, {}).

-define(TABLE_NAME, ?MODULE).

%%%===================================================================
%%% API
%%%===================================================================

-spec start_link() -> {ok, pid()} | ignore | {error, term()}.
start_link() ->
    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).

-spec add_schema(SchemaName :: atom(), RawSchema :: binary() | string()) -> ok | {error, term()}.
add_schema(SchemaName, RawSchema) ->
    gen_server:call(?MODULE, {add_schema, SchemaName, RawSchema}).

-spec get_schema(SchemaName :: atom()) -> {ok, parthenon_schema:schema()} | {error, not_found}.
get_schema(SchemaName) ->
    case ets:lookup(?TABLE_NAME, SchemaName) of
        [{_, Schema}] ->
            {ok, Schema};
        [] ->
            {error, not_found}
    end.

%%%===================================================================
%%% gen_server callbacks
%%%===================================================================

init([]) ->
    ets:new(?TABLE_NAME, [set, protected, {read_concurrency, true}, named_table]),
    {ok, #state{}}.

handle_call({add_schema, SchemaName, RawSchema}, _From, State) ->
    Result =
        case parthenon_schema:create(RawSchema) of
            {ok, Schema} ->
                ets:insert(?TABLE_NAME, {SchemaName, Schema}),
                ok;
            Error = {error, _} ->
                Error
        end,
    {reply, Result, State}.

handle_cast(_Msg, State) ->
    {noreply, State}.

handle_info(_Info, State) ->
    {noreply, State}.

terminate(_Reason, _State) ->
    ok.

%%%===================================================================
%%% Internal functions
%%%===================================================================