Skip to content
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

Improve DTC check #860

Merged
merged 1 commit into from
Jun 21, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -266,10 +266,16 @@ async Task<StartupCheckResult> TryEscalateToDistributedTransactions(TransactionO
try
{
using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew, transactionOptions, TransactionScopeAsyncFlowOption.Enabled))
using (await connectionFactory.OpenNewConnection().ConfigureAwait(false))
using (await connectionFactory.OpenNewConnection().ConfigureAwait(false))
{
scope.Complete();
FakePromotableResourceManager.ForceDtc();
using (await connectionFactory.OpenNewConnection().ConfigureAwait(false))
{
FakePromotableResourceManager.ForceDtc();
using (await connectionFactory.OpenNewConnection().ConfigureAwait(false))
{
scope.Complete();
}
}
}
}
catch (NotSupportedException ex)
Expand All @@ -281,13 +287,13 @@ async Task<StartupCheckResult> TryEscalateToDistributedTransactions(TransactionO
"Note that different transaction modes may affect consistency guarantees as you can't rely on distributed " +
"transactions to atomically update the database and consume a message. Original error message: " + ex.Message;
}
catch (SqlException sqlException)
catch (Exception exception)
{
message = "Could not escalate to a distributed transaction while configured to use TransactionScope. Check original error message for details. " +
"In case the problem is related to distributed transactions you can still use SQL Server transport but " +
"should specify a different transaction mode via `EndpointConfiguration.UseTransport<SqlServerTransport>().Transactions`. " +
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"should specify a different transaction mode via `EndpointConfiguration.UseTransport<SqlServerTransport>().Transactions`. " +
"should specify a different transaction mode by setting the `TransportTransactionMode` property on the `SqlServerTransport` instance when configuring the endpoint. " +

WIth the 8.0 API changes UseTransport() returns the routing settings so the transaction mode has to be set directly on the transport instance. The above sentence a bit less specific than it was prior and possibly confusing. Maybe we should send them to the docs instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't link in docs from components because we have no good way to ensure those links stay valid. But this is the 6.3 version so the UseTransport form is correct.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I am going to steal your wording (it's a bit hand-wavy but it's accurate) for the OTHER pull request on master where the message was not updated by the transport seam TF.

"Note that different transaction modes may affect consistency guarantees as you can't rely on distributed " +
"transactions to atomically update the database and consume a message. Original error message: " + sqlException.Message;
"transactions to atomically update the database and consume a message. Original error message: " + exception.Message;
}

if (!string.IsNullOrWhiteSpace(message))
Expand Down Expand Up @@ -360,6 +366,17 @@ public override string MakeCanonicalForm(string transportAddress)
return addressTranslator.Parse(transportAddress).Address;
}

class FakePromotableResourceManager : IEnlistmentNotification
{
public static readonly Guid Id = Guid.NewGuid();
public void Prepare(PreparingEnlistment preparingEnlistment) => preparingEnlistment.Prepared();
public void Commit(Enlistment enlistment) => enlistment.Done();
public void Rollback(Enlistment enlistment) => enlistment.Done();
public void InDoubt(Enlistment enlistment) => enlistment.Done();

public static void ForceDtc() => Transaction.Current.EnlistDurable(Id, new FakePromotableResourceManager(), EnlistmentOptions.None);
}

QueueAddressTranslator addressTranslator;
string connectionString;
Func<string> localAddress;
Expand Down