87 lines
2.4 KiB
Erlang
87 lines
2.4 KiB
Erlang
% Copyright (c) Camden Dixie O'Brien
|
|
% SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
-module(subject_router).
|
|
-behaviour(gen_server).
|
|
|
|
-export([start_link/0, log_session/1, get_activities/0]).
|
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
|
terminate/2, code_change/3]).
|
|
|
|
start_link() ->
|
|
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
|
|
|
|
log_session(Session) ->
|
|
gen_server:call(?MODULE, {log_session, Session}).
|
|
|
|
get_activities() ->
|
|
gen_server:call(?MODULE, get_activities).
|
|
|
|
init([]) ->
|
|
{MonitorRef, Pids} = pg:monitor(study_system_server, subject_servers),
|
|
SubjectTable = ets:new(subject_table, [private]),
|
|
register_servers(SubjectTable, Pids),
|
|
{ok, #{monitor_ref => MonitorRef,
|
|
subject_table => SubjectTable}}.
|
|
|
|
handle_call({log_session, {Subject, Type, Timestamp, Minutes}},
|
|
_From, State = #{subject_table := SubjectTable}) ->
|
|
case ets:lookup(SubjectTable, Subject) of
|
|
[{Subject, Pid}] ->
|
|
{reply,
|
|
subject_server:log_session(Pid, Type, Timestamp, Minutes),
|
|
State};
|
|
[] ->
|
|
{reply, {error, invalid_subject}, State}
|
|
end;
|
|
handle_call(get_activities, _From,
|
|
State = #{subject_table := SubjectTable}) ->
|
|
Pids = lists:flatten(ets:match(SubjectTable, {'_', '$1'})),
|
|
Activities = lists:flatmap(
|
|
fun(Pid) -> subject_server:get_activities(Pid) end,
|
|
Pids),
|
|
{reply, {activities, Activities}, State};
|
|
handle_call(_Request, _From, State) ->
|
|
{reply, ok, State}.
|
|
|
|
handle_cast(_Msg, State) ->
|
|
{noreply, State}.
|
|
|
|
handle_info({Ref, join, subject_servers, Pids},
|
|
State = #{monitor_ref := MonitorRef,
|
|
subject_table := SubjectTable})
|
|
when Ref =:= MonitorRef ->
|
|
register_servers(SubjectTable, Pids),
|
|
{noreply, State};
|
|
handle_info({Ref, leave, subject_servers, Pids},
|
|
State = #{monitor_ref := MonitorRef,
|
|
subject_table := SubjectTable})
|
|
when Ref =:= MonitorRef ->
|
|
deregister_servers(SubjectTable, Pids),
|
|
{noreply, State};
|
|
handle_info(_Info, State) ->
|
|
{noreply, State}.
|
|
|
|
terminate(_Reason, _State) ->
|
|
ok.
|
|
|
|
code_change(_OldVsn, State, _Extra) ->
|
|
{ok, State}.
|
|
|
|
register_servers(SubjectTable, Pids) ->
|
|
[register_server(SubjectTable, Pid) || Pid <- Pids].
|
|
|
|
register_server(SubjectTable, Pid) ->
|
|
try
|
|
{subject, Subject} = subject_server:get_subject(Pid),
|
|
ets:insert(SubjectTable, {Subject, Pid})
|
|
catch
|
|
_:_ -> ok
|
|
end.
|
|
|
|
deregister_servers(SubjectTable, Pids) ->
|
|
[deregister_server(SubjectTable, Pid) || Pid <- Pids].
|
|
|
|
deregister_server(SubjectTable, Pid) ->
|
|
ets:match_delete(SubjectTable, {'_', Pid}).
|