From b888bd027155ee69428617dcc53b9b0e8045b02d Mon Sep 17 00:00:00 2001 From: William Li Date: Thu, 16 Sep 2021 14:10:10 -0700 Subject: [PATCH] Fix 10 minutes time out of TransactionScope https://github.com/dotnet/sdk/issues/21101 --- src/Cli/dotnet/TransactionalAction.cs | 56 ++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/src/Cli/dotnet/TransactionalAction.cs b/src/Cli/dotnet/TransactionalAction.cs index 087b983112a7..ed0ee39082b5 100644 --- a/src/Cli/dotnet/TransactionalAction.cs +++ b/src/Cli/dotnet/TransactionalAction.cs @@ -2,12 +2,19 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using System.Reflection; using System.Transactions; +using Microsoft.DotNet.Cli.Utils; namespace Microsoft.DotNet.Cli { public sealed class TransactionalAction { + static TransactionalAction() + { + DisableTransactionTimeoutUpperLimit(); + } + private class EnlistmentNotification : IEnlistmentNotification { private Action _commit; @@ -65,19 +72,44 @@ public static T Run( // This automatically inherits any ambient transaction // If a transaction is inherited, completing this scope will be a no-op T result = default(T); - using (var scope = new TransactionScope( - TransactionScopeOption.Required, - TimeSpan.Zero)) + try { - Transaction.Current.EnlistVolatile( - new EnlistmentNotification(commit, rollback), - EnlistmentOptions.None); + using (var scope = new TransactionScope( + TransactionScopeOption.Required, + TimeSpan.Zero)) + { + Transaction.Current.EnlistVolatile( + new EnlistmentNotification(commit, rollback), + EnlistmentOptions.None); - result = action(); + result = action(); - scope.Complete(); + scope.Complete(); + } + + return result; + } + catch (TransactionAbortedException ex) + { + Reporter.Verbose.WriteLine(string.Format("TransactionAbortedException Message: {0}", ex.Message)); + Reporter.Verbose.WriteLine( + $"Inner Exception Message: {ex?.InnerException?.Message + "---" + ex?.InnerException}"); + throw; } - return result; + } + + private static void SetTransactionManagerField(string fieldName, object value) + { + typeof(TransactionManager).GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Static) + .SetValue(null, value); + } + + // https://github.com/dotnet/sdk/issues/21101 + // we should use the proper API once it is available + public static void DisableTransactionTimeoutUpperLimit() + { + SetTransactionManagerField("s_cachedMaxTimeout", true); + SetTransactionManagerField("s_maximumTimeout", TimeSpan.Zero); } public static void Run( @@ -86,7 +118,11 @@ public static void Run( Action rollback = null) { Run( - action: () => { action(); return null; }, + action: () => + { + action(); + return null; + }, commit: commit, rollback: rollback); }