package com.infonow.service.recovery.controller;
import java.util.Iterator;
import java.util.List;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import com.infonow.framework.logging.Level;
import com.infonow.framework.logging.Logger;
import com.infonow.framework.service.context.ServiceContext;
import com.infonow.service.recovery.AbstractRunner;
import com.infonow.service.recovery.TranslationOrphan;
import static org.apache.commons.collections4.CollectionUtils.collect;
public class TranslationController extends ServiceCallerBatchController<TranslationOrphan>
{
private static final String NAME = "Translation";
public TranslationController()
{
super(NAME);
}
@Override
public List<TranslationOrphan> loadIds(int numToRead)
{
List<TranslationOrphan> relationOrphans = getRecoveryQueries().getTranslationOrphans(numToRead,"PENDING");//new attribute here named status, gets all the orphans which are in pending state
//TranslationController will load orphans that are in PENDING(or NULL for backward compatibility) status to be processed by TranslationService, when does the entry in the table happen?
return relationOrphans;
}
public void changeStatus()
{
List<TranslationOrphan> relationOrphans = loadIds(10);
}
@Override
protected RecoveryRunner<List<TranslationOrphan>, ?> createRunner(List<TranslationOrphan> ids)
{
return new InowRelationRunner(ids);
}
@Override
protected void cleanUp(RecoveryRunner<List<TranslationOrphan>, ?> runner)
{
List<TranslationOrphan> ids = runner.getId();//skip the orphans which are in pending or inprogress state
//loop over ids, create a new list of ids without inprogress and pending status
System.out.println("ids");
System.out.println(ids);
getRecoveryQueries().deleteTranslateOrphans(ids);
}
@Override
public int getNumberOfIdsPerBatch()
{
return getNumberOfIdsToRead();
}
/**
* The Runnable instance use to process a batch of staging Addresses
*/
private class InowRelationRunner extends AbstractRunner<List<TranslationOrphan>, Object>
{
ServiceContext _context = null;
private Logger LOG = Logger.getLogger(TranslationOrphan.class.getName());
InowRelationRunner(List<TranslationOrphan> ids)
{
super(ids, NAME, getService(), getTransactionTemplate());
_context = new ServiceContext();
_context.setContextType("default");
}
@Override
public Object loadDataObject(List<TranslationOrphan> ids)
{
return loadMatchType(ids);
}
@Override
public Object loadUserObject(List<TranslationOrphan> ids)
{
// There is a bug in AbstractRunner where the userObject and userData are swapped.
// I don't want to change it because it might break every service, so I'll just
// flip the objects here like the other services seem to do.
// This is actually the userData in the service.
return ids;
}
@Override
public String loadMatchType(List<TranslationOrphan> ids)
{
return null;
}
@Override
public ServiceContext createServiceContext(Object dataObject)
{
return _context;
}
@Override
protected void handleRunException(Exception exception)
{
// We are going to make a new orphan with an incremented retry count
// and put it back in the queue.
List<TranslationOrphan> oldOrphans = (List<TranslationOrphan>) this.getId();
for (Iterator<TranslationOrphan> i = oldOrphans.iterator(); i.hasNext();)
{
TranslationOrphan oldOrphan = i.next();
long newRetryCount = oldOrphan.getRetryCount() + 1;
// First, compute the severity of the exception to be logged based on the retryCount.
Level loggingLevel = Level.WARNING;
// We only make it SEVERE if the retryCount is a multiple of 10
// to avoid hammering engineering support with e-mails.
if ((newRetryCount % 10) == 0)
{
loggingLevel = Level.SEVERE;
}
LOG.log(loggingLevel,
getDescription() + ": Error processing id - " + getId().toString() + ", re-submitting orphan.",
exception);
PlatformTransactionManager txnMgr = null;
TransactionStatus status = null;
try
{
txnMgr = _transactionTemplate.getTransactionManager();
status = txnMgr.getTransaction(
new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW));
double delayMinutesAsDouble = 0.0;
int delayMinutesAsInteger = 0;
// Compute the delay minutes for the new orphan.
// Since there is the potential for numeric overflows,
// we are wrapping the math in a try/catch block.
try
{
delayMinutesAsDouble = Math.pow(2, newRetryCount);
delayMinutesAsInteger = (int) delayMinutesAsDouble;
}
catch (Exception e)
{
delayMinutesAsInteger = 7 * 24 * 60; // Push re-try out to 7 days if numeric overflows occur.
}
getOrchestrationDao().insertTranslationOrphan(delayMinutesAsInteger, oldOrphan.getInowProfileSid(),
newRetryCount);
try
{
if (!status.isRollbackOnly())
{
txnMgr.commit(status);
}
}
catch (Exception e)
{
String msg = getDescription() + ": Error processing id - " + getId().toString();
LOG.log(Level.SEVERE, msg, e);
}
}
catch (Exception e)
{
String msg = getDescription() + ": Error processing id - " + getId().toString();
LOG.log(Level.SEVERE, msg, e);
}
finally
{
try
{
if (txnMgr != null && status != null && !status.isCompleted())
{
txnMgr.rollback(status);
}
}
catch (Exception ee)
{
String msg = getDescription() + ": Error processing id - " + getId().toString();
LOG.log(Level.SEVERE, msg, ee);
}
}
}
}
} // end inner-class InowRelationRunner
}
Comments