diff --git a/apps/roster/src/protocol/roster_room.erl b/apps/roster/src/protocol/roster_room.erl index 16f6254b50456862be985b65b6ef9fb29be8c1e9..e18b599b6db348ef50f94b4b34692fec1a0bff2a 100644 --- a/apps/roster/src/protocol/roster_room.erl +++ b/apps/roster/src/protocol/roster_room.erl @@ -231,17 +231,18 @@ info(#'Room'{status = remove, members = Members, admins = Admins0, id = Room}, R case roster:muc_member(APId, Room) of #'Member'{status = admin, reader = Reader} = AdmMember-> %% APId = roster:phone_id(ClientId), - {Mmbrs, Aliases, Rosters} = - lists:foldr(fun(#'Member'{phone_id = PhoneId}, {Ms, Alss, Rs} = Acc) -> + {Mmbrs, Aliases, RosterIds} = + lists:foldr(fun(#'Member'{phone_id = PhoneId}, {Ms, Alss, RIds} = Acc) -> case roster:muc_member(PhoneId, Room, presence) of %% #'Member'{status = admin} = M when Status == member -> M; %% TODO can admin remove other admin? #'Member'{feed_id = Feed, alias = Alias} = M -> roster:unsubscribe_room(M), %% Unsubscribe this member from the room. - {ok, #'Roster'{roomlist = Rooms} = Roster} = kvs:get('Roster', roster:roster_id(PhoneId)), + RosterId = roster:roster_id(PhoneId), + {ok, #'Roster'{roomlist = Rooms} = Roster} = kvs:get('Roster', RosterId), roster:unsubscribe_muc(Roster2 = Roster#'Roster'{roomlist = lists:ukeymerge(#'Room'.id, [StoredRoom#'Room'{status = removed}], Rooms)}, Feed), kvs:put(M2 = M#'Member'{status = removed, update = roster:now_msec()}), - {[M2 | Ms], [Alias, <<",">> | Alss], [Roster2 | Rs]}; + {[M2 | Ms], [Alias, <<",">> | Alss], [RosterId | RIds]}; false -> Acc end end, {[], [], []}, Members ++ Admins), {Admins2, Members2} = roster:split_members(Mmbrs), Admins3 = lists:ukeymerge(#'Member'.id, lists:ukeysort(#'Member'.id, Admins2), [AdmMember]), @@ -250,7 +251,7 @@ info(#'Room'{status = remove, members = Members, admins = Admins0, id = Room}, R files = [#'Desc'{payload = iolist_to_binary([APId, <<" removed: ">>, lists:droplast(Aliases)])}]}, Reader), {_, StoredRoom2} = roster:put_readers(write_top, AdmMember, StoredRoom), kvs:put(R = StoredRoom2#'Room'{update = roster:now_msec(), last_msg = Msg#'Message'.id}), - [roster:update_rooms(Rstr, R#'Room'{status = removed}) || Rstr <- Rosters], + [roster:update_rooms(RId, R#'Room'{status = removed}) || RId <- RosterIds], R2 = roster:reader_cache(R#'Room'{status = remove, last_msg = [], members = Members2, admins = Admins3}), roster:send_room(C, R2), @@ -280,9 +281,10 @@ info(#'Room'{status = delete, members = [], admins = [], id = Room} = R, Req, kvs:put(Member#'Member'{reader = 0, update = roster:now_msec(), status = removed}), roster:send_ses(C, roster:phone(PhoneId), R#'Room'{update = Now}); _ -> - {ok, Roster = #'Roster'{roomlist = Rooms}} = kvs:get('Roster', roster:roster_id(PhoneId)), + RosterId = roster:roster_id(PhoneId), + {ok, Roster = #'Roster'{roomlist = Rooms}} = kvs:get('Roster', RosterId), RoomRoster = lists:keyfind(Room, #'Room'.id, Rooms), - roster:update_rooms(Roster, RoomRoster#'Room'{type = group}) + roster:update_rooms(RosterId, RoomRoster#'Room'{type = group}) end || #'Member'{reader = Reader, phone_id = PhoneId} = Member <- roster:members(Feed), Reader/=0], {ok, R2} = kvs:get('Room', Room), kvs:put(case IsMsg of true -> R2#'Room'{status = delete}; _-> R2#'Room'{type = group} end), diff --git a/apps/roster/src/roster.erl b/apps/roster/src/roster.erl index cc3e4f5bf8dc247a52bee36dc5fd899e0d749c54..1cd9a139d5490459e1d10e6825f958bc37d48310 100644 --- a/apps/roster/src/roster.erl +++ b/apps/roster/src/roster.erl @@ -1091,7 +1091,7 @@ add_member(#'Room'{} = R, #'Member'{feed_id = #muc{name = Room} = Feed, alias = no_muc_message -> []; _ -> #writer{cache = LastMsg} = add_message(#'Message'{status = [], type = [sys], feed_id = Feed, from = PhoneId, to = Room, files = [#'Desc'{payload = MsgPayload}]}), LastMsg end, - update_rooms(Roster, R), subscribe_room(M2 = M#'Member'{phone_id = PhoneId}), + update_rooms(RosterId, R), subscribe_room(M2 = M#'Member'{phone_id = PhoneId}), subscribe_muc(PhoneId, Feed), {M2#'Member'{alias = member_alias(Alias, Name, Surname)}, Msg, R}; add_member(#'Room'{} = R, #'Member'{phone_id = PhoneId} = M, Args) -> @@ -1181,14 +1181,16 @@ contact_readmsg(LocalPhoneId, PhoneId) -> update_room(#'Roster'{} = Roster, #'Room'{} = Room)-> kvs:put(Roster#'Roster'{roomlist = lists:keyreplace(#'Room'.id, Room)}). -update_rooms(#'Roster'{roomlist = Rooms} = Roster, #'Room'{status = Status} = R) -> - R2 = case Status of removed -> R;_ -> R#'Room'{last_msg = []} end, - kvs:put(Roster#'Roster'{roomlist = lists:ukeymerge(#'Room'.id, [R2], Rooms)}); -update_rooms(RosterId, #'Room'{} = R) when is_integer(RosterId) -> - case kvs:get('Roster', RosterId) of - {error, _} -> {error, roster_not_found}; - {ok, #'Roster'{} = Roster} -> update_rooms(Roster, R) end; -update_rooms(PhoneId, R) -> update_rooms(roster_id(PhoneId), R). +update_rooms(RosterId, #'Room'{status = Status} = R) when is_integer(RosterId) -> + {atomic, Res} = mnesia:transaction(fun() -> + case kvs:get('Roster', RosterId) of + {error, _} -> {error, roster_not_found}; + {ok, #'Roster'{roomlist = Rooms} = Roster} -> + R2 = case Status of removed -> R;_ -> R#'Room'{last_msg = []} end, + kvs:put(Roster#'Roster'{roomlist = lists:ukeymerge(#'Room'.id, [R2], Rooms)}) + end end), + Res; +update_rooms(PhoneId, R) when is_binary(PhoneId) -> update_rooms(roster_id(PhoneId), R). remove_rooms(<<"emqttd_", _/binary>> = ClientId, Rooms) -> remove_rooms(phone_id(ClientId), Rooms);