From 406ce4d91667e64dc3944246bbd79ef629c00eb1 Mon Sep 17 00:00:00 2001 From: Hans Svensson Date: Mon, 8 Jun 2020 10:43:44 +0200 Subject: [PATCH 1/3] Fix starred messages to use message id Used to store the full message, but this doesn't work when messages are edited, etc. --- apps/roster/include/roster.hrl | 4 +- apps/roster/src/protocol/roster_favorite.erl | 74 ++++++++++++-------- apps/roster/src/roster.erl | 61 +++++----------- apps/roster/src/roster_db.erl | 2 - 4 files changed, 68 insertions(+), 73 deletions(-) diff --git a/apps/roster/include/roster.hrl b/apps/roster/include/roster.hrl index 337faa5e3..494711da3 100644 --- a/apps/roster/include/roster.hrl +++ b/apps/roster/include/roster.hrl @@ -178,7 +178,9 @@ -record('Star', {id = [] :: [] | integer(), client_id = [] :: [] | binary(), roster_id = [] :: [] | integer(), - message = [] :: [] |#'Message'{}, + %% internally in DB: integer() | #'Message'{} + %% new stars just have msg id, old stars a full message + message = [] :: [] | #'Message'{}, tags = [] :: list(#'Tag'{}), status = [] :: [] | add | remove}). diff --git a/apps/roster/src/protocol/roster_favorite.erl b/apps/roster/src/protocol/roster_favorite.erl index e0afd8031..80a657812 100644 --- a/apps/roster/src/protocol/roster_favorite.erl +++ b/apps/roster/src/protocol/roster_favorite.erl @@ -28,38 +28,56 @@ info(#'ExtendedStar'{}, Req, #cx{params = ClientId, client_pid = C} = State) -> end, {reply, {bert, IO}, Req, State}; -info(#'Star'{status = add, message = #'Message'{id = MsgId} = Msg} = Data, Req, #cx{params = ClientId, client_pid = C} = State) -> +info(#'Star'{status = add, message = #'Message'{id = MsgId}} = Data, Req, #cx{params = ClientId, client_pid = C} = State) -> ?ROSTER_LOG_REQ('Star', add, ClientId, "MsgId=~p", [MsgId]), RosterId = roster:roster_id(PhoneId = roster:phone_id(ClientId)), - IO = case kvs:get('Roster', RosterId) of - {ok, #'Roster'{favorite = StFavMsgs} = Roster} -> - case lists:keyfind(MsgId, #'Message'.id, - lists:flatten([M || #'Star'{message = M} <- StFavMsgs])) of - false -> UpdMsg = Msg#'Message'{seenby = [], repliedby = [], status = []}, - UpdData = Data#'Star'{roster_id = RosterId, message = UpdMsg, id = kvs:next_id('Star', 1)}, - UpdFavMsg = lists:keystore(Msg, #'Star'.message, StFavMsgs, UpdData), - kvs:put(Roster#'Roster'{favorite = UpdFavMsg, update = roster:now_msec(), status = update}), - roster:send_ses(C, roster:phone(PhoneId), UpdData), <<>>; - _ -> <<>> - end; - #error{} -> #io{code = #error{code = roster_not_found}} - end, + IO = case kvs:get('Message', MsgId) of + {ok, Msg} -> + case kvs:get('Roster', RosterId) of + {ok, #'Roster'{favorite = StFavMsgs} = Roster} -> + case lists:member(MsgId, [roster:star_msg_id(M) || #'Star'{message = M} <- StFavMsgs]) of + false -> + UpdData = Data#'Star'{roster_id = RosterId, message = MsgId, id = kvs:next_id('Star', 1)}, + UpdFavMsgs = StFavMsgs ++ [UpdData], + kvs:put(Roster#'Roster'{favorite = UpdFavMsgs, update = roster:now_msec(), status = update}), + roster:send_ses(C, roster:phone(PhoneId), UpdData#'Star'{message = Msg}), + <<>>; + _ -> + <<>> + end; + #error{} -> #io{code = #error{code = roster_not_found}} + end; + #error{} -> + #io{code = #error{code = message_not_found}} + end, {reply, {bert, IO}, Req, State}; -info(#'Star'{id = MsgId, status = remove}, Req, #cx{params = ClientId, client_pid = C} = State) -> - ?ROSTER_LOG_REQ('Star', remove, ClientId, "MsgId=~p", [MsgId]), - Response = case kvs:get('Roster', roster:roster_id(ClientId)) of - {ok, #'Roster'{favorite = StFavMsgs} = Roster} -> - case lists:keyfind(MsgId, #'Star'.id, StFavMsgs) of - #'Star'{} = StarToBeRemoved -> - kvs:put(Roster#'Roster'{favorite = lists:keydelete(MsgId, #'Star'.id, StFavMsgs), - update = roster:now_msec(), status = update}), - roster:send_ses(C, roster:phone(roster:phone_id(ClientId)), StarToBeRemoved#'Star'{status = remove}), - <<>>; - _ -> #io{code = #error{code = message_not_found}} - end; - #error{} -> #io{code = #error{code = roster_not_found}} - end, +info(#'Star'{id = StarId, status = remove}, Req, #cx{params = ClientId, client_pid = C} = State) -> + ?ROSTER_LOG_REQ('Star', remove, ClientId, "StarId=~p", [StarId]), + Response = + case kvs:get('Roster', roster:roster_id(ClientId)) of + {ok, #'Roster'{favorite = StFavMsgs} = Roster} -> + case lists:keyfind(StarId, #'Star'.id, StFavMsgs) of + #'Star'{message = M} = Star -> + kvs:put(Roster#'Roster'{favorite = lists:keydelete(StarId, #'Star'.id, StFavMsgs), + update = roster:now_msec(), status = update}), + Star1 = Star#'Star'{status = remove}, + MsgId = roster:star_msg_id(M), + case kvs:get('Message', MsgId) of + {ok, Msg} -> + roster:send_ses(C, roster:phone(roster:phone_id(ClientId)), + Star1#'Star'{message = Msg}), + <<>>; + _ -> + roster:send_ses(C, roster:phone(roster:phone_id(ClientId)), + Star1#'Star'{message = #'Message'{id = MsgId}}), + #io{code = #error{code = message_not_found}} + end; + _ -> + #io{code = #error{code = star_not_found}} + end; + #error{} -> #io{code = #error{code = roster_not_found}} + end, {reply, {bert, Response}, Req, State}; info(#'Star'{} = Star, Req, #cx{params = ClientId} = State) -> diff --git a/apps/roster/src/roster.erl b/apps/roster/src/roster.erl index 4ff5b7a8d..accf52a61 100644 --- a/apps/roster/src/roster.erl +++ b/apps/roster/src/roster.erl @@ -1268,38 +1268,12 @@ last_upd(#'Room'{id = Room}) -> {error, _} -> 0 end; %% get update field from Room table! last_upd(#'Contact'{phone_id = PhoneId, update = Update}) -> - case roster:is_online2(PhoneId) of {online, _} -> []; _-> Update end; + case roster:is_online2(PhoneId) of + {online, _} -> []; + _ -> Update + end; last_upd(#'Star'{message = #'Message'{created = Update}}) -> Update. -last_objs(Objs, PhoneId) -> - last_objs(Objs, PhoneId, 0, 100). -last_objs(Objs, PhoneId, LastSync, N) -> - last_objs(Objs, PhoneId, LastSync, N, {[], 0}). -last_objs([], _PhoneId, _LastSync, _N, {Acc, MaxUpd}) -> - {Acc, MaxUpd, []}; -last_objs(Objs, _PhoneId, _LastSync, N, {Acc, MaxUpd}) when length(Acc) >= N -> - {Acc, MaxUpd, Objs}; -last_objs([Obj|TObjs], PhoneId, LastSync, N, {Acc, MaxUpd}) -> - Feed = feed(Obj, PhoneId), - {Created, W} = - case kvs_stream:load_writer(Feed) of - #writer{cache = #'Message'{created = Crtd}} = Writer -> - {Crtd, Writer}; - #writer{} = Writer -> - {0, Writer}; - {error, not_found} -> - {0, Feed} - end, - LastUpd = erlang:max(Created, last_upd(Obj)), - Acc2 = case LastUpd > LastSync of - true -> - Acc++[{Obj, W}]; - _ -> - Acc - end, %% TODO sort objects if update? - last_objs(TObjs, PhoneId, LastSync, N, {Acc2, erlang:max(MaxUpd, LastUpd)}). - - split_objlist(Index, Roster) -> split_objlist(Index, Roster, 0, []). @@ -1380,11 +1354,17 @@ objlist(Index, Id, LastSync, N, Fun) when Index == #'Roster'.userlist; {error, roster_not_found} end. -build_object(Object, [Chunk | _] = Acc, Roster, LastSync, N, Fun) +build_object(Star = #'Star'{ message = M }, Acc, Roster, LastSync, N, Fun) -> + {ok, Msg} = kvs:get('Message', star_msg_id(M)), + build_object1(Star#'Star'{ message = Msg }, Acc, Roster, LastSync, N, Fun); +build_object(Object, Acc, Roster, LastSync, N, Fun) -> + build_object1(Object, Acc, Roster, LastSync, N, Fun). + +build_object1(Object, [Chunk | _] = Acc, Roster, LastSync, N, Fun) when N /= [] andalso length(Chunk) >= N -> Fun(Chunk), - build_object(Object, [[] | Acc], Roster, LastSync, N, Fun); -build_object(Object, Acc, + build_object1(Object, [[] | Acc], Roster, LastSync, N, Fun); +build_object1(Object, Acc, #'Roster'{ id = Id, phone = Phone } = Roster, LastSync, _N, _Fun) -> PhoneId = phone_id(Phone, Id), @@ -1529,16 +1509,12 @@ room(RosterId, RoomId, W, LastSync) -> % STARRED MESSAGES MANAGEMENT -starlist(#'Roster'{favorite = Stars} = R) -> %% not used - [star(R, StarMsg, [], 0) || StarMsg <- Stars]; -starlist(RosterId) when is_integer(RosterId)-> - case kvs:get('Roster', RosterId) of {ok, R} -> starlist(R); _ -> [] end; -starlist(PhoneId) -> - starlist(roster_id(PhoneId)). +star_msg_id(#'Message'{id = MId}) -> MId; +star_msg_id(MId) when is_integer(MId) -> MId. star(#'Roster'{id = RosterId, phone = Phone} = Roster, - #'Star'{message = #'Message'{feed_id = Feed, from = MsgFrom} = Msg} = StarMsg, W, LastSync) - when is_record(W, writer); is_record(W, p2p); W == [] -> + #'Star'{message = #'Message'{feed_id = Feed, from = MsgFrom} = Msg} = Star, W, LastSync) + when is_record(W, writer); is_record(W, p2p); W == [] -> Writer = case W of [] -> kvs_stream:load_writer(Feed); _ -> W end, From = case Feed of #muc{name = RoomId} -> @@ -1565,7 +1541,8 @@ star(#'Roster'{id = RosterId, phone = Phone} = Roster, Contact -> Contact end end, - #'ExtendedStar'{star = StarMsg#'Star'{message = Msg#'Message'{status = []}}, from = From}; + Msg1 = Msg#'Message'{status = [], seenby = [], repliedby = []}, + #'ExtendedStar'{star = Star#'Star'{message = Msg1}, from = From}; star(Local, StMsgsList, W, LastSync) -> {ok, Roster} = kvs:get('Roster', roster_id(Local)), star(Roster, StMsgsList, W, LastSync). diff --git a/apps/roster/src/roster_db.erl b/apps/roster/src/roster_db.erl index 0f7d8e081..1641125d4 100644 --- a/apps/roster/src/roster_db.erl +++ b/apps/roster/src/roster_db.erl @@ -368,8 +368,6 @@ upd_msgs(Fun) when is_function(Fun) -> [opt_put(Fun(M), M) || M <- kvs:all('Message')], [opt_put(W#writer{first = Fun(F), cache = Fun(C)}, W) || #writer{cache = C, first = F} = W <- kvs:all(writer), (is_record(C, 'Message') orelse C == []) andalso (F == [] orelse is_record(F, 'Message'))], - [opt_put(R#'Roster'{favorite = [S#'Star'{message = Fun(Msg)} || #'Star'{message = Msg} = S <- Stars]}, R) - || R = #'Roster'{favorite = Stars} <- kvs:all('Roster')], [opt_put(J#'Job'{data = [Fun(M) || M <- Msgs]}, J) || J = #'Job'{data = Msgs} <- kvs:all('Job')], ok; upd_msgs(Fun) when is_atom(Fun)-> -- GitLab From 3df2d482867942ce19ceaf06f3d2d2834118d33a Mon Sep 17 00:00:00 2001 From: Hans Svensson Date: Fri, 5 Jun 2020 16:28:04 +0200 Subject: [PATCH 2/3] Start modeling stars/favorites --- eqc/server_eqc.erl | 153 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 148 insertions(+), 5 deletions(-) diff --git a/eqc/server_eqc.erl b/eqc/server_eqc.erl index 51781068d..07b1ea324 100644 --- a/eqc/server_eqc.erl +++ b/eqc/server_eqc.erl @@ -16,6 +16,7 @@ -define(room(Handle, Name, Status, LastMsgId, LastMsg, Args), ?CALLOUT(mock, room, [Handle, Name, Status, LastMsgId, LastMsg, Args], ok)). +-define(star(Handle, StarId, RosterId, MsgId, Status), ?CALLOUT(mock, star, [Handle, StarId, RosterId, MsgId, Status], ok)). -define(message(Handle, From, Msg, Status, Type, Args), ?CALLOUT(mock, message, [Handle, From, Msg, Status, Type, Args], ok)). -define(contact(Handle, PhoneId, Status, Args), ?CALLOUT(mock, contact, [Handle, PhoneId, Status, Args], ok)). -define(message_ack(Handle, Id, Args), ?CALLOUT(mock, message_ack, [Handle, Id, Args], ok)). @@ -36,6 +37,7 @@ -type phone() :: nat(). -type phone_id() :: binary(). -type msg_id() :: nat(). +-type star_id() :: nat(). -record(client, { handle :: symbolic(pid()) @@ -46,6 +48,7 @@ { phone :: phone() , phone_id :: symbolic(phone_id()) , friends = #{} :: #{phone() => true} + , stars = [] :: list({star_id(), msg_id()}) }). -record(message, @@ -54,6 +57,12 @@ , visible_to = all :: all | [phone()] , from = sys :: phone() | sys }). +-record(star, + {id :: star_id(), + roster_id :: nat(), + msg_id :: msg_id(), + status :: add | remove }). + -record(contact, { id :: binary() , reader :: term() @@ -334,6 +343,27 @@ rename_room(OldRoom, NewRoom, S) -> Room1 = Room0#room{ name = NewRoom }, S#state{ rooms = lists:keyreplace(OldRoom, #room.id, S#state.rooms, Room1) }. +add_star(Phone, StarId, MsgId, S) -> + on_user(Phone, S, + fun(U = #user{ stars = Stars }) -> + U#user{ stars = lists:keystore(StarId, 1, Stars, {StarId, MsgId}) } + end). + +delete_star(Phone, StarId, S) -> + on_user(Phone, S, + fun(U = #user{ stars = Stars }) -> + U#user{ stars = lists:keydelete(StarId, 1, Stars) } + end). + +is_starred_msg(S, Phone, MsgId) -> + #user{ stars = Stars } = get_user(S, Phone), + lists:keymember(MsgId, 2, Stars). + +starred_msg(S, Phone, StarId) -> + #user{ stars = Stars } = get_user(S, Phone), + {_, MsgId} = lists:keyfind(StarId, 1, Stars), + MsgId. + %% -- Generators ------------------------------------------------------------- gen_phone() -> noshrink(choose(1, 1000)). @@ -446,13 +476,21 @@ get_profile(H) -> get_profile_post(S, [Handle], V) -> case V of - #{rooms := Rooms, friends := Friends} -> + #{rooms := Rooms, friends := Friends, stars := Stars } -> Phone = client_phone(S, Handle), conj([ check_friend(S, Phone, Friend) || Friend <- Friends ] ++ - [ check_room(S, Phone, Room) || Room <- Rooms ]); + [ check_room(S, Phone, Room) || Room <- Rooms ] ++ + [ check_star(S, Phone, Star) || Star <- Stars ]); _ -> false end. +check_star(S, Phone, #star{ id = StarId, msg_id = MsgId } = Star) -> + #user{ stars = Stars } = get_user(S, Phone), + case lists:keyfind(StarId, 1, Stars) of + {StarId, MsgId} -> true; + Err -> {Err, Star} + end. + check_friend(_S, _Phone, #contact{ status = Status }) when Status == request; Status == authorization -> true; check_friend(S, Phone, @@ -700,6 +738,69 @@ delete_message_callouts(S, [Handle, Feed, _FeedId, MsgId0, Ack]) -> || Phone <- Phones, H1 <- get_clients(S, Phone), H1 /= Handle ] ++ [ ?message_ack(Handle, '_', '_') || Ack ]). +%% --- add_star --- + +starrable_msgs(S) -> + [ {Handle, MsgId} + || #client{ handle = Handle, phone = Phone } <- S#state.clients, + #feed_info{ history = Msgs } <- [get_feed(S, Feed) || Feed <- user_feeds(S, Phone) ], + #message{ id = MsgId } <- Msgs ]. + +add_star_pre(S) -> + starrable_msgs(S) /= []. + +add_star_args(S) -> + ?LET({Handle, MsgId}, elements(starrable_msgs(S)), + [Handle, MsgId]). + +add_star_pre(S, [Handle, MsgId]) -> + lists:member({Handle, MsgId}, starrable_msgs(S)). + +add_star(Handle, MsgId) -> + call_client(Handle, {add_star, MsgId}). + +add_star_callouts(S, [Handle, MsgId]) -> + Phone = client_phone(S, Handle), + IsStarred = is_starred_msg(S, Phone, MsgId), + ?PAR([ ?CALLOUTS( + ?MATCH({StarId, ok}, ?star(Handle, ?VAR, '_', MsgId, add)), + ?APPLY(do_add_star, [Phone, StarId, MsgId]) ) || not IsStarred ] ++ + [ ?star(H1, '_', '_', MsgId, add) || H1 <- get_clients(S, Phone), H1 /= Handle, not IsStarred ] + ). + +do_add_star_next(S, _, [Phone, StarId, MsgId]) -> + add_star(Phone, StarId, MsgId, S). + +%% --- delete_star --- + +client_stars(S) -> + [ {Handle, StarId} + || #client{ handle = Handle, phone = Phone } <- S#state.clients, + #user{ phone = Phone1, stars = Stars } <- S#state.users, + Phone == Phone1, + {StarId, _MsgId} <- Stars ]. + +delete_star_pre(S) -> + client_stars(S) /= []. + +delete_star_args(S) -> + ?LET({Handle, StarId}, elements(client_stars(S)), [Handle, StarId]). + +delete_star_pre(S, [Handle, StarId]) -> + lists:member({Handle, StarId}, client_stars(S)). + +delete_star(Handle, StarId) -> + call_client(Handle, {delete_star, StarId}). + +delete_star_callouts(S, [Handle, StarId]) -> + Phone = client_phone(S, Handle), + MsgId = starred_msg(S, Phone, StarId), + ?PAR([ ?star(H1, StarId, '_', MsgId, remove) || H1 <- get_clients(S, Phone) ]). + +delete_star_next(S, _, [Handle, StarId]) -> + Phone = client_phone(S, Handle), + delete_star(Phone, StarId, S). + %% --- get_history --- clients_with_nonempty_feeds(S, Type) -> @@ -1268,7 +1369,9 @@ weight(_, add_to_room) -> 5; weight(_, remove_from_room) -> 3; weight(_, promote_member) -> 4; weight(_, demote_member) -> 4; -weight(_, leave_room) -> 3. +weight(_, leave_room) -> 3; +weight(_, add_star) -> 2; +weight(_, delete_star) -> 2. %% -- Connection handler ----------------------------------------------------- @@ -1329,6 +1432,32 @@ handle_connection(Parent, User) -> handle_connection(Parent, User) end. +handle_payload(#'Contact'{phone_id = PhoneId, reader = Reader, unread = Unread, last_msg = LastMsg, status = Status}) -> + mock:contact(self(), PhoneId, Status, #{reader => Reader, unread => Unread}), + case LastMsg of + #'Message'{} -> mock_message(LastMsg); + _ -> ok + end; +handle_payload(#'Message'{} = Message) -> + mock_message(Message); +handle_payload(#'MessageAck'{id = Id, next = Prev, feed_id = Feed}) -> + mock:message_ack(self(), Id, #{prev => Prev, feed => Feed}); +handle_payload(#'Room'{name = Name0, status = Status, last_msg = LastMsg, admins = _As, members = _Ms}) -> + Name = + case Name0 of + [] -> <<"no name">>; + _ -> hd(binary:split(Name0, <<"-">>)) + end, + mock:room(self(), Name, Status, to_msg_id(LastMsg), to_msg_payload(LastMsg), #{ }); +handle_payload(#'Star'{id = StarId, roster_id = RosterId, message = #'Message'{id = MsgId}, status = St}) -> + mock:star(self(), StarId, RosterId, MsgId, St); +handle_payload(#io{ code = {ok, _}, data = {ok, _} }) -> + ok; +handle_payload(#io{ code = {error, Err}}) -> + mock:error(Err); +handle_payload(Payload) -> + mock:unexpected(self(), Payload). + call_client(H, Msg) -> Ref = make_ref(), H ! {call, Ref, self(), Msg}, @@ -1346,8 +1475,10 @@ mock_message(#'Message'{feed_id = Feed, prev = Prev, next = Next, type = Type, handle_call(User, get_profile) -> ?mqtt(Profile) = nynja:get_profile1(User, 1000), - #'Profile'{ rosters = [#'Roster'{ userlist = Contacts, roomlist = Rooms }] } = Profile, - #{ rooms => [to_room(R) || R <- Rooms], friends => [to_contact(C) || C <- Contacts] }; + #'Profile'{ rosters = [#'Roster'{ userlist = Contacts, roomlist = Rooms, favorite = Stars }] } = Profile, + #{ rooms => [to_room(R) || R <- Rooms], + friends => [to_contact(C) || C <- Contacts], + stars => [to_star(S) || S <- Stars] }; handle_call(User, {get_room, Room}) -> ?mqtt(R) = nynja:get_room(User, Room), @@ -1390,6 +1521,14 @@ handle_call(User, {read_msg, FeedId, MsgId}) -> ReadMsg = nynja:read_msg(User, FeedId, MsgId), async_send(User, ReadMsg); +handle_call(User, {add_star, MsgId}) -> + StarMsg = #'Star'{status = add, message = #'Message'{id = MsgId}}, + async_send(User, StarMsg); + +handle_call(User, {delete_star, StarId}) -> + StarMsg = #'Star'{status = remove, id = StarId}, + async_send(User, StarMsg); + handle_call(User, {get_history, Feed, MsgId, Count}) -> case nynja:get_messages(User, Feed, MsgId, Count) of ?mqtt(#'History'{data = Messages}) -> [ to_message(Msg) || Msg <- Messages ]; @@ -1553,6 +1692,9 @@ to_contact(#'Contact'{ phone_id = Id, reader = Reader, unread = Unread, status = to_member(#'Member'{id = Id, feed_id = Feed, phone_id = PhoneId, reader = Reader, status = Status}) -> #member{ id = Id, feed = Feed, phone_id = PhoneId, reader = Reader, status = Status }. +to_star(#'ExtendedStar'{star = #'Star'{id = StarId, roster_id = RosterId, message = #'Message'{id = MsgId}, status = St}}) -> + #star{id = StarId, roster_id = RosterId, msg_id = MsgId, status = St}. + singleton_room(RoomId, Member = #'Member'{}, member, Status) -> #'Room'{ id = RoomId, members = [Member], status = Status }; singleton_room(RoomId, Member = #'Member'{}, admin, Status) -> @@ -1602,6 +1744,7 @@ api_spec() -> , #api_fun{ name = message, arity = 6 } , #api_fun{ name = message_ack, arity = 3 } , #api_fun{ name = room, arity = 6 } + , #api_fun{ name = star, arity = 5 } , #api_fun{ name = error, arity = 1 } ] } ] }. -- GitLab From a010a6489d7719c2d441411a7fa0f55eb47fae09 Mon Sep 17 00:00:00 2001 From: Hans Svensson Date: Fri, 5 Jun 2020 16:27:45 +0200 Subject: [PATCH 3/3] Refactor payload handling and user roster_validator:validate/1 to validate data --- eqc/server_eqc.erl | 32 +++++--------------------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/eqc/server_eqc.erl b/eqc/server_eqc.erl index 07b1ea324..71bb93a07 100644 --- a/eqc/server_eqc.erl +++ b/eqc/server_eqc.erl @@ -1398,34 +1398,12 @@ handle_connection(Parent, User) -> Res = handle_call(User, Msg), From ! {reply, Ref, Res}, handle_connection(Parent, User); - {Pid, ?mqtt(#'Contact'{phone_id = PhoneId, reader = Reader, unread = Unread, last_msg = LastMsg, status = Status})} -> - catch mock:contact(self(), PhoneId, Status, #{reader => Reader, unread => Unread}), - case LastMsg of - #'Message'{} -> mock_message(LastMsg); - _ -> ok - end, - handle_connection(Parent, User); - {Pid, ?mqtt(#'Message'{} = Message)} -> - mock_message(Message), - handle_connection(Parent, User); - {Pid, ?mqtt(#'MessageAck'{id = Id, next = Prev, feed_id = Feed})} -> - catch mock:message_ack(self(), Id, #{prev => Prev, feed => Feed}), - handle_connection(Parent, User); - {Pid, ?mqtt(#'Room'{name = Name0, status = Status, last_msg = LastMsg, admins = _As, members = _Ms})} -> - Name = - case Name0 of - [] -> <<"no name">>; - _ -> hd(binary:split(Name0, <<"-">>)) - end, - catch mock:room(self(), Name, Status, to_msg_id(LastMsg), to_msg_payload(LastMsg), #{ }), - handle_connection(Parent, User); - {Pid, ?mqtt(#io{ code = {ok, _}, data = {ok, _} })} -> - handle_connection(Parent, User); - {Pid, ?mqtt(#io{ code = {error, Err}})} -> - catch mock:error(Err), - handle_connection(Parent, User); {Pid, ?mqtt(Payload)} -> - catch mock:unexpected(self(), Payload), + case roster_validator:validate(Payload) of + [] -> ok; + Err -> catch mock:validation_error(Err) + end, + catch handle_payload(Payload), handle_connection(Parent, User); Packet -> catch mock:unexpected(self(), Packet), -- GitLab