From 6214e0385d696880cdb19404d085b15889161b2f Mon Sep 17 00:00:00 2001 From: Pawel Chmielowski Date: Wed, 23 Jul 2025 19:40:18 +0200 Subject: [PATCH 1/2] Report db failures from mod_muc:restore_room --- src/mod_muc.erl | 13 ++++++------- src/mod_muc_admin.erl | 34 ++++++++++++++++++++++++++++++---- src/mod_muc_sql.erl | 6 ++++-- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/src/mod_muc.erl b/src/mod_muc.erl index 7a8a9f9ea..0ca31cb80 100644 --- a/src/mod_muc.erl +++ b/src/mod_muc.erl @@ -97,7 +97,7 @@ -callback import(binary(), binary(), [binary()]) -> ok. -callback store_room(binary(), binary(), binary(), list(), list()|undefined) -> {atomic, any()}. -callback store_changes(binary(), binary(), binary(), list()) -> {atomic, any()}. --callback restore_room(binary(), binary(), binary()) -> muc_room_opts() | error. +-callback restore_room(binary(), binary(), binary()) -> muc_room_opts() | error | {error, atom()}. -callback forget_room(binary(), binary(), binary()) -> {atomic, any()}. -callback can_use_nick(binary(), binary(), jid(), binary()) -> boolean(). -callback get_rooms(binary(), binary()) -> [#muc_room{}]. @@ -591,20 +591,17 @@ extract_password(#iq{} = IQ) -> false end. --spec unhibernate_room(binary(), binary(), binary()) -> {ok, pid()} | error. +-spec unhibernate_room(binary(), binary(), binary()) -> {ok, pid()} | {error, notfound | db_failure | term()}. unhibernate_room(ServerHost, Host, Room) -> unhibernate_room(ServerHost, Host, Room, true). --spec unhibernate_room(binary(), binary(), binary(), boolean()) -> {ok, pid()} | error. +-spec unhibernate_room(binary(), binary(), binary(), boolean()) -> {ok, pid()} | {error, notfound | db_failure | term()}. unhibernate_room(ServerHost, Host, Room, ResetHibernationTime) -> RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE), case RMod:find_online_room(ServerHost, Room, Host) of error -> Proc = procname(ServerHost, {Room, Host}), - case ?GEN_SERVER:call(Proc, {unhibernate, Room, Host, ResetHibernationTime}, 20000) of - {ok, _} = R -> R; - _ -> error - end; + ?GEN_SERVER:call(Proc, {unhibernate, Room, Host, ResetHibernationTime}, 20000); {ok, _} = R2 -> R2 end. @@ -888,6 +885,8 @@ load_room(RMod, Host, ServerHost, Room, ResetHibernationTime) -> case restore_room(ServerHost, Host, Room) of error -> {error, notfound}; + {error, _} = Err -> + Err; Opts0 -> Mod = gen_mod:db_mod(ServerHost, mod_muc), case proplists:get_bool(persistent, Opts0) of diff --git a/src/mod_muc_admin.erl b/src/mod_muc_admin.erl index 77b46b275..9a8ab60b1 100644 --- a/src/mod_muc_admin.erl +++ b/src/mod_muc_admin.erl @@ -1289,6 +1289,8 @@ create_room_with_opts(Name1, Host1, ServerHost1, CustomRoomOpts) -> {error, _} -> throw({error, "Unable to start room"}) end; + {db_failure, _Name, _Host} -> + throw({error, "Database error"}); _ -> throw({error, "Room already exists"}) end. @@ -1307,6 +1309,8 @@ destroy_room(Name1, Service1) -> case get_room_pid_validate(Name1, Service1, <<"service">>) of {room_not_found, _, _} -> throw({error, "Room doesn't exists"}); + {db_failure, _Name, _Host} -> + throw({error, "Database error"}); {Pid, _, _} -> mod_muc_room:destroy(Pid), ok @@ -1698,6 +1702,8 @@ change_room_option(Name, Service, OptionString, ValueString) -> case get_room_pid_validate(Name, Service, <<"service">>) of {room_not_found, _, _} -> throw({error, "Room not found"}); + {db_failure, _Name, _Host} -> + throw({error, "Database error"}); {Pid, _, _} -> {Option, Value} = format_room_option(OptionString, ValueString), change_room_option(Pid, Option, Value) @@ -1823,25 +1829,29 @@ parse_nodes(_, _) -> throw({error, "Invalid 'subscribers' - unknown node name used"}). -spec get_room_pid_validate(binary(), binary(), binary()) -> - {pid() | room_not_found, binary(), binary()}. + {pid() | room_not_found | db_failure, binary(), binary()}. get_room_pid_validate(Name, Service, ServiceArg) -> Name2 = validate_room(Name), {ServerHost, Service2} = validate_muc2(Service, ServiceArg), case mod_muc:unhibernate_room(ServerHost, Service2, Name2) of - error -> + {error, notfound} -> {room_not_found, Name2, Service2}; + {error, db_failure} -> + {db_failure, Name2, Service2}; {ok, Pid} -> {Pid, Name2, Service2} end. %% @doc Get the Pid of an existing MUC room, or 'room_not_found'. --spec get_room_pid(binary(), binary()) -> pid() | room_not_found | invalid_service | unknown_service. +-spec get_room_pid(binary(), binary()) -> pid() | room_not_found | db_failure | invalid_service | unknown_service. get_room_pid(Name, Service) -> try get_room_serverhost(Service) of ServerHost -> case mod_muc:unhibernate_room(ServerHost, Service, Name) of - error -> + {error, notfound} -> room_not_found; + {error, db_failure} -> + db_failure; {ok, Pid} -> Pid end @@ -1954,6 +1964,8 @@ get_room_affiliations(Name, Service) -> ({{Uname, Domain, _Res}, Aff}) when is_atom(Aff)-> {Uname, Domain, Aff, <<>>} end, Affiliations); + {db_failure, _Name, _Host} -> + throw({error, "Database error"}); _ -> throw({error, "The room does not exist."}) end. @@ -1975,6 +1987,8 @@ get_room_affiliations_v3(Name, Service) -> Jid = makeencode(Uname, Domain), {Jid, Aff, <<>>} end, Affiliations); + {db_failure, _Name, _Host} -> + throw({error, "Database error"}); _ -> throw({error, "The room does not exist."}) end. @@ -1993,6 +2007,8 @@ get_room_history(Name, Service) -> _ -> throw({error, "Unable to fetch room state."}) end; + {db_failure, _Name, _Host} -> + throw({error, "Database error"}); _ -> throw({error, "The room does not exist."}) end. @@ -2012,6 +2028,8 @@ get_room_affiliation(Name, Service, JID) -> {ok, StateData} = mod_muc_room:get_state(Pid), UserJID = jid:decode(JID), mod_muc_room:get_affiliation(UserJID, StateData); + {db_failure, _Name, _Host} -> + throw({error, "Database error"}); _ -> throw({error, "The room does not exist."}) end. @@ -2052,6 +2070,8 @@ set_room_affiliation(Name, Service, JID, AffiliationString) -> {error, _} -> throw({error, "Unable to perform change"}) end; + {db_failure, _Name, _Host} -> + throw({error, "Database error"}); _ -> throw({error, "Room doesn't exists"}) end. @@ -2084,6 +2104,8 @@ subscribe_room(User, Nick, Room, NodeList) -> {error, Reason} -> throw({error, binary_to_list(Reason)}) end; + {db_failure, _Name, _Host} -> + throw({error, "Database error"}); _ -> throw({error, "The room does not exist"}) end @@ -2129,6 +2151,8 @@ unsubscribe_room(User, Room) -> {error, Reason} -> throw({error, binary_to_list(Reason)}) end; + {db_failure, _Name, _Host} -> + throw({error, "Database error"}); _ -> throw({error, "The room does not exist"}) end @@ -2146,6 +2170,8 @@ get_subscribers(Name, Host) -> {Pid, _, _} when is_pid(Pid) -> {ok, JIDList} = mod_muc_room:get_subscribers(Pid), [jid:encode(jid:remove_resource(J)) || J <- JIDList]; + {db_failure, _Name, _Host} -> + throw({error, "Database error"}); _ -> throw({error, "The room does not exist"}) end. diff --git a/src/mod_muc_sql.erl b/src/mod_muc_sql.erl index b6cff55d1..f99325f87 100644 --- a/src/mod_muc_sql.erl +++ b/src/mod_muc_sql.erl @@ -220,10 +220,12 @@ restore_room(LServer, Host, Name) -> Opts2 = lists:keystore(subscribers, 1, OptsD, {subscribers, SubData}), mod_muc:opts_to_binary(Opts2); _ -> - error + {error, db_failure} end; + {selected, _} -> + error; _ -> - error + {error, db_failure} end. forget_room(LServer, Host, Name) -> From 1a9b147baf76ce6f7f216c49bd74312f24b41f5d Mon Sep 17 00:00:00 2001 From: Pawel Chmielowski Date: Wed, 23 Jul 2025 20:20:51 +0200 Subject: [PATCH 2/2] Report db failures in mod_muc_mnesia:restore_room --- src/mod_muc_mnesia.erl | 4 +++- src/mod_muc_sql.erl | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mod_muc_mnesia.erl b/src/mod_muc_mnesia.erl index 9e16a56c5..65c37a7ab 100644 --- a/src/mod_muc_mnesia.erl +++ b/src/mod_muc_mnesia.erl @@ -76,9 +76,11 @@ store_room(_LServer, Host, Name, Opts, _) -> mnesia:transaction(F). restore_room(_LServer, Host, Name) -> - case catch mnesia:dirty_read(muc_room, {Name, Host}) of + try mnesia:dirty_read(muc_room, {Name, Host}) of [#muc_room{opts = Opts}] -> Opts; _ -> error + catch + _:_ -> {error, db_failure} end. forget_room(_LServer, Host, Name) -> diff --git a/src/mod_muc_sql.erl b/src/mod_muc_sql.erl index f99325f87..31c8703c1 100644 --- a/src/mod_muc_sql.erl +++ b/src/mod_muc_sql.erl @@ -220,7 +220,7 @@ restore_room(LServer, Host, Name) -> Opts2 = lists:keystore(subscribers, 1, OptsD, {subscribers, SubData}), mod_muc:opts_to_binary(Opts2); _ -> - {error, db_failure} + {error, db_failure} end; {selected, _} -> error;