[CSHARP-3690] IClientSessionHandle.IsInTransaction remains true even if transaction has been aborted Created: 27/May/21 Updated: 27/Oct/23 Resolved: 02/Jun/21 |
|
| Status: | Closed |
| Project: | C# Driver |
| Component/s: | Error Handling, Transactions |
| Affects Version/s: | 2.12.3 |
| Fix Version/s: | None |
| Type: | Bug | Priority: | Major - P3 |
| Reporter: | Daniel Camarena | Assignee: | Dmitry Lukyanov (Inactive) |
| Resolution: | Works as Designed | Votes: | 0 |
| Labels: | InTransaction, command, exception, failed, transactions | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Environment: |
C#; .NET 5; VS 2019; Windows 10, xunit 2.4.1 |
||
| Attachments: |
|
| Description |
|
IClientSessionHandle.IsInTransaction remains true on aborted transaction because of e.g. MongoWriteException. CommitTransaction excepts afterwards with the message: MongoDB.Driver.MongoCommandException : Command commitTransaction failed: Transaction 1 has been aborted.. I've attached a complete VS 2019 solution with xunit unit tests to reproduce the behavior. Unit test AbortTransactionOnMongoDbException and ZombieSessionHowEcsDoesItTest4 fail because IsInTransaction is true even after transaction was aborted and therefore CommitTransaction is called. |
| Comments |
| Comment by Daniel Camarena [ 22/Jun/21 ] | |||||||||||||
|
I solved it like advised by Dmitry Lukyanov: DAL is checking for MongoServerException, calls AbortTransaction and throws the exception again. If someone is interested in my solution how to handle it divided into DAL and BL:
| |||||||||||||
| Comment by Daniel Camarena [ 22/Jun/21 ] | |||||||||||||
|
Dear Dmitry Lukyanov, thank you again for your response. I think I have no other option than to accept your answer and do the workaround in my business logic. I still think that the session variable IsInTransaction in the driver should represent the status of a transaction - apparently in the server - the client has no transactions and therefore it's irrelevant if it thinks that there is an transaction active. But anyway, it seems that we are not on the same page regarding this issue.
Thank you again for you effort, | |||||||||||||
| Comment by Dmitry Lukyanov (Inactive) [ 21/Jun/21 ] | |||||||||||||
|
Hello daniel.camarena@azo.com , the behavior you're seeing is designed. IsInTransaction represents the status of a transaction on the client side. | |||||||||||||
| Comment by Daniel Camarena [ 21/Jun/21 ] | |||||||||||||
|
Hi,
as I'm new here, I don't know if anybody is reading comments on "closed" items. A short "another developer is reflecting it" or "we are still thinking about it" or "you were wrong, everything is fine like it is" would be great.
Thanks, Daniel | |||||||||||||
| Comment by Daniel Camarena [ 03/Jun/21 ] | |||||||||||||
|
Dear Dmitry Lukyanov,
thank you for your investigation and the answer. The unit test is just an easy example to show the behavior I'd have excepted in another way. I know that the second insert fails and why it fails. For me the interesting thing in the unit test is, that the transaction was aborted on server side for some reason, but the session object on client side still indicates that the transaction is active, which is not true. I don't want to call AbortTransaction because of a server side exception. The decision was already made by the server - the transaction was already aborted. The code in the except path is just to convince the client driver to indicate the correct information (IsInTranaction=false) which should not be job of the business logic, but the driver itself. So, I'd agree if the lines you sent would be in the driver. When the driver notices that the server has aborted a transaction it should bring local variables in the same state to represent the real state of the object on the server.
Thank you for the example, but in my real world program this is unfortunately not possible because several different classes are working on the same transaction without knowing of each other. So one central part is starting the transaction, everybody else is listening on events, modifying data if necessary and at the end the transaction is committed. Therefore, the example you showed is quite easy and the easiest way to use the session object avoiding the problem I have, unfortunately not an option in my case.
Long story short: From my point of view the driver should keep the provided information up to date and not obligate the user to do this. In this particular case: When the driver notices that the server has ended the transaction, it should bring local variables to a correct state.
Thank you once again for your time and effort investigating in this issue.
Best regards, Daniel | |||||||||||||
| Comment by Dmitry Lukyanov (Inactive) [ 01/Jun/21 ] | |||||||||||||
|
Hello daniel.camarena@azo.com,
so, the behavior you're seeing is expected. | |||||||||||||
| Comment by Mikalai Mazurenka (Inactive) [ 28/May/21 ] | |||||||||||||
|
Thanks for reporting this issue! We need some time to investigate it and will come back to you. | |||||||||||||
| Comment by Daniel Camarena [ 27/May/21 ] | |||||||||||||
|
Description in documentation of IsInTransaction which is not met: http://mongodb.github.io/mongo-csharp-driver/2.12/reference/driver/crud/sessions_and_transactions/#isintransaction Due to MongoDbException an transaction is aborted and call of commit and rollback is no longer possible. Everything is fine from my point of view if IsInTransaction would indicate it correctly. |