diff options
author | Paweł Chmielowski <pawel@process-one.net> | 2022-07-28 19:24:28 +0200 |
---|---|---|
committer | Paweł Chmielowski <pawel@process-one.net> | 2022-07-28 19:24:28 +0200 |
commit | 2b3644c8ac7dc4cc81b73332964f860d8186a31d (patch) | |
tree | 873cb994f3c95e2ab3e94a4283c0ae411f62b17d /src | |
parent | Make connection close errors bubble up from inside sql transaction (diff) |
Handle errors reported from begin/commit inside transaction
Diffstat (limited to 'src')
-rw-r--r-- | src/ejabberd_sql.erl | 80 |
1 files changed, 45 insertions, 35 deletions
diff --git a/src/ejabberd_sql.erl b/src/ejabberd_sql.erl index d4d7c74a..53135e8f 100644 --- a/src/ejabberd_sql.erl +++ b/src/ejabberd_sql.erl @@ -560,44 +560,54 @@ outer_transaction(F, NRestarts, _Reason) -> [T]), erlang:exit(implementation_faulty) end, - sql_begin(), - put(?NESTING_KEY, PreviousNestingLevel + 1), - try F() of - Res -> - sql_commit(), - {atomic, Res} - catch - ?EX_RULE(throw, {aborted, Reason}, _) when NRestarts > 0 -> - rollback_transaction(F, NRestarts, Reason); - ?EX_RULE(throw, {aborted, Reason}, Stack) when NRestarts =:= 0 -> - StackTrace = ?EX_STACK(Stack), - ?ERROR_MSG("SQL transaction restarts exceeded~n** " - "Restarts: ~p~n** Last abort reason: " - "~p~n** Stacktrace: ~p~n** When State " - "== ~p", - [?MAX_TRANSACTION_RESTARTS, Reason, - StackTrace, get(?STATE_KEY)]), - rollback_transaction(F, NRestarts, Reason); - ?EX_RULE(exit, Reason, _) -> - rollback_transaction(F, 0, Reason) - end. - -rollback_transaction(F, NRestarts, Reason) -> - Res = case driver_restart_required(Reason) of - true -> - {aborted, Reason}; + case sql_begin() of + {error, Reason} -> + maybe_restart_transaction(F, NRestarts, Reason, false); _ -> - case sql_rollback() of - {Tag, Reason2} when Tag == error; Tag == aborted -> - case driver_restart_required(Reason2) of - true -> - {aborted, Reason2}; + put(?NESTING_KEY, PreviousNestingLevel + 1), + try F() of + Res -> + case sql_commit() of + {error, Reason} -> + restart(Reason); _ -> - continue - end; - _ -> - continue + {atomic, Res} + end + catch + ?EX_RULE(throw, {aborted, Reason}, _) when NRestarts > 0 -> + maybe_restart_transaction(F, NRestarts, Reason, true); + ?EX_RULE(throw, {aborted, Reason}, Stack) when NRestarts =:= 0 -> + StackTrace = ?EX_STACK(Stack), + ?ERROR_MSG("SQL transaction restarts exceeded~n** " + "Restarts: ~p~n** Last abort reason: " + "~p~n** Stacktrace: ~p~n** When State " + "== ~p", + [?MAX_TRANSACTION_RESTARTS, Reason, + StackTrace, get(?STATE_KEY)]), + maybe_restart_transaction(F, NRestarts, Reason, true); + ?EX_RULE(exit, Reason, _) -> + maybe_restart_transaction(F, 0, Reason, true) end + end. + +maybe_restart_transaction(F, NRestarts, Reason, DoRollback) -> + Res = case driver_restart_required(Reason) of + true -> + {aborted, Reason}; + _ when DoRollback -> + case sql_rollback() of + {error, Reason2} -> + case driver_restart_required(Reason2) of + true -> + {aborted, Reason2}; + _ -> + continue + end; + _ -> + continue + end; + _ -> + continue end, case Res of continue when NRestarts > 0 -> |