package uk.bl.monitrix.heritrix.ingest;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import play.Logger;
import akka.actor.Actor;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.actor.UntypedActorFactory;
import scala.concurrent.Await;
import scala.concurrent.Future;
import akka.pattern.Patterns;
import scala.concurrent.duration.Duration;
import akka.util.Timeout;
import uk.bl.monitrix.database.DBIngestConnector;
import uk.bl.monitrix.heritrix.ingest.IngestControlMessage.Command;
/**
* The IngestWatcher provides a control entry point into the ingest system. The actual work
* of monitoring and ingest is handled by the {@link IngestActor}.
* @author Rainer Simon <rainer.simon@ait.ac.at>
*/
public class IngestWatcher {
private ActorRef ingestActor;
public IngestWatcher(final DBIngestConnector db, final ActorSystem system) {
this.ingestActor = system.actorOf(new Props(new UntypedActorFactory() {
private static final long serialVersionUID = 1373336745955431875L;
@Override
public Actor create() {
return new IngestActor(db, system);
}
}), "ingest-actor");
refresh();
}
/**
* Re-syncs the status of the IngestWatcher with the DB-backed IngestSchedule
*/
public void refresh() {
ingestActor.tell(new IngestControlMessage(Command.SYNC_WITH_SCHEDULE), ActorRef.noSender());
}
/**
* Starts the watcher.
*/
public void startWatching() {
Logger.info("Starting ingest watcher");
ingestActor.tell(new IngestControlMessage(Command.START), ActorRef.noSender());
}
/**
* Stops the watcher.
*/
public void stopWatching() {
Logger.info("Stopping ingest watcher");
ingestActor.tell(new IngestControlMessage(Command.STOP), ActorRef.noSender());
}
/**
* Returns true if the underlying ingest actor is still alive, or whether
* it has crashed.
* @return <code>true</code> if the actor is alive and kicking
*/
public boolean isAlive() {
return true;
}
/**
* Returns true if the ingest process is running - i.e. if the actor is alive
* and has not yet stopped the ingest loop.
* @return <code>true</code> if the ingest loop is running
*/
public boolean isRunning() {
if (!isAlive())
return false;
try {
Future<Object> future =
Patterns.ask(ingestActor, new IngestControlMessage(Command.CHECK_RUNNING), new Timeout(Duration.create(5, TimeUnit.SECONDS)));
Object result = Await.result(future, Duration.create(30, TimeUnit.SECONDS));
return (Boolean) result;
} catch (Exception e) {
return false;
}
}
@SuppressWarnings("unchecked")
public Map<String, IngestStatus> getStatus() {
try {
Future<Object> future =
Patterns.ask(ingestActor, new IngestControlMessage(Command.GET_STATUS), new Timeout(Duration.create(5, TimeUnit.SECONDS)));
Object result = Await.result(future, Duration.create(30, TimeUnit.SECONDS));
return (Map<String, IngestStatus>) result;
} catch (Exception e) {
return new HashMap<String, IngestStatus>();
}
}
}