diff --git a/fluxer_gateway/src/presence/presence.erl b/fluxer_gateway/src/presence/presence.erl index 736f86b2f..1d8e506a5 100644 --- a/fluxer_gateway/src/presence/presence.erl +++ b/fluxer_gateway/src/presence/presence.erl @@ -84,11 +84,14 @@ code_change(_OldVsn, State, _Extra) -> -spec handle_call(term(), gen_server:from(), state()) -> {reply, term(), state()} | {stop, normal, ok, state()}. handle_call({session_connect, Request}, {Pid, _}, State) when is_map(Request), is_pid(Pid) -> - {reply, Reply, NewState} = presence_session:handle_session_connect(Request, Pid, State), + SessionPid = session_connect_pid(Request, Pid), + {reply, Reply, NewState} = presence_session:handle_session_connect( + Request, SessionPid, State + ), FinalState = presence_broadcast:publish_global_presence( maps:get(sessions, NewState), NewState ), - presence_broadcast:send_cached_presences_to_session(Pid, FinalState), + presence_broadcast:send_cached_presences_to_session(SessionPid, FinalState), {reply, Reply, FinalState}; handle_call(get_current_visible_presence, _From, State) -> {reply, presence_broadcast:current_visible_presence(State), State}; @@ -141,6 +144,12 @@ handle_cast({sync_group_dm_recipients, RecipientsByChannel}, State) when handle_cast(Msg, State) -> handle_cast_guild(Msg, State). +-spec session_connect_pid(map(), pid()) -> pid(). +session_connect_pid(#{session_pid := Pid}, _CallerPid) when is_pid(Pid) -> + Pid; +session_connect_pid(_Request, CallerPid) -> + CallerPid. + -spec handle_sync_friends_cast([term()], [term()], state()) -> {noreply, state()}. handle_sync_friends_cast(FriendIds, FlushedIds, State) -> {noreply, @@ -280,6 +289,14 @@ normalize_start_link(ignore) -> -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). +session_connect_pid_prefers_request_session_pid_test() -> + Caller = self(), + Other = spawn(fun idle_session_proc/0), + ?assertEqual(Other, session_connect_pid(#{session_pid => Other}, Caller)), + ?assertEqual(Caller, session_connect_pid(#{}, Caller)), + ?assertEqual(Caller, session_connect_pid(#{session_pid => undefined}, Caller)), + Other ! stop. + presence_rejoin_notifies_all_sessions_test() -> Parent = self(), Session1 = spawn(fun() -> rejoin_check_receiver(Parent, one) end), @@ -349,6 +366,13 @@ test_session_entry(Pid) -> socket_pid => undefined }. +-spec idle_session_proc() -> ok. +idle_session_proc() -> + receive + stop -> ok + after 1000 -> ok + end. + -spec rejoin_check_receiver(pid(), atom()) -> term(). rejoin_check_receiver(Parent, Tag) -> receive diff --git a/fluxer_gateway/src/session/session_lifecycle.erl b/fluxer_gateway/src/session/session_lifecycle.erl index 5875b10f7..6d688d1ef 100644 --- a/fluxer_gateway/src/session/session_lifecycle.erl +++ b/fluxer_gateway/src/session/session_lifecycle.erl @@ -414,21 +414,22 @@ handle_resume_offline_timeout(_Msg, State) -> ok. notify_presence_on_resume(#{presence_pid := undefined}, _Sid, _St, _Afk, _Mob) -> ok; -notify_presence_on_resume(#{presence_pid := Pid}, SessionId, Status, Afk, Mobile) -> - spawn(fun() -> notify_presence_on_resume_worker(Pid, SessionId, Status, Afk, Mobile) end), +notify_presence_on_resume(#{presence_pid := Pid} = State, SessionId, Status, Afk, Mobile) -> + Request = #{ + session_id => SessionId, + session_pid => self(), + socket_pid => maps:get(socket_pid, State, undefined), + status => Status, + afk => Afk, + mobile => Mobile + }, + spawn(fun() -> notify_presence_on_resume_worker(Pid, Request) end), ok. --spec notify_presence_on_resume_worker(pid(), session_id(), status(), boolean(), boolean()) -> - ok. -notify_presence_on_resume_worker(Pid, SessionId, Status, Afk, Mobile) -> +-spec notify_presence_on_resume_worker(pid(), map()) -> ok. +notify_presence_on_resume_worker(Pid, Request) -> try - gen_server:call( - Pid, - {session_connect, #{ - session_id => SessionId, status => Status, afk => Afk, mobile => Mobile - }}, - 10000 - ), + gen_server:call(Pid, {session_connect, Request}, 10000), ok catch error:_Reason -> ok; diff --git a/fluxer_gateway/test/session_lifecycle_tests.erl b/fluxer_gateway/test/session_lifecycle_tests.erl index 66ba401cb..041e5654d 100644 --- a/fluxer_gateway/test/session_lifecycle_tests.erl +++ b/fluxer_gateway/test/session_lifecycle_tests.erl @@ -363,6 +363,31 @@ resume_success_state(State0) -> {reply, {ok, _Missed, 1}, State1} = session_lifecycle:handle_resume(0, self(), State0), State1. +handle_resume_registers_the_session_process_with_presence_test() -> + SessionPid = self(), + Presence = spawn(fun() -> fake_presence_loop(SessionPid) end), + State0 = resume_test_state(#{presence_pid => Presence, seq => 1}), + {reply, {ok, [], 1}, _State1} = session_lifecycle:handle_resume(1, self(), State0), + receive + {presence_session_connect, Request} -> + ?assertEqual(SessionPid, maps:get(session_pid, Request)), + ?assertEqual(<<"session-resume-test">>, maps:get(session_id, Request)) + after 2000 -> + ?assert(false, presence_session_connect_not_received) + end. + +fake_presence_loop(Parent) -> + receive + {'$gen_call', From, {session_connect, Request}} -> + Parent ! {presence_session_connect, Request}, + gen_server:reply(From, {ok, []}), + fake_presence_loop(Parent); + _Other -> + fake_presence_loop(Parent) + after 5000 -> + ok + end. + resume_test_state(Overrides) -> maps:merge( #{