Handle errors reported from begin/commit inside transaction

This commit is contained in:
Paweł Chmielowski 2022-07-28 19:24:28 +02:00
parent 3d329c7e8f
commit 2b3644c8ac
1 changed files with 45 additions and 35 deletions

View File

@ -560,44 +560,54 @@ outer_transaction(F, NRestarts, _Reason) ->
[T]), [T]),
erlang:exit(implementation_faulty) erlang:exit(implementation_faulty)
end, end,
sql_begin(), case sql_begin() of
put(?NESTING_KEY, PreviousNestingLevel + 1), {error, Reason} ->
try F() of maybe_restart_transaction(F, NRestarts, Reason, false);
Res -> _ ->
sql_commit(), put(?NESTING_KEY, PreviousNestingLevel + 1),
{atomic, Res} try F() of
catch Res ->
?EX_RULE(throw, {aborted, Reason}, _) when NRestarts > 0 -> case sql_commit() of
rollback_transaction(F, NRestarts, Reason); {error, Reason} ->
?EX_RULE(throw, {aborted, Reason}, Stack) when NRestarts =:= 0 -> restart(Reason);
StackTrace = ?EX_STACK(Stack), _ ->
?ERROR_MSG("SQL transaction restarts exceeded~n** " {atomic, Res}
"Restarts: ~p~n** Last abort reason: " end
"~p~n** Stacktrace: ~p~n** When State " catch
"== ~p", ?EX_RULE(throw, {aborted, Reason}, _) when NRestarts > 0 ->
[?MAX_TRANSACTION_RESTARTS, Reason, maybe_restart_transaction(F, NRestarts, Reason, true);
StackTrace, get(?STATE_KEY)]), ?EX_RULE(throw, {aborted, Reason}, Stack) when NRestarts =:= 0 ->
rollback_transaction(F, NRestarts, Reason); StackTrace = ?EX_STACK(Stack),
?EX_RULE(exit, Reason, _) -> ?ERROR_MSG("SQL transaction restarts exceeded~n** "
rollback_transaction(F, 0, Reason) "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. end.
rollback_transaction(F, NRestarts, Reason) -> maybe_restart_transaction(F, NRestarts, Reason, DoRollback) ->
Res = case driver_restart_required(Reason) of Res = case driver_restart_required(Reason) of
true -> true ->
{aborted, Reason}; {aborted, Reason};
_ -> _ when DoRollback ->
case sql_rollback() of case sql_rollback() of
{Tag, Reason2} when Tag == error; Tag == aborted -> {error, Reason2} ->
case driver_restart_required(Reason2) of case driver_restart_required(Reason2) of
true -> true ->
{aborted, Reason2}; {aborted, Reason2};
_ -> _ ->
continue continue
end; end;
_ -> _ ->
continue continue
end end;
_ ->
continue
end, end,
case Res of case Res of
continue when NRestarts > 0 -> continue when NRestarts > 0 ->