package com.temenos.interaction.core.workflow; /* * #%L * interaction-core * %% * Copyright (C) 2012 - 2013 Temenos Holdings N.V. * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * #L% */ import javax.ws.rs.core.Response.Status.Family; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.temenos.interaction.core.command.InteractionCommand; import com.temenos.interaction.core.command.InteractionContext; import com.temenos.interaction.core.command.InteractionException; /** * <p>This command implements a workflow that will retry if there is an error.</p> * Commands are added to this workflow and then retried according to the retry count * and the incremental backoff (configured in milliseconds). * @author aphethean */ public class RetryWorkflowStrategyCommand implements WorkflowCommand { private final static Logger logger = LoggerFactory.getLogger(RetryWorkflowStrategyCommand.class); private InteractionCommand command; private int maxRetryCount; private long maxRetryInterval; /** * Construct with a list of commands to execute. * @param commands * @param maxRetryCount * @param maxRetryInterval (in milliseconds) * @invariant commands not null */ public RetryWorkflowStrategyCommand(InteractionCommand command, int maxRetryCount, long maxRetryInterval) { this.command = command; this.maxRetryCount = maxRetryCount; this.maxRetryInterval = maxRetryInterval; if (command == null) throw new IllegalArgumentException("No commands supplied"); } /** * @throws InteractionException * if Family.SERVER_ERROR error then retry maxRetryCount times * and keep incremental interval according to maxRetryInterval */ private Result commandExecute(InteractionContext ctx) throws InteractionException { Result result = null; int retryCount = -1; while ( ( maxRetryCount - retryCount++ ) > -1 ) { try { result = command.execute(ctx); break; } catch (InteractionException ex) { if (Family.SERVER_ERROR.equals(ex.getHttpStatus().getFamily()) && retryCount < maxRetryCount ) { long nextRetry = maxRetryInterval * (int)Math.pow(2,retryCount); logger.info("iris_request maxRetryCount=" + String.valueOf(maxRetryCount) + " maxRetryInterval=" + String.valueOf(maxRetryInterval) + " retryingNumber=" + String.valueOf(retryCount) + " nextRetryIn=" + String.valueOf(nextRetry) + " seconds"); try { Thread.sleep(nextRetry); } catch (InterruptedException e) { logger.error("InterruptedException: ", e); } } else { throw ex; } } } return result; } @Override public boolean isEmpty() { return command == null; } /** * @throws InteractionException */ @Override public Result execute(InteractionContext ctx) throws InteractionException { assert(command != null); if (ctx == null) throw new IllegalArgumentException("InteractionContext must be supplied"); return commandExecute(ctx); } }