mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-19 05:55:34 +09:00
fix(gateway): flush buffered presences in arrival order (#2273)
This commit is contained in:
1 parent
32a64fb097
commit
bb7e8cc6f1
1 file changed
+58
-5
@@ -94,8 +94,8 @@ buffer_presence(Event, Data, State) ->
|
|||||||
Pending = ensure_queue(maps:get(pending_presences, State, [])),
|
Pending = ensure_queue(maps:get(pending_presences, State, [])),
|
||||||
UserId = presence_user_id(Data),
|
UserId = presence_user_id(Data),
|
||||||
Entry = #{event => Event, data => Data, user_id => UserId},
|
Entry = #{event => Event, data => Data, user_id => UserId},
|
||||||
Trimmed = trim_queue_from_tail(Pending, ?MAX_PENDING_PRESENCE_BUFFER_SIZE - 1),
|
Trimmed = trim_queue_from_front(Pending, ?MAX_PENDING_PRESENCE_BUFFER_SIZE - 1),
|
||||||
NewPending = queue:in_r(Entry, Trimmed),
|
NewPending = queue:in(Entry, Trimmed),
|
||||||
State#{pending_presences => NewPending}.
|
State#{pending_presences => NewPending}.
|
||||||
|
|
||||||
-spec maybe_flush_pending_presences(event(), map(), session_state()) ->
|
-spec maybe_flush_pending_presences(event(), map(), session_state()) ->
|
||||||
@@ -261,10 +261,10 @@ relationship_target_id(Data) when is_map(Data) ->
|
|||||||
ensure_queue(List) when is_list(List) -> queue:from_list(List);
|
ensure_queue(List) when is_list(List) -> queue:from_list(List);
|
||||||
ensure_queue(Q) -> Q.
|
ensure_queue(Q) -> Q.
|
||||||
|
|
||||||
-spec trim_queue_from_tail(queue:queue(T), non_neg_integer()) -> queue:queue(T).
|
-spec trim_queue_from_front(queue:queue(T), non_neg_integer()) -> queue:queue(T).
|
||||||
trim_queue_from_tail(Queue, MaxLen) ->
|
trim_queue_from_front(Queue, MaxLen) ->
|
||||||
case queue:len(Queue) > MaxLen of
|
case queue:len(Queue) > MaxLen of
|
||||||
true -> trim_queue_from_tail(queue:drop_r(Queue), MaxLen);
|
true -> trim_queue_from_front(queue:drop(Queue), MaxLen);
|
||||||
false -> Queue
|
false -> Queue
|
||||||
end.
|
end.
|
||||||
|
|
||||||
@@ -437,4 +437,57 @@ flushed_id_list_test() ->
|
|||||||
?assertEqual([42], flushed_id_list(42)),
|
?assertEqual([42], flushed_id_list(42)),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
presence_status_data(UserIdBin, Status) ->
|
||||||
|
#{<<"user">> => #{<<"id">> => UserIdBin}, <<"status">> => Status}.
|
||||||
|
|
||||||
|
buffered_presences_flush_in_arrival_order_test() ->
|
||||||
|
drain_mailbox(),
|
||||||
|
Base = #{
|
||||||
|
user_id => 1,
|
||||||
|
seq => 0,
|
||||||
|
buffer => [],
|
||||||
|
socket_pid => self(),
|
||||||
|
pending_presences => queue:new()
|
||||||
|
},
|
||||||
|
S1 = buffer_presence(presence_update, presence_status_data(<<"2">>, <<"online">>), Base),
|
||||||
|
S2 = buffer_presence(presence_update, presence_status_data(<<"2">>, <<"dnd">>), S1),
|
||||||
|
Flushed = flush_all_pending_presences(S2),
|
||||||
|
?assertEqual(2, maps:get(seq, Flushed)),
|
||||||
|
?assertEqual([{1, <<"online">>}, {2, <<"dnd">>}], collect_dispatched_statuses(2)).
|
||||||
|
|
||||||
|
pending_presence_buffer_drops_oldest_when_full_test() ->
|
||||||
|
Total = ?MAX_PENDING_PRESENCE_BUFFER_SIZE + 2,
|
||||||
|
Filled = lists:foldl(
|
||||||
|
fun(N, Acc) ->
|
||||||
|
buffer_presence(
|
||||||
|
presence_update,
|
||||||
|
presence_status_data(integer_to_binary(N), <<"online">>),
|
||||||
|
Acc
|
||||||
|
)
|
||||||
|
end,
|
||||||
|
#{user_id => 1, pending_presences => queue:new()},
|
||||||
|
lists:seq(1, Total)
|
||||||
|
),
|
||||||
|
Pending = queue:to_list(maps:get(pending_presences, Filled)),
|
||||||
|
?assertEqual(?MAX_PENDING_PRESENCE_BUFFER_SIZE, length(Pending)),
|
||||||
|
?assertEqual(3, maps:get(user_id, hd(Pending))),
|
||||||
|
?assertEqual(Total, maps:get(user_id, lists:last(Pending))).
|
||||||
|
|
||||||
|
collect_dispatched_statuses(0) ->
|
||||||
|
[];
|
||||||
|
collect_dispatched_statuses(N) ->
|
||||||
|
receive
|
||||||
|
{dispatch, presence_update, Data, Seq} ->
|
||||||
|
[{Seq, maps:get(<<"status">>, Data)} | collect_dispatched_statuses(N - 1)]
|
||||||
|
after 100 ->
|
||||||
|
[]
|
||||||
|
end.
|
||||||
|
|
||||||
|
drain_mailbox() ->
|
||||||
|
receive
|
||||||
|
_Message -> drain_mailbox()
|
||||||
|
after 0 ->
|
||||||
|
ok
|
||||||
|
end.
|
||||||
|
|
||||||
-endif.
|
-endif.
|
||||||
Reference in new issue
Block a user