package dk.statsbiblioteket.medieplatform.autonomous;
import org.slf4j.Logger;
import dk.statsbiblioteket.util.Strings;
import org.slf4j.LoggerFactory;
import java.util.Date;
/**
* The purpose of this class is the decorate a runnable component with additional behaivour.
* Unless the component specifically requests it (by settting presevable=false on the result collector) the
* result will be written back to DOMS
*/
public class AutonomousWorker<T extends Item> implements Runnable {
private static Logger log = LoggerFactory.getLogger(AutonomousWorker.class);
private RunnableComponent<T> component;
private ResultCollector resultCollector;
private T item;
private EventStorer<T> eventStorer;
private boolean pause = false;
private boolean stop = false;
public AutonomousWorker(RunnableComponent<T> component, ResultCollector resultCollector, T item,
EventStorer<T> eventStorer) {
this.component = component;
this.resultCollector = resultCollector;
this.item = item;
this.eventStorer = eventStorer;
}
private String getComponentFormattedName() {
return component.getComponentName() + "-" + component.getComponentVersion();
}
@Override
public void run() {
try {
try {
try {
//do work
resultCollector.setTimestamp(new Date());
component.doWorkOnItem(item, resultCollector);
} catch (Throwable e) {
log.warn("Component threw exception", e);
//the work failed
resultCollector.addFailure(item.getFullID(),
"exception",
component.getClass().getSimpleName(),
"Component threw exception: " + e.toString(),
Strings.getStackTrace(e));
}
} finally {
resultCollector.setDuration(new Date().getTime() - resultCollector.getTimestamp().getTime());
if (resultCollector.isPreservable()) {
try {
preserveResult(item, resultCollector);
} catch (Throwable t) {
resultCollector.addFailure(item.getFullID(),
"exception",
component.getClass().getSimpleName(),
"Caught exception '" + t.toString() + "'while attempting to preserve result for item " + item.getFullID(),
Strings.getStackTrace(t));
}
} else {
log.info("The result collector is not marked as preservable, so it is not preserved in DOMS, but embedded here instead: {}",
resultCollector.toReport());
}
}
} finally {
if (!resultCollector.isSuccess()) {
log.error("Failed for item {}. The report was {}", item.getFullID(), resultCollector.toReport());
}
}
}
public ResultCollector getResultCollector() {
return resultCollector;
}
/**
* This method stores the event back into DOMS, so it should be visible to the SBOI soonish
*
* @param item the item worked on
* @param result the result of the work
*/
private void preserveResult(T item, ResultCollector result) throws CommunicationException, NotFoundException {
while (pause && !stop) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
//just keep sleeping
}
}
if (stop) {
log.warn("The worker is stopped, so the result will not be preserved. The result was '{}'",
result.toReport());
return;
}
eventStorer.appendEventToItem(item,
getComponentFormattedName(),
result.getTimestamp(),
result.toReport(),
component.getEventID(),
result.isSuccess());
}
public T getItem() {
return item;
}
public void setPause(boolean pause) {
this.pause = pause;
}
public void setStop(boolean stop) {
this.stop = stop;
}
}