All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.microsoft.azure.servicebus.primitives.RetryPolicy Maven / Gradle / Ivy

Go to download

Java library for Azure Service Bus. Please note, a newer package com.azure:azure-messaging-servicebus for Azure Service Bus is available as of December 2020. While this package will continue to receive critical bug fixes, we strongly encourage you to upgrade. Read the migration guide at https://aka.ms/azsdk/java/migrate/sb for more details.

There is a newer version: 3.6.7
Show newest version
/*
 * Copyright (c) Microsoft. All rights reserved.
 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
 */
package com.microsoft.azure.servicebus.primitives;

import java.time.Duration;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Represents an abstraction of a policy for retrying messaging operations when an exception is encountered. Some exceptions encountered by a sender or receiver can be transient like ServerBusy and the operation
 * will succeed if retried. Clients can specify a retry policy using {@link ConnectionStringBuilder} which guides senders and receivers to automatically retry the failed operation before throwing the exception to the client application.  
 * Users should not implement this class, instead should use one of the provided implementations through {@link #getDefault} or {@link #getNoRetry}.
 * @since 1.0
 *
 */
// TODO: SIMPLIFY retryPolicy - ConcurrentHashMap is not needed
public abstract class RetryPolicy
{    
	private static final RetryPolicy NO_RETRY = new RetryExponential(Duration.ofSeconds(0), Duration.ofSeconds(0), 0, ClientConstants.NO_RETRY);	

	private final String name;
	private ConcurrentHashMap retryCounts;

	/**
	 * Creates an instance of RetryPolicy with the given name.
	 * @param name name of the policy
	 */
	protected RetryPolicy(final String name)
	{
		this.name = name;
		this.retryCounts = new ConcurrentHashMap();
	}

	/**
	 * Increments the number of successive retry attempts made by a client.
	 * @param clientId id of the client retrying a failed operation
	 */
	public void incrementRetryCount(String clientId)
	{
		Integer retryCount = this.retryCounts.get(clientId);
		this.retryCounts.put(clientId, retryCount == null ? 1 : retryCount + 1);
	}

	/**
	 * Resets the number of retry attempts made by a client. This method is called by the client when retried operation succeeds. 
	 * @param clientId id of the client that just retried a failed operation and succeeded.
	 */
	public void resetRetryCount(String clientId)
	{
		Integer currentRetryCount = this.retryCounts.get(clientId);
		if (currentRetryCount != null && currentRetryCount.intValue() != 0)
		{
			this.retryCounts.put(clientId, 0);
		}
	}

	/**
	 * Determines if an exception is retry-able or not. Only transient exceptions should be retried. 
	 * @param exception exception encountered by an operation, to be determined if it is retry-able.
	 * @return true if the exception is retry-able (like ServerBusy or other transient exception), else returns false
	 */
	public static boolean isRetryableException(Exception exception)
	{
		if (exception == null)
		{
			throw new IllegalArgumentException("exception cannot be null");
		}

		if (exception instanceof ServiceBusException)
		{
			return ((ServiceBusException) exception).getIsTransient();
		}

		return false;
	}

	/**
	 * Retry policy that provides exponentially increasing retry intervals with each successive failure. This policy is suitable for use by use most client applications and is also the default policy
	 * if no retry policy is specified.
	 * @return a retry policy that provides exponentially increasing retry intervals
	 */
	public static RetryPolicy getDefault()
	{
		return new RetryExponential(
				ClientConstants.DEFAULT_RERTRY_MIN_BACKOFF, 
				ClientConstants.DEFAULT_RERTRY_MAX_BACKOFF, 
				ClientConstants.DEFAULT_MAX_RETRY_COUNT,
				ClientConstants.DEFAULT_RETRY);
	}

	/**
	 * Gets a retry policy that doesn't retry any operations, effectively disabling retries. Clients can use this retry policy in case they do not want any operation automatically retried.
	 * @return a retry policy that doesn't retry any operations
	 */
	public static RetryPolicy getNoRetry()
	{
		return RetryPolicy.NO_RETRY;
	}

	protected int getRetryCount(String clientId)
	{
		Integer retryCount = this.retryCounts.get(clientId);
		return retryCount == null ? 0 : retryCount;
	}

	/**
	 * Gets the interval after which nextRetry should be attempted, based on the last exception encountered and the remaining time before the operation times out.
	 * 
	 * @param clientId id of the sender or receiver or client object that encountered the exception.
	 * @param lastException last exception encountered
	 * @param remainingTime remainingTime to retry before the operation times out
	 * @return duration after which the operation will be retried. Returns null when the operation should not retried.
	 */
	public Duration getNextRetryInterval(String clientId, Exception lastException, Duration remainingTime)
	{
		if (!RetryPolicy.isRetryableException(lastException))
		{
			return null;
		}
		
		int baseWaitTime = 0;
		if (lastException != null &&
                (lastException instanceof ServerBusyException || (lastException.getCause() != null && lastException.getCause() instanceof ServerBusyException)))
        {
            baseWaitTime += ClientConstants.SERVER_BUSY_BASE_SLEEP_TIME_IN_SECS;
        }

		return this.onGetNextRetryInterval(clientId, lastException, remainingTime, baseWaitTime);
	}

	/**
	 * Adjusts the interval after which nextRetry should be attempted, based on the last exception encountered, the remaining time before the operation times out and the minimum wait time before retry.
	 * Clients can override this method to specify a wait time based on the exception encountered.
	 * @param clientId id of the sender or receiver or client object that encountered the exception.
	 * @param lastException last exception encountered
	 * @param remainingTime remainingTime to retry before the operation times out
	 * @param baseWaitTime minimum wait time determined by the base retry policy. Overriding methods can return a different value.
	 * @return duration after which the operation will be retried. Returns null when the operation should not retried
	 */
	protected abstract Duration onGetNextRetryInterval(String clientId, Exception lastException, Duration remainingTime, int baseWaitTime);

	@Override
	public String toString()
	{
		return this.name;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy