Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix transaction extensions to handle failures correctly #25

Merged
merged 2 commits into from
Oct 27, 2024

Conversation

waiting-for-dev
Copy link
Member

Overview

The intercepting_failure method was not handling the block's output correctly when it was a failure. It wasn't throwing :halt with the failure as the given handlers were raising and therefore the throwing part was never reached.

We modify the method to pass the failure to the handler and skip the throwing part, while extensions need to work in two phases:

1 - From within the transaction block, they intercept a failure a first time and assign it to a result variable available from the outer scope. After that, they raise to rollback the transaction but return the result variable after that.

2 - From outside the transaction block, they throw again the failure when the result is actually a failure.

We also make public the throw_failure method so that other extensions can create similar behavior.

We also add a warning in the ActiveRecord extension to make it clear that the :requires_new option is not yet supported for this approach. We should find a way to make it work in the future.

Closes #23

Screenshots/Screencasts

Details

The `intercepting_failure` method was not handling the block's output
correctly when it was a failure. It wasn't throwing `:halt` with the
failure as the given handlers were raising and therefore the throwing
part was never reached.

We modify the method to pass the failure to the handler and skip the
throwing part, while extensions need to work in two phases:

1 - From within the transaction block, they intercept a failure a first time
and assign it to a `result` variable available from the outer scope.
After that, they raise to rollback the transaction but return the
`result` variable after that.

2 - From outside the transaction block, they throw again the failure
when the `result` is actually a failure.

We also make public the `throw_failure` method so that other extensions
can create similar behavior.

We also add a warning in the ActiveRecord extension to make it clear
that the `:requires_new` option is not yet supported for this approach.
We should find a way to make it work in the future.

Closes #23
Copy link
Member

@timriley timriley left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@waiting-for-dev Changes look good. Thank you!

It seems like the job of writing an extension has become a bit more complicated with this change, but if that's what's necessary to provide correct behaviour, then that's fine :) The extensions still seem straightforward enough to follow.

I've left one suggestion about how we can simplify things a little. Happy for you to decide what you think is best for that.

lib/dry/operation/extensions/active_record.rb Outdated Show resolved Hide resolved
@waiting-for-dev
Copy link
Member Author

It seems like the job of writing an extension has become a bit more complicated with this change, but if that's what's necessary to provide correct behaviour, then that's fine :)

Yeah, unfortunately now everything becomes more cumbersome, but unfortunately I can't see any other way to workaround the two mechanisms breaking the control flow in sequence :/

@waiting-for-dev waiting-for-dev merged commit a6ea211 into main Oct 27, 2024
6 checks passed
@waiting-for-dev waiting-for-dev deleted the waiting-for-dev/fix_failure_and_transaction branch October 27, 2024 04:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Transaction does not return the expected Failure
2 participants