public static void InvokeWithConcurrencyRetryAllowNested( Action <TransactionScope> action, TransactionScopeOption transactionScopeOption = TransactionScopeOption.Required, int maxRetries = 3, TimeSpan?timeout = null) //TransactionScopeAsyncFlowOption transactionScopeAsyncFlowOption = TransactionScopeAsyncFlowOption.Suppress) // .NET 4.5.1 feature { if (action == null) { throw new ArgumentNullException("action"); } // If this is an inner transaction, the outer transaction is responsible for the retry logic if (transactionScopeOption == TransactionScopeOption.Required && Transaction.Current != null) { using (var scope = CreateSerializable(transactionScopeOption, timeout /*, transactionScopeAsyncFlowOption*/)) { action(scope); } } else { var attempt = 0; ActionUtils.RetryAction( () => { attempt++; using (var scope = CreateSerializable(transactionScopeOption, timeout /*, transactionScopeAsyncFlowOption*/)) { action(scope); } }, TimeSpan.MaxValue, ex => { if (ex is TransactionAbortedException && ex.InnerException is ConcurrencyException) { var msg = string.Format("Transaction concurrency fault occured. Attempt: {0}/{1}", attempt, maxRetries); Log.Warn(msg, ex); if (attempt < maxRetries) { return(true); } } return(false); }); } }
public static void InvokeWithConcurrencyRetry( Action <TransactionScope> action, TransactionScopeOption transactionScopeOption = TransactionScopeOption.Required, int maxRetries = 3, TimeSpan?timeout = null) //TransactionScopeAsyncFlowOption transactionScopeAsyncFlowOption = TransactionScopeAsyncFlowOption.Suppress) // .NET 4.5.1 feature { if (action == null) { throw new ArgumentNullException(nameof(action)); } if (transactionScopeOption == TransactionScopeOption.Required && Transaction.Current != null) { throw new TransactionException("Error, ambient transaction already exists. Retry must occur on outer or new transaction scope"); } var attempt = 0; ActionUtils.RetryAction( () => { attempt++; using (var scope = CreateSerializable(transactionScopeOption, timeout /*, transactionScopeAsyncFlowOption*/)) { action(scope); } }, TimeSpan.MaxValue, ex => { if (ex is TransactionAbortedException && ex.InnerException is ConcurrencyException) { Log.WarnException($"Transaction concurrency fault occured. Attempt: {attempt}/{maxRetries}", ex); if (attempt < maxRetries) { return(true); } } return(false); }); }