From ea9958c59143b3514afc763b1f5adb96411daca4 Mon Sep 17 00:00:00 2001 From: Mikhail Uvarov Date: Sat, 7 Oct 2023 00:03:01 +0200 Subject: [PATCH 1/4] Return internal-server-error IQ instead of an empty result set In case there is an error when querying Currently debugging case when one message in archive is encoded by other format (i.e. expected XML, but gets erlang term) --- big_tests/tests/mam_SUITE.erl | 77 +++++++++++++++++++++++------- src/mam/mod_mam_muc_rdbms_arch.erl | 6 ++- src/mam/mod_mam_rdbms_arch.erl | 6 ++- 3 files changed, 71 insertions(+), 18 deletions(-) diff --git a/big_tests/tests/mam_SUITE.erl b/big_tests/tests/mam_SUITE.erl index 078a8408179..ce0ffaa35af 100644 --- a/big_tests/tests/mam_SUITE.erl +++ b/big_tests/tests/mam_SUITE.erl @@ -115,6 +115,8 @@ muc_light_stored_in_pm_if_allowed_to/1, muc_light_chat_markers_are_archived_if_enabled/1, muc_light_chat_markers_are_not_archived_if_disabled/1, + muc_light_failed_to_decode_message_in_database/1, + pm_failed_to_decode_message_in_database/1, messages_filtered_when_prefs_default_policy_is_always/1, messages_filtered_when_prefs_default_policy_is_never/1, messages_filtered_when_prefs_default_policy_is_roster/1, @@ -478,7 +480,8 @@ muc_light_cases() -> muc_light_shouldnt_modify_pm_archive, muc_light_stored_in_pm_if_allowed_to, muc_light_chat_markers_are_archived_if_enabled, - muc_light_chat_markers_are_not_archived_if_disabled + muc_light_chat_markers_are_not_archived_if_disabled, + muc_light_failed_to_decode_message_in_database ]. muc_rsm_cases() -> @@ -538,7 +541,8 @@ prefs_cases() -> run_set_and_get_prefs_cases]. impl_specific() -> - [check_user_exist]. + [check_user_exist, + pm_failed_to_decode_message_in_database]. suite() -> require_rpc_nodes([mim]) ++ escalus:suite(). @@ -835,6 +839,12 @@ init_per_testcase(C=same_stanza_id, Config) -> init_per_testcase(C=muc_message_with_stanzaid, Config) -> Config1 = escalus_fresh:create_users(Config, [{alice, 1}, {bob, 1}]), escalus:init_per_testcase(C, start_alice_room(Config1)); +init_per_testcase(C=muc_light_failed_to_decode_message_in_database, Config) -> + dynamic_modules:ensure_modules(host_type(), required_modules(C, Config)), + escalus:init_per_testcase(C, Config); +init_per_testcase(C=pm_failed_to_decode_message_in_database, Config) -> + dynamic_modules:ensure_modules(host_type(), required_modules(C, Config)), + escalus:init_per_testcase(C, Config); init_per_testcase(C, Config) when C =:= retract_muc_message; C =:= retract_muc_message_on_stanza_id; C =:= retract_wrong_muc_message -> @@ -969,20 +979,6 @@ end_per_testcase(C=muc_no_elements, Config) -> end_per_testcase(C=muc_only_stanzaid, Config) -> destroy_room(Config), escalus:end_per_testcase(C, Config); -end_per_testcase(C = muc_light_stored_in_pm_if_allowed_to, Config) -> - escalus:end_per_testcase(C, Config); -end_per_testcase(C = retract_message_on_stanza_id, Config) -> - escalus:end_per_testcase(C, Config); -end_per_testcase(C = muc_light_chat_markers_are_archived_if_enabled, Config) -> - escalus:end_per_testcase(C, Config); -end_per_testcase(C = muc_light_chat_markers_are_not_archived_if_disabled, Config) -> - escalus:end_per_testcase(C, Config); -end_per_testcase(C = no_elements, Config) -> - escalus:end_per_testcase(C, Config); -end_per_testcase(C = only_stanzaid, Config) -> - escalus:end_per_testcase(C, Config); -end_per_testcase(C = same_stanza_id, Config) -> - escalus:end_per_testcase(C, Config); end_per_testcase(CaseName, Config) -> escalus:end_per_testcase(CaseName, Config). @@ -1000,6 +996,26 @@ required_modules(muc_no_elements, Config) -> Opts = #{muc := MUC} = ?config(mam_meta_opts, Config), NewOpts = Opts#{muc := MUC#{no_stanzaid_element => true}}, [{mod_mam, NewOpts}]; +required_modules(muc_light_failed_to_decode_message_in_database, Config) -> + Opts = #{muc := MUC} = ?config(mam_meta_opts, Config), + NewOpts = Opts#{muc := MUC#{db_message_format => mam_message_eterm}}, + [{mod_mam, NewOpts}]; +required_modules(muc_light_failed_to_decode_message_in_database2, Config) -> + %% We apply this preset in the middle of + %% muc_light_failed_to_decode_message_in_database test + Opts = #{muc := MUC} = ?config(mam_meta_opts, Config), + NewOpts = Opts#{muc := MUC#{db_message_format => mam_message_xml}}, + [{mod_mam, NewOpts}]; +required_modules(pm_failed_to_decode_message_in_database, Config) -> + Opts = #{pm := PM} = ?config(mam_meta_opts, Config), + NewOpts = Opts#{pm := PM#{db_message_format => mam_message_eterm}}, + [{mod_mam, NewOpts}]; +required_modules(pm_failed_to_decode_message_in_database2, Config) -> + %% We apply this preset in the middle of + %% pm_failed_to_decode_message_in_database test + Opts = #{pm := PM} = ?config(mam_meta_opts, Config), + NewOpts = Opts#{pm := PM#{db_message_format => mam_message_xml}}, + [{mod_mam, NewOpts}]; required_modules(muc_only_stanzaid, Config) -> Opts = ?config(mam_meta_opts, Config), [{mod_mam, Opts}]; @@ -1691,6 +1707,35 @@ muc_light_chat_markers_are_not_archived_if_disabled(Config) -> then_archive_response_is(Bob, ExpectedResponse, Config) end). +muc_light_failed_to_decode_message_in_database(Config) -> + escalus:story(Config, [{alice, 1}], fun(Alice) -> + Room = muc_helper:fresh_room_name(), + given_muc_light_room(Room, Alice, []), + + M1 = when_muc_light_message_is_sent(Alice, Room, + <<"Msg 1">>, <<"Id1">>), + then_muc_light_message_is_received_by([Alice], M1), + mam_helper:wait_for_room_archive_size(muc_light_host(), Room, 2), + NewMods = required_modules(muc_light_failed_to_decode_message_in_database2, Config), + %% Change the encoding format for messages in the database + dynamic_modules:ensure_modules(host_type(), NewMods), + when_archive_query_is_sent(Alice, muc_light_helper:room_bin_jid(Room), Config), + Err = escalus:wait_for_stanza(Alice), + escalus_assert:is_error(Err, <<"wait">>, <<"internal-server-error">>) + end). + +pm_failed_to_decode_message_in_database(Config) -> + escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> + escalus:send(Alice, escalus_stanza:chat_to(Bob, <<"Hi">>)), + mam_helper:wait_for_archive_size(Alice, 1), + NewMods = required_modules(pm_failed_to_decode_message_in_database2, Config), + %% Change the encoding format for messages in the database + dynamic_modules:ensure_modules(host_type(), NewMods), + when_archive_query_is_sent(Alice, undefined, Config), + Err = escalus:wait_for_stanza(Alice), + escalus_assert:is_error(Err, <<"wait">>, <<"internal-server-error">>) + end). + retrieve_form_fields(ConfigIn) -> escalus_fresh:story(ConfigIn, [{alice, 1}], fun(Alice) -> P = ?config(props, ConfigIn), diff --git a/src/mam/mod_mam_muc_rdbms_arch.erl b/src/mam/mod_mam_muc_rdbms_arch.erl index cbe905940ef..335b41f3b58 100644 --- a/src/mam/mod_mam_muc_rdbms_arch.erl +++ b/src/mam/mod_mam_muc_rdbms_arch.erl @@ -384,7 +384,11 @@ lookup_messages(_Result, #{owner_jid := ArcJID} = Params, #{host_type := HostTyp Env = env_vars(HostType, ArcJID), ExdParams = mam_encoder:extend_lookup_params(Params, Env), Filter = mam_filter:produce_filter(ExdParams, lookup_fields()), - {ok, mam_lookup:lookup(Env, Filter, ExdParams)}. + try + {ok, mam_lookup:lookup(Env, Filter, ExdParams)} + catch error:Reason:Stacktrace -> + {error, {Reason, {stacktrace, Stacktrace}}} + end. lookup_query(QueryType, Env, Filters, Order, OffsetLimit) -> mam_lookup_sql:lookup_query(QueryType, Env, Filters, Order, OffsetLimit). diff --git a/src/mam/mod_mam_rdbms_arch.erl b/src/mam/mod_mam_rdbms_arch.erl index c77b404959e..c3fbd1fffcf 100644 --- a/src/mam/mod_mam_rdbms_arch.erl +++ b/src/mam/mod_mam_rdbms_arch.erl @@ -405,7 +405,11 @@ lookup_messages(_Result, #{owner_jid := ArcJID} = Params, #{host_type := HostTyp Env = env_vars(HostType, ArcJID), ExdParams = mam_encoder:extend_lookup_params(Params, Env), Filter = mam_filter:produce_filter(ExdParams, lookup_fields()), - {ok, mam_lookup:lookup(Env, Filter, ExdParams)}. + try + {ok, mam_lookup:lookup(Env, Filter, ExdParams)} + catch error:Reason:Stacktrace -> + {error, {Reason, {stacktrace, Stacktrace}}} + end. lookup_query(QueryType, Env, Filters, Order, OffsetLimit) -> mam_lookup_sql:lookup_query(QueryType, Env, Filters, Order, OffsetLimit). From 4d1bf14626c7ade7d81518d210a08a0b9a35f543 Mon Sep 17 00:00:00 2001 From: Mikhail Uvarov Date: Sat, 7 Oct 2023 17:56:06 +0200 Subject: [PATCH 2/4] Disable pm_failed_to_decode_message_in_database for elastic --- big_tests/tests/mam_SUITE.erl | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/big_tests/tests/mam_SUITE.erl b/big_tests/tests/mam_SUITE.erl index ce0ffaa35af..99e67a774f4 100644 --- a/big_tests/tests/mam_SUITE.erl +++ b/big_tests/tests/mam_SUITE.erl @@ -840,11 +840,21 @@ init_per_testcase(C=muc_message_with_stanzaid, Config) -> Config1 = escalus_fresh:create_users(Config, [{alice, 1}, {bob, 1}]), escalus:init_per_testcase(C, start_alice_room(Config1)); init_per_testcase(C=muc_light_failed_to_decode_message_in_database, Config) -> - dynamic_modules:ensure_modules(host_type(), required_modules(C, Config)), - escalus:init_per_testcase(C, Config); + case proplists:get_value(configuration, Config) of + elasticsearch -> + {skip, "elasticsearch does not support encodings"}; + _ -> + dynamic_modules:ensure_modules(host_type(), required_modules(C, Config)), + escalus:init_per_testcase(C, Config) + end; init_per_testcase(C=pm_failed_to_decode_message_in_database, Config) -> - dynamic_modules:ensure_modules(host_type(), required_modules(C, Config)), - escalus:init_per_testcase(C, Config); + case proplists:get_value(configuration, Config) of + elasticsearch -> + {skip, "elasticsearch does not support encodings"}; + _ -> + dynamic_modules:ensure_modules(host_type(), required_modules(C, Config)), + escalus:init_per_testcase(C, Config) + end; init_per_testcase(C, Config) when C =:= retract_muc_message; C =:= retract_muc_message_on_stanza_id; C =:= retract_wrong_muc_message -> From f274d4dcb963d1a6379d4858e62a0a6067ce40fb Mon Sep 17 00:00:00 2001 From: Mikhail Uvarov Date: Tue, 12 Dec 2023 18:22:35 +0100 Subject: [PATCH 3/4] Return an error for each decoded message separately --- big_tests/tests/mam_SUITE.erl | 59 ++++++++++++++++-------------- src/mam/mam_decoder.erl | 20 +++++++++- src/mam/mod_mam_muc_rdbms_arch.erl | 8 +--- src/mam/mod_mam_rdbms_arch.erl | 8 +--- 4 files changed, 52 insertions(+), 43 deletions(-) diff --git a/big_tests/tests/mam_SUITE.erl b/big_tests/tests/mam_SUITE.erl index 99e67a774f4..cea723c11ac 100644 --- a/big_tests/tests/mam_SUITE.erl +++ b/big_tests/tests/mam_SUITE.erl @@ -225,6 +225,7 @@ -include("mam_helper.hrl"). -include_lib("common_test/include/ct.hrl"). +-include_lib("eunit/include/eunit.hrl"). -include_lib("exml/include/exml_stream.hrl"). %%-------------------------------------------------------------------- @@ -839,15 +840,8 @@ init_per_testcase(C=same_stanza_id, Config) -> init_per_testcase(C=muc_message_with_stanzaid, Config) -> Config1 = escalus_fresh:create_users(Config, [{alice, 1}, {bob, 1}]), escalus:init_per_testcase(C, start_alice_room(Config1)); -init_per_testcase(C=muc_light_failed_to_decode_message_in_database, Config) -> - case proplists:get_value(configuration, Config) of - elasticsearch -> - {skip, "elasticsearch does not support encodings"}; - _ -> - dynamic_modules:ensure_modules(host_type(), required_modules(C, Config)), - escalus:init_per_testcase(C, Config) - end; -init_per_testcase(C=pm_failed_to_decode_message_in_database, Config) -> +init_per_testcase(C, Config) when C =:= muc_light_failed_to_decode_message_in_database; + C =:= pm_failed_to_decode_message_in_database -> case proplists:get_value(configuration, Config) of elasticsearch -> {skip, "elasticsearch does not support encodings"}; @@ -1010,22 +1004,10 @@ required_modules(muc_light_failed_to_decode_message_in_database, Config) -> Opts = #{muc := MUC} = ?config(mam_meta_opts, Config), NewOpts = Opts#{muc := MUC#{db_message_format => mam_message_eterm}}, [{mod_mam, NewOpts}]; -required_modules(muc_light_failed_to_decode_message_in_database2, Config) -> - %% We apply this preset in the middle of - %% muc_light_failed_to_decode_message_in_database test - Opts = #{muc := MUC} = ?config(mam_meta_opts, Config), - NewOpts = Opts#{muc := MUC#{db_message_format => mam_message_xml}}, - [{mod_mam, NewOpts}]; required_modules(pm_failed_to_decode_message_in_database, Config) -> Opts = #{pm := PM} = ?config(mam_meta_opts, Config), NewOpts = Opts#{pm := PM#{db_message_format => mam_message_eterm}}, [{mod_mam, NewOpts}]; -required_modules(pm_failed_to_decode_message_in_database2, Config) -> - %% We apply this preset in the middle of - %% pm_failed_to_decode_message_in_database test - Opts = #{pm := PM} = ?config(mam_meta_opts, Config), - NewOpts = Opts#{pm := PM#{db_message_format => mam_message_xml}}, - [{mod_mam, NewOpts}]; required_modules(muc_only_stanzaid, Config) -> Opts = ?config(mam_meta_opts, Config), [{mod_mam, Opts}]; @@ -1043,6 +1025,16 @@ required_modules(_, Config) -> Opts = ?config(mam_meta_opts, Config), [{mod_mam, Opts}]. +pm_with_db_message_format_xml(Config) -> + Opts = #{pm := PM} = ?config(mam_meta_opts, Config), + NewOpts = Opts#{pm := PM#{db_message_format => mam_message_xml}}, + [{mod_mam, NewOpts}]. + +muc_with_db_message_format_xml(Config) -> + Opts = #{muc := MUC} = ?config(mam_meta_opts, Config), + NewOpts = Opts#{muc := MUC#{db_message_format => mam_message_xml}}, + [{mod_mam, NewOpts}]. + %%-------------------------------------------------------------------- %% Group name helpers %%-------------------------------------------------------------------- @@ -1721,29 +1713,28 @@ muc_light_failed_to_decode_message_in_database(Config) -> escalus:story(Config, [{alice, 1}], fun(Alice) -> Room = muc_helper:fresh_room_name(), given_muc_light_room(Room, Alice, []), - M1 = when_muc_light_message_is_sent(Alice, Room, <<"Msg 1">>, <<"Id1">>), then_muc_light_message_is_received_by([Alice], M1), mam_helper:wait_for_room_archive_size(muc_light_host(), Room, 2), - NewMods = required_modules(muc_light_failed_to_decode_message_in_database2, Config), + NewMods = muc_with_db_message_format_xml(Config), %% Change the encoding format for messages in the database dynamic_modules:ensure_modules(host_type(), NewMods), when_archive_query_is_sent(Alice, muc_light_helper:room_bin_jid(Room), Config), - Err = escalus:wait_for_stanza(Alice), - escalus_assert:is_error(Err, <<"wait">>, <<"internal-server-error">>) + [ArcMsg | _] = respond_messages(assert_respond_size(2, wait_archive_respond(Alice))), + assert_failed_to_decode_message(ArcMsg) end). pm_failed_to_decode_message_in_database(Config) -> escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> escalus:send(Alice, escalus_stanza:chat_to(Bob, <<"Hi">>)), mam_helper:wait_for_archive_size(Alice, 1), - NewMods = required_modules(pm_failed_to_decode_message_in_database2, Config), + NewMods = pm_with_db_message_format_xml(Config), %% Change the encoding format for messages in the database dynamic_modules:ensure_modules(host_type(), NewMods), when_archive_query_is_sent(Alice, undefined, Config), - Err = escalus:wait_for_stanza(Alice), - escalus_assert:is_error(Err, <<"wait">>, <<"internal-server-error">>) + [ArcMsg] = respond_messages(assert_respond_size(1, wait_archive_respond(Alice))), + assert_failed_to_decode_message(ArcMsg) end). retrieve_form_fields(ConfigIn) -> @@ -3228,3 +3219,15 @@ pagination_test(Name, RSM, Range, Config) -> wait_message_range(Alice, Range) end, parallel_story(Config, [{alice, 1}], F). + +assert_failed_to_decode_message(ArcMsg) -> + Forwarded = parse_forwarded_message(ArcMsg), + Err = <<"Failed to decode message in database">>, + ?assertMatch(#forwarded_message{message_body = Err}, Forwarded), + ?assertMatch(#forwarded_message{message_type = <<"error">>}, Forwarded), + #forwarded_message{message_children = [Msg]} = Forwarded, + ?assertMatch(#xmlel{ + name = <<"error">>, + attrs = [{<<"code">>, <<"500">>}, {<<"type">>,<<"wait">>}], + children = [#xmlel{name = <<"internal-server-error">>}, + #xmlel{name = <<"text">>, children = [#xmlcdata{content = Err}]}]}, Msg). diff --git a/src/mam/mam_decoder.erl b/src/mam/mam_decoder.erl index 147a46ec935..28b893221d1 100644 --- a/src/mam/mam_decoder.erl +++ b/src/mam/mam_decoder.erl @@ -4,6 +4,9 @@ -export([decode_muc_gdpr_row/2]). -export([decode_retraction_info/3]). +-include_lib("kernel/include/logger.hrl"). +-include_lib("exml/include/exml.hrl"). + -type ext_mess_id() :: non_neg_integer() | binary(). -type env_vars() :: mod_mam_rdbms_arch:env_vars(). -type db_row() :: {ext_mess_id(), ExtSrcJID :: binary(), ExtData :: binary()}. @@ -51,8 +54,23 @@ decode_jid(ExtJID, #{db_jid_codec := Codec, archive_jid := ArcJID}) -> -spec decode_packet(binary(), env_vars()) -> exml:element(). decode_packet(ExtBin, Env = #{db_message_codec := Codec}) -> Bin = unescape_binary(ExtBin, Env), - mam_message:decode(Codec, Bin). + try + mam_message:decode(Codec, Bin) + catch Class:Reason:Stacktrace -> + ?LOG_ERROR(#{what => mam_failed_to_decode_message, + encoded_message => ExtBin, + class => Class, reason => Reason, stacktrace => Stacktrace}), + error_stanza() + end. -spec unescape_binary(binary(), env_vars()) -> binary(). unescape_binary(Bin, #{host_type := HostType}) -> mongoose_rdbms:unescape_binary(HostType, Bin). + +error_stanza() -> + Text = <<"Failed to decode message in database">>, + Err = mongoose_xmpp_errors:internal_server_error(<<"en">>, Text), + Body = #xmlel{name = <<"body">>, children = [#xmlcdata{content = Text}]}, + #xmlel{name = <<"message">>, + attrs = [{<<"type">>, <<"error">>}], + children = [Err, Body]}. diff --git a/src/mam/mod_mam_muc_rdbms_arch.erl b/src/mam/mod_mam_muc_rdbms_arch.erl index 335b41f3b58..02829c92743 100644 --- a/src/mam/mod_mam_muc_rdbms_arch.erl +++ b/src/mam/mod_mam_muc_rdbms_arch.erl @@ -378,17 +378,11 @@ extract_gdpr_messages(HostType, SenderID) -> Acc :: {ok, mod_mam:lookup_result()}, Params :: mam_iq:lookup_params(), Extra :: gen_hook:extra(). -lookup_messages({error, _Reason} = Result, _Params, _Extra) -> - {ok, Result}; lookup_messages(_Result, #{owner_jid := ArcJID} = Params, #{host_type := HostType}) -> Env = env_vars(HostType, ArcJID), ExdParams = mam_encoder:extend_lookup_params(Params, Env), Filter = mam_filter:produce_filter(ExdParams, lookup_fields()), - try - {ok, mam_lookup:lookup(Env, Filter, ExdParams)} - catch error:Reason:Stacktrace -> - {error, {Reason, {stacktrace, Stacktrace}}} - end. + {ok, mam_lookup:lookup(Env, Filter, ExdParams)}. lookup_query(QueryType, Env, Filters, Order, OffsetLimit) -> mam_lookup_sql:lookup_query(QueryType, Env, Filters, Order, OffsetLimit). diff --git a/src/mam/mod_mam_rdbms_arch.erl b/src/mam/mod_mam_rdbms_arch.erl index c3fbd1fffcf..94670d370fd 100644 --- a/src/mam/mod_mam_rdbms_arch.erl +++ b/src/mam/mod_mam_rdbms_arch.erl @@ -399,17 +399,11 @@ extract_gdpr_messages(Env, ArcID) -> Acc :: {ok, mod_mam:lookup_result()}, Params :: mam_iq:lookup_params(), Extra :: gen_hook:extra(). -lookup_messages({error, _Reason} = Result, _Params, _Extra) -> - {ok, Result}; lookup_messages(_Result, #{owner_jid := ArcJID} = Params, #{host_type := HostType}) -> Env = env_vars(HostType, ArcJID), ExdParams = mam_encoder:extend_lookup_params(Params, Env), Filter = mam_filter:produce_filter(ExdParams, lookup_fields()), - try - {ok, mam_lookup:lookup(Env, Filter, ExdParams)} - catch error:Reason:Stacktrace -> - {error, {Reason, {stacktrace, Stacktrace}}} - end. + {ok, mam_lookup:lookup(Env, Filter, ExdParams)}. lookup_query(QueryType, Env, Filters, Order, OffsetLimit) -> mam_lookup_sql:lookup_query(QueryType, Env, Filters, Order, OffsetLimit). From 87d01acbc290aeda34910804c1e8b77d5dbc5159 Mon Sep 17 00:00:00 2001 From: Mikhail Uvarov Date: Tue, 12 Dec 2023 19:21:51 +0100 Subject: [PATCH 4/4] Make fix work with cassandra Move fix into mam_message module --- src/mam/mam_decoder.erl | 20 +------------------- src/mam/mam_message.erl | 20 +++++++++++++++++++- src/mam/mod_mam_cassandra_arch.erl | 4 ++-- src/mam/mod_mam_muc_cassandra_arch.erl | 4 ++-- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/mam/mam_decoder.erl b/src/mam/mam_decoder.erl index 28b893221d1..147a46ec935 100644 --- a/src/mam/mam_decoder.erl +++ b/src/mam/mam_decoder.erl @@ -4,9 +4,6 @@ -export([decode_muc_gdpr_row/2]). -export([decode_retraction_info/3]). --include_lib("kernel/include/logger.hrl"). --include_lib("exml/include/exml.hrl"). - -type ext_mess_id() :: non_neg_integer() | binary(). -type env_vars() :: mod_mam_rdbms_arch:env_vars(). -type db_row() :: {ext_mess_id(), ExtSrcJID :: binary(), ExtData :: binary()}. @@ -54,23 +51,8 @@ decode_jid(ExtJID, #{db_jid_codec := Codec, archive_jid := ArcJID}) -> -spec decode_packet(binary(), env_vars()) -> exml:element(). decode_packet(ExtBin, Env = #{db_message_codec := Codec}) -> Bin = unescape_binary(ExtBin, Env), - try - mam_message:decode(Codec, Bin) - catch Class:Reason:Stacktrace -> - ?LOG_ERROR(#{what => mam_failed_to_decode_message, - encoded_message => ExtBin, - class => Class, reason => Reason, stacktrace => Stacktrace}), - error_stanza() - end. + mam_message:decode(Codec, Bin). -spec unescape_binary(binary(), env_vars()) -> binary(). unescape_binary(Bin, #{host_type := HostType}) -> mongoose_rdbms:unescape_binary(HostType, Bin). - -error_stanza() -> - Text = <<"Failed to decode message in database">>, - Err = mongoose_xmpp_errors:internal_server_error(<<"en">>, Text), - Body = #xmlel{name = <<"body">>, children = [#xmlcdata{content = Text}]}, - #xmlel{name = <<"message">>, - attrs = [{<<"type">>, <<"error">>}], - children = [Err, Body]}. diff --git a/src/mam/mam_message.erl b/src/mam/mam_message.erl index f519c990ba8..befb84e625a 100644 --- a/src/mam/mam_message.erl +++ b/src/mam/mam_message.erl @@ -13,9 +13,27 @@ -export([encode/2, decode/2]). +-include_lib("kernel/include/logger.hrl"). +-include_lib("exml/include/exml.hrl"). + -spec encode(module(), exml:element()) -> binary(). encode(Mod, Packet) -> Mod:encode(Packet). -spec decode(module(), binary()) -> exml:element(). -decode(Mod, Bin) -> Mod:decode(Bin). +decode(Mod, Bin) -> + try + Mod:decode(Bin) + catch Class:Reason:Stacktrace -> + ?LOG_ERROR(#{what => mam_failed_to_decode_message, + encoded_message => Bin, + class => Class, reason => Reason, stacktrace => Stacktrace}), + error_stanza() + end. +error_stanza() -> + Text = <<"Failed to decode message in database">>, + Err = mongoose_xmpp_errors:internal_server_error(<<"en">>, Text), + Body = #xmlel{name = <<"body">>, children = [#xmlcdata{content = Text}]}, + #xmlel{name = <<"message">>, + attrs = [{<<"type">>, <<"error">>}], + children = [Err, Body]}. diff --git a/src/mam/mod_mam_cassandra_arch.erl b/src/mam/mod_mam_cassandra_arch.erl index c1f35752255..9acf29ae83a 100644 --- a/src/mam/mod_mam_cassandra_arch.erl +++ b/src/mam/mod_mam_cassandra_arch.erl @@ -739,12 +739,12 @@ fetch_user_messages_cql() -> packet_to_stored_binary(HostType, Packet) -> %% Module implementing mam_message behaviour Module = db_message_format(HostType), - Module:encode(Packet). + mam_message:encode(Module, Packet). stored_binary_to_packet(HostType, Bin) -> %% Module implementing mam_message behaviour Module = db_message_format(HostType), - Module:decode(Bin). + mam_message:decode(Module, Bin). %% ---------------------------------------------------------------------- %% Params getters diff --git a/src/mam/mod_mam_muc_cassandra_arch.erl b/src/mam/mod_mam_muc_cassandra_arch.erl index 2dda8308a3c..9e7aba451c7 100644 --- a/src/mam/mod_mam_muc_cassandra_arch.erl +++ b/src/mam/mod_mam_muc_cassandra_arch.erl @@ -757,12 +757,12 @@ list_message_ids_cql(Filter) -> packet_to_stored_binary(HostType, Packet) -> %% Module implementing mam_muc_message behaviour Module = db_message_format(HostType), - Module:encode(Packet). + mam_message:encode(Module, Packet). stored_binary_to_packet(HostType, Bin) -> %% Module implementing mam_muc_message behaviour Module = db_message_format(HostType), - Module:decode(Bin). + mam_message:decode(Module, Bin). %% ---------------------------------------------------------------------- %% Params getters