-
Notifications
You must be signed in to change notification settings - Fork 39
EF-280: Treat dispose of an active MongoTransaction as rollback #263
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
base: main
Are you sure you want to change the base?
Conversation
tests/MongoDB.EntityFrameworkCore.FunctionalTests/Storage/TransactionTests.cs
Show resolved
Hide resolved
tests/MongoDB.EntityFrameworkCore.FunctionalTests/Storage/TransactionTests.cs
Show resolved
Hide resolved
tests/MongoDB.EntityFrameworkCore.FunctionalTests/Storage/TransactionTests.cs
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR modifies the transaction disposal behavior to automatically rollback active transactions instead of throwing an exception. This enables the use of ExecuteInTransaction on ExecutionStrategy which disposes transactions via using statements on exceptions rather than explicitly rolling back.
Key Changes:
- Modified
MongoTransaction.Dispose()andDisposeAsync()to automatically rollback active transactions instead of throwing exceptions - Removed tests that verified the old behavior (disposing without commit/rollback throws)
- Updated tests to reflect new behavior where dispose without commit/rollback silently rolls back
- Added new tests for
ExecuteInTransactionintegration with execution strategies
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 8 comments.
| File | Description |
|---|---|
src/MongoDB.EntityFrameworkCore/Storage/MongoTransaction.cs |
Changed disposal methods to automatically rollback active transactions; removed unused import and helper method |
tests/MongoDB.EntityFrameworkCore.FunctionalTests/Storage/TransactionTests.cs |
Removed old tests expecting exceptions on dispose, updated tests to reflect silent rollback behavior, added new tests for ExecuteInTransaction integration |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
tests/MongoDB.EntityFrameworkCore.FunctionalTests/Storage/TransactionTests.cs
Outdated
Show resolved
Hide resolved
tests/MongoDB.EntityFrameworkCore.FunctionalTests/Storage/TransactionTests.cs
Outdated
Show resolved
Hide resolved
tests/MongoDB.EntityFrameworkCore.FunctionalTests/Storage/TransactionTests.cs
Outdated
Show resolved
Hide resolved
tests/MongoDB.EntityFrameworkCore.FunctionalTests/Storage/TransactionTests.cs
Outdated
Show resolved
Hide resolved
tests/MongoDB.EntityFrameworkCore.FunctionalTests/Storage/TransactionTests.cs
Show resolved
Hide resolved
tests/MongoDB.EntityFrameworkCore.FunctionalTests/Storage/TransactionTests.cs
Show resolved
Hide resolved
| break; | ||
|
|
||
| default: | ||
| throw new InvalidOperationException($"Can not Dispose MongoTransaction {TransactionId} because it is {_transactionState}."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we throw instead of rolling back for the "Committing" and "RollingBack" states? Also, do we want to throw by default if a new state is introduced? If we're responsible for the lifetime of the transaction, and it is disposed while in anything other than a final state (Failed, Committed, RolledBack), then I think we should attempt to roll back, since the transaction is going away.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Committing and RollingBack are in-progress states. They should never get here.
Even if we do I don't think we can roll-back mid-commit and I'm sure we can't roll back mid roll back.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you point me to where these states are defined so I can read up on it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's an enum at the start of this file.
We set it to Committing at the start of the Commit methods, and RollingBack at the start of the RollBack methods.
If it's either of these states when disposing it basically has to either be either a bug in our code or a concurrency issue where they are trying to use the non-thread-safe MongoTransaction across multiple threads and one is doing a dispose while the other is performing a commit or rollback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I spent some more time looking at all the code here, rather than just the PR, and I now understand these are just states we have, not the server or driver. Given that, as you say, this is not thread-safe, then Committing and RollingBack are not observable outside the class for any thread-safe correct code. So, first, why even have them? Second, if we detect that we are in a state that can only be reached by executing in a thread-unsafe manner, then we should explicitly say that in the exception message so that people know this is why the code threw--like what System.Collections.Generic does when you try to modify a collection while it is in use.
This allows ExecuteInTransaction to be used on ExecutionStrategy as on exception it simply disposes the transaction by way of a
usingrather than explicitly rolling back.