internal async Task <bool> GetShouldReplaceDeadSessionOrThrowIfNoRetryAsync( QldbTransactionException qte, T currentSession, int retryAttempt, RetryPolicy retryPolicy, CancellationToken token) { bool replaceDeadSession = this.GetIsSessionDeadAndThrowIfNoRetry( qte, currentSession, retryPolicy.MaxRetries, retryAttempt); try { var backoffDelay = retryPolicy.BackoffStrategy.CalculateDelay( new RetryPolicyContext(retryAttempt, qte.InnerException)); await Task.Delay(backoffDelay, token); } catch (Exception) { // Safeguard against semaphore leak if parameter actions throw exceptions. if (replaceDeadSession) { this.poolPermits.Release(); } throw; } return(replaceDeadSession); }
internal bool GetShouldReplaceDeadSessionOrThrowIfNoRetry( QldbTransactionException qte, T currentSession, int retryAttempt, RetryPolicy retryPolicy, Action <int> retryAction) { bool replaceDeadSession = this.GetIsSessionDeadAndThrowIfNoRetry( qte, currentSession, retryPolicy.MaxRetries, retryAttempt); try { retryAction?.Invoke(retryAttempt); Thread.Sleep(retryPolicy.BackoffStrategy.CalculateDelay( new RetryPolicyContext(retryAttempt, qte.InnerException))); } catch (Exception) { // Safeguard against semaphore leak if parameter actions throw exceptions. if (replaceDeadSession) { this.poolPermits.Release(); } throw; } return(replaceDeadSession); }
private bool GetIsSessionDeadAndThrowIfNoRetry( QldbTransactionException qte, T currentSession, int maxRetries, int retryAttempt) { if (qte is RetriableException) { // Always retry on the first attempt if failure was caused by a stale session in the pool. if (qte.InnerException is InvalidSessionException && retryAttempt == 1) { this.Logger.LogDebug("Initial session received from pool invalid. Retrying..."); return(true); } // Normal retry logic. if (retryAttempt > maxRetries) { if (qte.IsSessionAlive) { this.ReleaseSession(currentSession); } else { this.poolPermits.Release(); } throw qte.InnerException; } this.Logger.LogInformation("A recoverable error has occurred. Attempting retry #{}.", retryAttempt); this.Logger.LogDebug( "Errored Transaction ID: {}. Error cause: {}", qte.TransactionId, qte.InnerException.ToString()); if (qte.IsSessionAlive) { this.Logger.LogDebug("Retrying with a different session..."); this.ReleaseSession(currentSession); } else { this.Logger.LogDebug("Replacing invalid session..."); } return(!qte.IsSessionAlive); } else { if (qte.IsSessionAlive) { this.ReleaseSession(currentSession); } else { this.poolPermits.Release(); } throw qte.InnerException; } }