chut / src / chut_user.erl

%%%===================================================================
%%% Module used to create an abstraction layer against all components
%%% of a user.
%%%===================================================================
-module(chut_user).

%% API
-export([start/3, terminate/1, subscribe/1, unsubscribe/2, subscribers/1,
         message/3, relay/3, history/1]).

%%--------------------------------------------------------------------
%% Function: Start(UserId, TimeOut, HistoryLimit) -> ok
%% Description: registers a new user process or does nothing if it
%% already is registered.
%%--------------------------------------------------------------------
start(UserId, TimeOut, HistoryLimit) ->
    case global:whereis_name(UserId) of
        undefined ->
            %% start it here
            ChildSpec = {UserId,
                         {chut_user_sup, start_link, [UserId, TimeOut]},
                         transient,
                         TimeOut,
                         supervisor,
                         [chut_user_sup]},
            supervisor:start_child(chut_user_supersup,ChildSpec),
            chut_user_manager:add_handler(UserId, chut_user_dispatch_handler, UserId),
            chut_user_manager:add_handler(UserId, chut_user_history_handler, {UserId,HistoryLimit}),
            io:format("started user process for id ~p~n",[UserId]),
            started;
        _Pid ->
            io:format("connected to user ~p~n",[UserId]),
            ok
    end.

%%--------------------------------------------------------------------
%% Function: terminate(UserId, Reason) -> true
%% Description: kills the supervisor which should trickle down to the
%% children. The commands to remove the supervisor are ran within an
%% independent process. This is necessary because otherwise,
%% terminating the user will keep it from deleting its own child spec
%% from the chut supervisor.
%%--------------------------------------------------------------------
terminate(UserId) ->
    proc_lib:spawn(fun() ->
        supervisor:terminate_child(chut_user_supersup, UserId),
        supervisor:delete_child(chut_user_supersup, UserId)
    end).

%%--------------------------------------------------------------------
%% Function: subscribe(UserId) -> {ok, HandlerId}
%% Description: adds a listen handler to a gen_event and notifies the
%% gen_fsm to track it.
%%--------------------------------------------------------------------
subscribe(UserId) ->
    HandlerId = {chut_user_listen_handler, make_ref()},
    chut_user_manager:add_sup_handler(UserId, HandlerId, {UserId, self(), HandlerId}),
    chut_user_monitor:add_handler(UserId, HandlerId),
    {ok, HandlerId}.

%%--------------------------------------------------------------------
%% Function: subscribers(UserId) -> [Subscriber]
%% Description: returns a list of all the handlers attached to a given
%% user.
%%--------------------------------------------------------------------
subscribers(UserId) ->
    chut_user_manager:get_handlers(UserId).

%%--------------------------------------------------------------------
%% Function: unsubscribe(UserId, HandlerId) -> ok
%% Description: removes a client's listen handler from a user.
%%--------------------------------------------------------------------
unsubscribe(UserId, HandlerId) ->
    chut_user_manager:delete_handler(UserId, HandlerId, []),
    chut_user_monitor:delete_handler(UserId, HandlerId),
    ok.

%%--------------------------------------------------------------------
%% Function: message(From, To, Message) -> ok
%% Description: Takes a message and routes it through the sending user
%%--------------------------------------------------------------------
message(From, To, Message) ->
    chut_user_manager:notify(From, {send, To, Message}),
    ok.

%%--------------------------------------------------------------------
%% Function: relay(From, To, Message) -> ok
%% Description: Usually called by the dispatch handler. takes a sent
%% message and routes it to the receiving user.
%%--------------------------------------------------------------------
relay(From, To, Message) ->
    chut_user_manager:notify(To, {received, From, Message}),
    ok.

%%--------------------------------------------------------------------
%% Function: history(UserId) -> [Messages]
%% Description: Called by the client. Contacts an event handler
%% that returns the last messages sent and received by UserId.
%%--------------------------------------------------------------------
history(UserId) ->
    chut_user_manager:notify(UserId, {self(), history}),
    receive
        {UserId, {history, History}} ->
            History
        after 5000 ->
            throw(no_history_response)
    end.
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.