-
Type: New Feature
-
Resolution: Fixed
-
Priority: Unknown
-
Affects Version/s: None
-
Component/s: None
-
None
after_commit is triggered on every document saved or destroyed:
- if there is a transaction, the callback is triggered immediately after the transaction is committed. This naturally happens after all other callbacks completed successfully.
- if there is no transaction, the callback is triggered after the corresponding persistence operation completed and all other callbacks completed successfully.
after_rollback is triggered on every document saved or destroyed:
- if there is a transaction, the callback triggered immediately after the transaction is rolled back.
- this callback is not triggered if there is no transaction.
*We will consider introducing an optional implicit transactions in Mongoid.
Rationale
In ActiveRecord save and destroy operations are automatically wrapped in a transaction. Therefore, transactional callbacks are always triggered, even if a used did not open a transaction explicitly. This is a desired and expected behavior.
In contrast, Mongoid does not wrap operations in transactions. Therefore, if we want to achieve the same behavior as Rails, we have to trigger the callbacks without a transaction. However, there are still gotchas that do not allow us to exactly copy AR.
It would be semantically correct to trigger this callback if and only if the persistence operation was completed successfully. However, this is different from the AR behavior. In AR, if there is an exception raised in after_save callback, the implicit transaction will be rolled back, and after_rollback will be triggered instead. And what is maybe even more important - the persistence operation will be reverted.
We cannot do the same in Mongoid without a transaction. If the persistence operation completed, there is no way to revert it, even if an exception in raised in after_save. Since a fully AR-compatible behavior is not achievable, we can only decide what we can sacrifice.
after_commit
We believe that if there is no transaction, the after_commit callback should be triggered the latest, only if all other callbacks completed successfully. This is semantically close to what AR does. The tradeoff here is it is possible that a document was persisted, but its after_commit wasn't called. But this can happen if there was an exception raised in an after_* callback. So, a user has a chance to handle this situation.
after_rollback
As to after_rollback, we believe that this callback should not be triggered at all if there is no transaction. In case of after_commit happy path without a transaction we can end up in a situation that is equivalent to the one in AR; for after_rollback this is not going to happen.
Add :on option to after_commit and after_rollback callbacks (https://jira.mongodb.org/browse/MONGOID-5058)
- has to be done after
-
MONGOID-5530 Add transaction method
- Closed
-
MONGOID-5534 Add transaction method to Mongoid module
- Closed
- is duplicated by
-
MONGOID-4975 Add callbacks to Mongoid::Documents related to Mongo transactions
- Closed
-
MONGOID-5541 Improve callback behavior in transactions
- Closed
- related to
-
MONGOID-5700 Commit & rollback callbacks defined in mongoid 8.1 before code to run them is added
- Closed