package won.matcher.service.nodemanager.actor;
import akka.actor.ActorRef;
import akka.actor.OneForOneStrategy;
import akka.actor.SupervisorStrategy;
import akka.camel.CamelMessage;
import akka.camel.javaapi.UntypedConsumerActor;
import akka.cluster.pubsub.DistributedPubSub;
import akka.cluster.pubsub.DistributedPubSubMediator;
import akka.event.Logging;
import akka.event.LoggingAdapter;
import akka.japi.Function;
import scala.concurrent.duration.Duration;
import won.matcher.service.common.event.NeedEvent;
import won.matcher.service.common.service.monitoring.MonitoringService;
import org.apache.jena.riot.Lang;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import won.matcher.service.crawler.msg.CrawlUriMessage;
import won.matcher.service.crawler.msg.ResourceCrawlUriMessage;
/**
* Camel actor represents the need consumer protocol to a won node.
* It is used to listen at the WoN node for events about new created needs,
* activated needs and deactivated needs. Depending on the endpoint it
* might be used with different protocols (e.g. JMS over activemq).
*
* User: hfriedrich
* Date: 28.04.2015
*/
@Component
@Scope("prototype")
public class NeedConsumerProtocolActor extends UntypedConsumerActor
{
private static final String MSG_HEADER_METHODNAME = "methodName";
private static final String MSG_HEADER_METHODNAME_NEEDCREATED = "needCreated";
private static final String MSG_HEADER_METHODNAME_NEEDACTIVATED = "needActivated";
private static final String MSG_HEADER_METHODNAME_NEEDDEACTIVATED = "needDeactivated";
private static final String MSG_HEADER_WON_NODE_URI = "wonNodeURI";
private static final String MSG_HEADER_NEED_URI = "needUri";
private final String endpoint;
private ActorRef pubSubMediator;
private LoggingAdapter log = Logging.getLogger(getContext().system(), this);
@Autowired
private MonitoringService monitoringService;
public NeedConsumerProtocolActor(String endpoint) {
this.endpoint = endpoint;
pubSubMediator = DistributedPubSub.get(getContext().system()).mediator();
}
@Override
public String getEndpointUri() {
return endpoint;
}
@Override
public void onReceive(final Object message) throws Exception {
if (message instanceof CamelMessage) {
CamelMessage camelMsg = (CamelMessage) message;
String needUri = (String) camelMsg.getHeaders().get(MSG_HEADER_NEED_URI);
String wonNodeUri = (String) camelMsg.getHeaders().get(MSG_HEADER_WON_NODE_URI);
// monitoring code
monitoringService.startClock(MonitoringService.NEED_HINT_STOPWATCH, needUri);
// process the incoming need event
if (needUri != null && wonNodeUri != null) {
Object methodName = camelMsg.getHeaders().get(MSG_HEADER_METHODNAME);
if (methodName != null) {
log.debug("Received event '{}' for needUri '{}' and wonNeedUri '{}' and publish it to matchers",
methodName, needUri, wonNodeUri);
// publish a need event to all the (distributed) matchers
NeedEvent event = null;
long crawlDate = System.currentTimeMillis();
if (methodName.equals(MSG_HEADER_METHODNAME_NEEDCREATED)) {
event = new NeedEvent(needUri, wonNodeUri, NeedEvent.TYPE.CREATED, crawlDate,
camelMsg.body().toString(), Lang.TRIG);
pubSubMediator.tell(new DistributedPubSubMediator.Publish(event.getClass().getName(), event), getSelf());
} else if (methodName.equals(MSG_HEADER_METHODNAME_NEEDACTIVATED)) {
event = new NeedEvent(needUri, wonNodeUri, NeedEvent.TYPE.ACTIVATED, crawlDate,
camelMsg.body().toString(), Lang.TRIG);
pubSubMediator.tell(new DistributedPubSubMediator.Publish(event.getClass().getName(), event), getSelf());
} else if (methodName.equals(MSG_HEADER_METHODNAME_NEEDDEACTIVATED)) {
event = new NeedEvent(needUri, wonNodeUri, NeedEvent.TYPE.DEACTIVATED, crawlDate,
camelMsg.body().toString(), Lang.TRIG);
pubSubMediator.tell(new DistributedPubSubMediator.Publish(event.getClass().getName(), event), getSelf());
} else {
unhandled(message);
}
// let the crawler save the data of this event too
ResourceCrawlUriMessage resMsg = new ResourceCrawlUriMessage(
needUri, needUri, wonNodeUri, CrawlUriMessage.STATUS.SAVE, crawlDate);
resMsg.setSerializedResource(camelMsg.body().toString());
resMsg.setSerializationFormat(Lang.TRIG);
pubSubMediator.tell(new DistributedPubSubMediator.Publish(resMsg.getClass().getName(), resMsg), getSelf());
return;
}
}
}
unhandled(message);
}
@Override
public SupervisorStrategy supervisorStrategy() {
SupervisorStrategy supervisorStrategy = new OneForOneStrategy(
0, Duration.Zero(), new Function<Throwable, SupervisorStrategy.Directive>()
{
@Override
public SupervisorStrategy.Directive apply(Throwable t) throws Exception {
log.warning("Actor encountered error: {}", t);
// default behaviour
return SupervisorStrategy.escalate();
}
});
return supervisorStrategy;
}
}