This blog is part of our Rails 6.1 series.
Rails 6.1 deprecates the use of return, break or throw to exit a transaction block.
return / break
1>> Post.transaction do 2>> @post.update(post_params) 3>> 4>> break # or return 5>> end 6 7# => TRANSACTION (0.1ms) begin transaction 8# => DEPRECATION WARNING: Using `return`, `break` or `throw` to exit a transaction block is 9# => deprecated without replacement. If the `throw` came from 10# => `Timeout.timeout(duration)`, pass an exception class as a second 11# => argument so it doesn't use `throw` to abort its block. This results 12# => in the transaction being committed, but in the next release of Rails 13# => it will rollback. 14# => TRANSACTION (0.8ms) commit transaction
throw
1>> Timeout.timeout(1) do 2>> Post.transaction do 3>> @post.update(post_params) 4>> 5>> sleep 3 # simulate slow request 6>> end 7>> end 8 9# => TRANSACTION (0.1ms) begin transaction 10# => DEPRECATION WARNING: Using `return`, `break` or `throw` to exit a transaction block is 11# => deprecated without replacement. If the `throw` came from 12# => `Timeout.timeout(duration)`, pass an exception class as a second 13# => argument so it doesn't use `throw` to abort its block. This results 14# => in the transaction being committed, but in the next release of Rails 15# => it will rollback. 16# => TRANSACTION (1.6ms) commit transaction 17# => Completed 500 Internal Server Error in 1022ms (ActiveRecord: 3.2ms | Allocations: 9736) 18# => Timeout::Error (execution expired)
Here, even when the error was thrown the transaction is committed. This is something which is going to change in the future versions.
This is done because currently, when a transaction block is wrapped in Timeout.timeout(duration) i.e. without second argument(an exception class) then it uses throw to exit the transaction.
Solution
1>> Timeout.timeout(1, Timeout::Error) do 2>> Post.transaction do 3>> @post.update(post_params) 4>> 5>> sleep 3 # simulate slow request 6>> end 7>> end 8 9# => TRANSACTION (0.1ms) begin transaction 10# => TRANSACTION (0.7ms) rollback transaction 11# => Timeout::Error (execution expired)
Check out the pull request for more details on this.