fix: bug found by dialyzer and make test case cleaner
This commit is contained in:
parent
572ca6433e
commit
336089f8a7
|
@ -715,17 +715,39 @@ t_missing_table(Config) ->
|
||||||
connect_and_create_table(Config),
|
connect_and_create_table(Config),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
%% We test that we can handle when the prepared statement with the channel
|
||||||
|
%% name already exists in the connection instance when we try to make a new
|
||||||
|
%% prepared statement. It is unknown in which scenario this can happen but it
|
||||||
|
%% has been observed in a production log file.
|
||||||
|
%% See:
|
||||||
|
%% https://emqx.atlassian.net/browse/EEC-1036
|
||||||
t_prepared_statement_exists(Config) ->
|
t_prepared_statement_exists(Config) ->
|
||||||
Name = ?config(pgsql_name, Config),
|
Name = ?config(pgsql_name, Config),
|
||||||
BridgeType = ?config(pgsql_bridge_type, Config),
|
BridgeType = ?config(pgsql_bridge_type, Config),
|
||||||
|
emqx_common_test_helpers:on_exit(fun() ->
|
||||||
|
meck:unload()
|
||||||
|
end),
|
||||||
|
MeckOpts = [passthrough, no_link, no_history, non_strict],
|
||||||
|
meck:new(emqx_postgresql, MeckOpts),
|
||||||
|
InsertPrepStatementDupAndThenRemoveMeck =
|
||||||
|
fun(Conn, Key, SQL, List) ->
|
||||||
|
meck:passthrough([Conn, Key, SQL, List]),
|
||||||
|
meck:delete(
|
||||||
|
epgsql,
|
||||||
|
parse2,
|
||||||
|
4
|
||||||
|
),
|
||||||
|
meck:passthrough([Conn, Key, SQL, List])
|
||||||
|
end,
|
||||||
|
meck:expect(
|
||||||
|
epgsql,
|
||||||
|
parse2,
|
||||||
|
InsertPrepStatementDupAndThenRemoveMeck
|
||||||
|
),
|
||||||
%% We should recover if the prepared statement name already exists in the
|
%% We should recover if the prepared statement name already exists in the
|
||||||
%% driver
|
%% driver
|
||||||
?check_trace(
|
?check_trace(
|
||||||
begin
|
begin
|
||||||
?inject_crash(
|
|
||||||
#{?snk_kind := pgsql_fake_prepare_statement_exists},
|
|
||||||
snabbkaffe_nemesis:recover_after(1)
|
|
||||||
),
|
|
||||||
?assertMatch({ok, _}, create_bridge(Config)),
|
?assertMatch({ok, _}, create_bridge(Config)),
|
||||||
?retry(
|
?retry(
|
||||||
_Sleep = 1_000,
|
_Sleep = 1_000,
|
||||||
|
@ -742,13 +764,19 @@ t_prepared_statement_exists(Config) ->
|
||||||
ok
|
ok
|
||||||
end
|
end
|
||||||
),
|
),
|
||||||
|
InsertPrepStatementDup =
|
||||||
|
fun(Conn, Key, SQL, List) ->
|
||||||
|
meck:passthrough([Conn, Key, SQL, List]),
|
||||||
|
meck:passthrough([Conn, Key, SQL, List])
|
||||||
|
end,
|
||||||
|
meck:expect(
|
||||||
|
epgsql,
|
||||||
|
parse2,
|
||||||
|
InsertPrepStatementDup
|
||||||
|
),
|
||||||
%% We should get status disconnected if removing already existing statment don't help
|
%% We should get status disconnected if removing already existing statment don't help
|
||||||
?check_trace(
|
?check_trace(
|
||||||
begin
|
begin
|
||||||
?inject_crash(
|
|
||||||
#{?snk_kind := pgsql_fake_prepare_statement_exists},
|
|
||||||
snabbkaffe_nemesis:recover_after(30)
|
|
||||||
),
|
|
||||||
?assertMatch({ok, _}, create_bridge(Config)),
|
?assertMatch({ok, _}, create_bridge(Config)),
|
||||||
?retry(
|
?retry(
|
||||||
_Sleep = 1_000,
|
_Sleep = 1_000,
|
||||||
|
|
|
@ -661,7 +661,6 @@ prepare_sql_to_conn(
|
||||||
) when is_pid(Conn) ->
|
) when is_pid(Conn) ->
|
||||||
LogMeta = #{msg => "postgresql_prepare_statement", name => Key, sql => SQL},
|
LogMeta = #{msg => "postgresql_prepare_statement", name => Key, sql => SQL},
|
||||||
?SLOG(info, LogMeta),
|
?SLOG(info, LogMeta),
|
||||||
test_maybe_inject_prepared_statement_already_exists(Conn, Key, SQL),
|
|
||||||
case epgsql:parse2(Conn, Key, SQL, []) of
|
case epgsql:parse2(Conn, Key, SQL, []) of
|
||||||
{ok, Statement} ->
|
{ok, Statement} ->
|
||||||
prepare_sql_to_conn(Conn, Rest, Statements#{Key => Statement}, 0);
|
prepare_sql_to_conn(Conn, Rest, Statements#{Key => Statement}, 0);
|
||||||
|
@ -694,8 +693,8 @@ prepare_sql_to_conn(
|
||||||
case epgsql:close(Conn, statement, Key) of
|
case epgsql:close(Conn, statement, Key) of
|
||||||
ok ->
|
ok ->
|
||||||
?SLOG(info, #{msg => "pqsql_closed_statement_successfully"});
|
?SLOG(info, #{msg => "pqsql_closed_statement_successfully"});
|
||||||
{error, Error} ->
|
{error, CloseError} ->
|
||||||
?SLOG(warning, #{msg => "pqsql_close_statement_failed", cause => Error})
|
?SLOG(warning, #{msg => "pqsql_close_statement_failed", cause => CloseError})
|
||||||
end,
|
end,
|
||||||
prepare_sql_to_conn(Conn, ToPrepare, Statements, Attempts + 1);
|
prepare_sql_to_conn(Conn, ToPrepare, Statements, Attempts + 1);
|
||||||
{error, Error} ->
|
{error, Error} ->
|
||||||
|
@ -709,25 +708,6 @@ prepare_sql_to_conn(
|
||||||
{error, export_error(TranslatedError)}
|
{error, export_error(TranslatedError)}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
-ifdef(TEST).
|
|
||||||
test_maybe_inject_prepared_statement_already_exists(Conn, Key, SQL) ->
|
|
||||||
try
|
|
||||||
%% In test we inject a crash in the following trace point to test the
|
|
||||||
%% scenario when the prepared statement already exists. It is unknkown
|
|
||||||
%% in which scenario this can happen but it has been observed in a
|
|
||||||
%% production log file. See:
|
|
||||||
%% https://emqx.atlassian.net/browse/EEC-1036
|
|
||||||
?tp(pgsql_fake_prepare_statement_exists, #{})
|
|
||||||
catch
|
|
||||||
_:_ ->
|
|
||||||
epgsql:parse2(Conn, Key, SQL, [])
|
|
||||||
end,
|
|
||||||
ok.
|
|
||||||
-else.
|
|
||||||
test_maybe_inject_prepared_statement_already_exists(_Conn, _Key, _SQL) ->
|
|
||||||
ok.
|
|
||||||
-endif.
|
|
||||||
|
|
||||||
to_bin(Bin) when is_binary(Bin) ->
|
to_bin(Bin) when is_binary(Bin) ->
|
||||||
Bin;
|
Bin;
|
||||||
to_bin(Atom) when is_atom(Atom) ->
|
to_bin(Atom) when is_atom(Atom) ->
|
||||||
|
|
Loading…
Reference in New Issue