mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-22 16:20:52 +01:00
Make connection close errors bubble up from inside sql transaction
This commit is contained in:
parent
1ea53bf940
commit
3d329c7e8f
@ -479,6 +479,12 @@ handle_reconnect(Reason, #state{host = Host, reconnect_count = RC} = State) ->
|
|||||||
"** Retry after: ~B seconds",
|
"** Retry after: ~B seconds",
|
||||||
[State#state.db_type, Reason,
|
[State#state.db_type, Reason,
|
||||||
StartInterval div 1000]),
|
StartInterval div 1000]),
|
||||||
|
case State#state.db_type of
|
||||||
|
mysql -> catch p1_mysql_conn:stop(State#state.db_ref);
|
||||||
|
sqlite -> catch sqlite3:close(sqlite_db(State#state.host));
|
||||||
|
pgsql -> catch pgsql:terminate(State#state.db_ref);
|
||||||
|
_ -> ok
|
||||||
|
end,
|
||||||
p1_fsm:send_event_after(StartInterval, connect),
|
p1_fsm:send_event_after(StartInterval, connect),
|
||||||
{next_state, connecting, State#state{reconnect_count = RC + 1}}.
|
{next_state, connecting, State#state{reconnect_count = RC + 1}}.
|
||||||
|
|
||||||
@ -562,9 +568,7 @@ outer_transaction(F, NRestarts, _Reason) ->
|
|||||||
{atomic, Res}
|
{atomic, Res}
|
||||||
catch
|
catch
|
||||||
?EX_RULE(throw, {aborted, Reason}, _) when NRestarts > 0 ->
|
?EX_RULE(throw, {aborted, Reason}, _) when NRestarts > 0 ->
|
||||||
sql_rollback(),
|
rollback_transaction(F, NRestarts, Reason);
|
||||||
put(?NESTING_KEY, ?TOP_LEVEL_TXN),
|
|
||||||
outer_transaction(F, NRestarts - 1, Reason);
|
|
||||||
?EX_RULE(throw, {aborted, Reason}, Stack) when NRestarts =:= 0 ->
|
?EX_RULE(throw, {aborted, Reason}, Stack) when NRestarts =:= 0 ->
|
||||||
StackTrace = ?EX_STACK(Stack),
|
StackTrace = ?EX_STACK(Stack),
|
||||||
?ERROR_MSG("SQL transaction restarts exceeded~n** "
|
?ERROR_MSG("SQL transaction restarts exceeded~n** "
|
||||||
@ -573,11 +577,36 @@ outer_transaction(F, NRestarts, _Reason) ->
|
|||||||
"== ~p",
|
"== ~p",
|
||||||
[?MAX_TRANSACTION_RESTARTS, Reason,
|
[?MAX_TRANSACTION_RESTARTS, Reason,
|
||||||
StackTrace, get(?STATE_KEY)]),
|
StackTrace, get(?STATE_KEY)]),
|
||||||
sql_rollback(),
|
rollback_transaction(F, NRestarts, Reason);
|
||||||
{aborted, Reason};
|
|
||||||
?EX_RULE(exit, Reason, _) ->
|
?EX_RULE(exit, Reason, _) ->
|
||||||
sql_rollback(),
|
rollback_transaction(F, 0, Reason)
|
||||||
{aborted, Reason}
|
end.
|
||||||
|
|
||||||
|
rollback_transaction(F, NRestarts, Reason) ->
|
||||||
|
Res = case driver_restart_required(Reason) of
|
||||||
|
true ->
|
||||||
|
{aborted, Reason};
|
||||||
|
_ ->
|
||||||
|
case sql_rollback() of
|
||||||
|
{Tag, Reason2} when Tag == error; Tag == aborted ->
|
||||||
|
case driver_restart_required(Reason2) of
|
||||||
|
true ->
|
||||||
|
{aborted, Reason2};
|
||||||
|
_ ->
|
||||||
|
continue
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
case Res of
|
||||||
|
continue when NRestarts > 0 ->
|
||||||
|
put(?NESTING_KEY, ?TOP_LEVEL_TXN),
|
||||||
|
outer_transaction(F, NRestarts - 1, Reason);
|
||||||
|
continue ->
|
||||||
|
{aborted, Reason};
|
||||||
|
Other ->
|
||||||
|
Other
|
||||||
end.
|
end.
|
||||||
|
|
||||||
execute_bloc(F) ->
|
execute_bloc(F) ->
|
||||||
@ -865,23 +894,22 @@ sql_rollback() ->
|
|||||||
[{mssql, [<<"rollback transaction;">>]},
|
[{mssql, [<<"rollback transaction;">>]},
|
||||||
{any, [<<"rollback;">>]}]).
|
{any, [<<"rollback;">>]}]).
|
||||||
|
|
||||||
|
driver_restart_required(<<"query timed out">>) -> true;
|
||||||
|
driver_restart_required(<<"connection closed">>) -> true;
|
||||||
|
driver_restart_required(<<"Failed sending data on socket", _/binary>>) -> true;
|
||||||
|
driver_restart_required(<<"SQL connection failed">>) -> true;
|
||||||
|
driver_restart_required(<<"Communication link failure">>) -> true;
|
||||||
|
driver_restart_required(_) -> false.
|
||||||
|
|
||||||
%% Generate the OTP callback return tuple depending on the driver result.
|
%% Generate the OTP callback return tuple depending on the driver result.
|
||||||
abort_on_driver_error({error, <<"query timed out">>} = Reply, From, Timestamp) ->
|
abort_on_driver_error({Tag, Msg} = Reply, From, Timestamp) when Tag == error; Tag == aborted ->
|
||||||
reply(From, Reply, Timestamp),
|
reply(From, Reply, Timestamp),
|
||||||
{stop, timeout, get(?STATE_KEY)};
|
case driver_restart_required(Msg) of
|
||||||
abort_on_driver_error({error, <<"connection closed">>} = Reply, From, Timestamp) ->
|
true ->
|
||||||
reply(From, Reply, Timestamp),
|
handle_reconnect(Msg, get(?STATE_KEY));
|
||||||
handle_reconnect(<<"connection closed">>, get(?STATE_KEY));
|
_ ->
|
||||||
abort_on_driver_error({error, <<"Failed sending data on socket", _/binary>>} = Reply,
|
{next_state, session_established, get(?STATE_KEY)}
|
||||||
From, Timestamp) ->
|
end;
|
||||||
reply(From, Reply, Timestamp),
|
|
||||||
{stop, closed, get(?STATE_KEY)};
|
|
||||||
abort_on_driver_error({error, <<"SQL connection failed">>} = Reply, From, Timestamp) ->
|
|
||||||
reply(From, Reply, Timestamp),
|
|
||||||
{stop, timeout, get(?STATE_KEY)};
|
|
||||||
abort_on_driver_error({error, <<"Communication link failure">>} = Reply, From, Timestamp) ->
|
|
||||||
reply(From, Reply, Timestamp),
|
|
||||||
{stop, closed, get(?STATE_KEY)};
|
|
||||||
abort_on_driver_error(Reply, From, Timestamp) ->
|
abort_on_driver_error(Reply, From, Timestamp) ->
|
||||||
reply(From, Reply, Timestamp),
|
reply(From, Reply, Timestamp),
|
||||||
{next_state, session_established, get(?STATE_KEY)}.
|
{next_state, session_established, get(?STATE_KEY)}.
|
||||||
|
Loading…
Reference in New Issue
Block a user