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
Handle after commit strategy when transactional callback of Active Record object fails before handler scheduling #183
Comments
Related #181 |
P.S. Here is how we could handle it for Rails 4 & 5 def committed!(should_run_callbacks_rails_4=true, should_run_callbacks: true)
if should_run_callbacks_rails_4 && should_run_callbacks
@klass.perform_later(YAML.dump(@event))
end
end although mutation testing will probably scream 😱 |
I think we're only interested in knowing whether a transaction has been committed or rolled back:
Adding a test case for the situation you described is a good idea. |
It is possible that after_commit in one of ActiveRecords has failed (raised). In such case: * error is bubbled up after transaction block * commited! is called with additional argument (with specifics depending on Rails version) What it means for us is that: * transaction is commited, records are saved (and events appended) thus proceeding with scheduling of handling the event * AsyncRecord#committed must accept additional arguments to not fail scheduling in this case [#183]
|
Have a look at this Rails 4 code:
and this similar Rails 5 code:
and especially look at the
ensure
part.Now imagine there is ActiveRecord object with
after_commit
callback.Imagine that we saved this ActiveRecord object and then published an event with an async handler subscribed to it (and configured to work in after-commit fashion) and then commit a transaction. That's a perfectly normal scenario. In such case RES'es
AsyncRecord
is added to the list ofrecords
connected to current transaction.Now imagine that the
after_commit
callback from the AR object fails and raises an exception. In such case for the rest of the records (including our AsyncRecord) inensure
part are called withcommitted!
but passingfalse
orshould_run_callbacks: false
.Our current behavior is to ignore this
false
and still try to enqueue the handler. Maybe that's ok, but maybe we should follow AR convention and abort like other records do...The benefit of current behavior is that in case of success the handler is scheduled and the situation is most likely more consistent. The downside is that if we get an exception then the exception will bubble us from
ensure
and thecommitted!(false)
won't be called on the rest of the records - with unknown implications for me.I decided to not fix it as part of #182 because the situation is less clear for me in terms of what behavior we want to have. We don't have tests for current behavior. We can add them and make this expectation explicit or we can reflect on our behavior and change it if we think that would be better.
What are your opinions?
The text was updated successfully, but these errors were encountered: