SNAPKITTYWEST commited on
Commit
d44946a
·
verified ·
1 Parent(s): 20c2253

Add src/hk_browser_registry.erl

Browse files
Files changed (1) hide show
  1. src/hk_browser_registry.erl +70 -0
src/hk_browser_registry.erl ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ %%%-------------------------------------------------------------------
2
+ %%% @doc HK-BROWSER :: session_id -> pid directory.
3
+ %%%
4
+ %%% `hk_browser_session' processes are anonymous (started under
5
+ %%% `simple_one_for_one', so they can't be `{local, Name}' registered
6
+ %%% by session id -- ids are runtime data, not compile-time atoms).
7
+ %%% This registry is the lookup table the API and agent runtime use
8
+ %%% instead. A session registers itself once Chromium is confirmed
9
+ %%% ready; the registry monitors it and removes the entry on exit
10
+ %%% (including the gap between a crash and `hk_browser_sup' bringing
11
+ %%% a replacement back up under the same session id, which
12
+ %%% re-registers when *it* becomes ready).
13
+ %%% @end
14
+ %%%-------------------------------------------------------------------
15
+ -module(hk_browser_registry).
16
+ -behaviour(gen_server).
17
+
18
+ -export([start_link/0, register/2, unregister/1, lookup/1, list_sessions/0]).
19
+ -export([init/1, handle_call/3, handle_cast/2, handle_info/2]).
20
+
21
+ -define(TAB, hk_browser_registry_tab).
22
+
23
+ start_link() ->
24
+ hk_sup_util:start_link_retry(
25
+ fun() -> gen_server:start_link({local, ?MODULE}, ?MODULE, [], []) end).
26
+
27
+ -spec register(binary(), pid()) -> ok.
28
+ register(SessionId, Pid) ->
29
+ gen_server:call(?MODULE, {register, SessionId, Pid}).
30
+
31
+ -spec unregister(binary()) -> ok.
32
+ unregister(SessionId) ->
33
+ gen_server:call(?MODULE, {unregister, SessionId}).
34
+
35
+ -spec lookup(binary()) -> {ok, pid()} | {error, not_found}.
36
+ lookup(SessionId) ->
37
+ case ets:lookup(?TAB, SessionId) of
38
+ [{SessionId, Pid}] -> {ok, Pid};
39
+ [] -> {error, not_found}
40
+ end.
41
+
42
+ -spec list_sessions() -> [{binary(), pid()}].
43
+ list_sessions() ->
44
+ ets:tab2list(?TAB).
45
+
46
+ init([]) ->
47
+ ets:new(?TAB, [set, named_table, protected]),
48
+ {ok, #{monitors => #{}}}.
49
+
50
+ handle_call({register, SessionId, Pid}, _From, State = #{monitors := Mons}) ->
51
+ ets:insert(?TAB, {SessionId, Pid}),
52
+ MonRef = erlang:monitor(process, Pid),
53
+ {reply, ok, State#{monitors := Mons#{MonRef => SessionId}}};
54
+ handle_call({unregister, SessionId}, _From, State) ->
55
+ ets:delete(?TAB, SessionId),
56
+ {reply, ok, State}.
57
+
58
+ handle_cast(_Msg, State) ->
59
+ {noreply, State}.
60
+
61
+ handle_info({'DOWN', MonRef, process, _Pid, _Reason}, State = #{monitors := Mons}) ->
62
+ case maps:take(MonRef, Mons) of
63
+ {SessionId, Mons2} ->
64
+ ets:delete(?TAB, SessionId),
65
+ {noreply, State#{monitors := Mons2}};
66
+ error ->
67
+ {noreply, State}
68
+ end;
69
+ handle_info(_Info, State) ->
70
+ {noreply, State}.