package com.bao.lc.httpcommand;
import org.apache.commons.chain.Context;
import org.apache.commons.chain.Filter;
import org.apache.commons.chain.Command;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.bao.lc.bean.IDValuePair;
import com.bao.lc.bean.ResultCode;
import com.bao.lc.httpcommand.impl.DefaultCommandBuilder;
import com.bao.lc.httpcommand.params.HttpCommandPNames;
import com.bao.lc.httpcommand.params.HttpCommandParams;
public class RetryHttpCommand implements Filter
{
private static Log log = LogFactory.getLog(RetryHttpCommand.class);
/*Input parameters*/
private CommandBuilder commandBuilder = null;
private CommandRetryStrategy retryStrategy = null;
/*Cache the last generated command for method "postprocess" usage*/
private Command command = null;
public RetryHttpCommand(CommandBuilder commandBuilder, CommandRetryStrategy retryStrategy)
{
if(commandBuilder == null)
{
throw new IllegalArgumentException("commandBuilder can't be null");
}
this.commandBuilder = commandBuilder;
this.retryStrategy = retryStrategy;
}
public RetryHttpCommand(Command command, CommandRetryStrategy retryStrategy)
{
this(new DefaultCommandBuilder(command), retryStrategy);
}
@Override
public boolean execute(Context context) throws Exception
{
boolean result = Command.PROCESSING_COMPLETE;
int execCount = 0;
while(true)
{
execCount++;
try
{
log.debug("Attempt to execute: " + execCount);
//Get the command
command = commandBuilder.build(context, execCount);
result = command.execute(context);
IDValuePair rc = HttpCommandParams.getResultCode(context);
//Get out of the loop in 2 cases:
//1. Success
//2. Fail but RetryStrategy tell us to retry
if(rc == ResultCode.RC_OK || !retryStrategy.shouldRetry(context, execCount, rc))
{
break;
}
}
catch(Exception e)
{
if(!retryStrategy.shouldRetry(context, execCount, e))
{
throw e;
}
}
}
return result;
}
@Override
public boolean postprocess(Context context, Exception exception)
{
if(command instanceof Filter)
{
return ((Filter) command).postprocess(context, exception);
}
// save the exception command
if(!context.containsKey(HttpCommandPNames.EXCEPTION_COMMAND))
{
context.put(HttpCommandPNames.EXCEPTION_COMMAND, this);
}
return false;
}
}