/* * Copyright (c) 2012-2015 iWave Software LLC * All Rights Reserved */ package com.emc.sa.service.vmware.tasks; import org.apache.commons.lang.StringUtils; import com.emc.sa.engine.ExecutionTask; import com.iwave.ext.vmware.VMWareException; import com.iwave.ext.vmware.VMwareUtils; import com.vmware.vim25.MethodFault; /** * Base task for retryable * * @author jonnymiller * * @param <T> */ public abstract class RetryableTask<T> extends ExecutionTask<T> { private static final int DEFAULT_MAX_TRIES = 5; private static final long DEFAULT_DELAY = 10000; private int maxTries = DEFAULT_MAX_TRIES; private long delay = DEFAULT_DELAY; private T result; public int getMaxTries() { return maxTries; } public void setMaxTries(int maxTries) { this.maxTries = maxTries; } public long getDelay() { return delay; } public void setDelay(long delay) { this.delay = delay; } @Override public T executeTask() throws Exception { debug("Executing: %s", getDetail()); int tries = 1; boolean success = tryOnce(tries); while (!success) { tries++; Thread.sleep(delay); logInfo("retryable.task", getName()); beforeRetry(); success = tryOnce(tries); } return result; } private boolean tryOnce(int tries) { try { result = tryExecute(); return true; } catch (VMWareException e) { if (!canRetry(e)) { fail(e); } else if (tries >= maxTries) { logError("retryable.task.max.retries", getName()); fail(e); } String message = getMessage(e); logInfo("retryable.task.failed.retry", getName(), message); return false; } } protected void beforeRetry() { } protected abstract T tryExecute(); protected abstract boolean canRetry(VMWareException e); protected void fail(VMWareException e) { String message = getMessage(e); logError("retryable.task.failed.with.error", getName(), message); throw e; } protected String getMessage(VMWareException e) { String message = null; String defaultMessage = null; Throwable cause = e.getCause(); if (cause instanceof MethodFault) { message = VMwareUtils.getFaultMessage((MethodFault) cause); defaultMessage = cause.getClass().getName(); } else if (cause != null) { message = cause.getMessage(); defaultMessage = cause.getClass().getName(); } else { message = e.getMessage(); defaultMessage = e.getClass().getName(); } return StringUtils.defaultIfBlank(message, defaultMessage); } }