org.yamcs.api.artemis.ArtemisEventProducer Maven / Gradle / Ivy
Show all versions of yamcs-artemis Show documentation
package org.yamcs.api.artemis;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yamcs.ConfigurationException;
import org.yamcs.YamcsException;
import org.yamcs.api.AbstractEventProducer;
import org.yamcs.api.YamcsConnectionProperties;
import org.yamcs.protobuf.Yamcs.Event;
import org.yamcs.protobuf.Yamcs.ProtoDataType;
import org.yamcs.utils.TimeEncoding;
import org.yaml.snakeyaml.Yaml;
/**
* An EventProducer that publishes events over Artemis
*
* By default, repeated message are detected and reduced, resulting in pseudo events with a message like 'last event
* repeated X times'. This behaviour can be turned off.
*/
public class ArtemisEventProducer extends AbstractEventProducer implements ConnectionListener {
static final String CONF_REPEATED_EVENT_REDUCTION = "repeatedEventReduction";
YamcsConnector yconnector;
SimpleString address;
YamcsClient yclient;
static Logger logger = LoggerFactory.getLogger(ArtemisEventProducer.class);
static final int MAX_QUEUE_SIZE = 1000;
ArrayBlockingQueue queue = new ArrayBlockingQueue<>(MAX_QUEUE_SIZE);
public ArtemisEventProducer(YamcsConnectionProperties ycd) {
if (ycd.getInstance() == null) {
throw new IllegalArgumentException("Please provide the yamcs instance to connect to");
}
yconnector = new YamcsConnector();
yconnector.setMaxAttempts(Integer.MAX_VALUE);
yconnector.addConnectionListener(this);
yconnector.connect(ycd);
address = Protocol.getEventRealtimeAddress(ycd.getInstance());
InputStream is = ArtemisEventProducer.class.getResourceAsStream("/event-producer.yaml");
boolean repeatedEventReduction = true;
if (is != null) {
Object o = new Yaml().load(is);
if (!(o instanceof Map, ?>)) {
throw new ConfigurationException("event-producer.yaml does not contain a map but a " + o.getClass());
}
@SuppressWarnings("unchecked")
Map m = (Map) o;
if (m.containsKey(CONF_REPEATED_EVENT_REDUCTION)) {
repeatedEventReduction = (Boolean) m.get(CONF_REPEATED_EVENT_REDUCTION);
}
}
if (repeatedEventReduction) {
setRepeatedEventReduction(true, 60000);
}
}
@Override
public void connecting(String url) {
}
@Override
public void connected(String url) {
try {
yclient = yconnector.getSession().newClientBuilder().setDataProducer(true).build();
while (!queue.isEmpty()) {
yclient.sendData(address, ProtoDataType.EVENT, queue.poll());
}
} catch (ArtemisApiException e) {
e.printStackTrace();
}
}
@Override
public void connectionFailed(String url, YamcsException exception) {
logger.warn("Failed to connect to " + url + ": " + exception.getMessage());
}
@Override
public void disconnected() {
}
@Override
public void log(String message) {
}
@Override
public void close() {
try {
yconnector.close();
} catch (ActiveMQException e) {
e.printStackTrace();
}
}
/* (non-Javadoc)
* @see org.yamcs.api.EventProducer#sendEvent(org.yamcs.protobuf.Yamcs.Event)
*/
@Override
public synchronized void sendEvent(Event event) {
logger.debug("Sending Event: {}", event.getMessage());
if (yconnector.isConnected()) {
try {
yclient.sendData(address, ProtoDataType.EVENT, event);
} catch (ArtemisApiException e) {
logger.error("Failed to send event ", e);
}
} else {
queue.offer(event);
}
}
@Override
public String toString() {
return ArtemisEventProducer.class.getName() + " connected to " + yconnector.getUrl();
}
@Override
public long getMissionTime() {
return TimeEncoding.currentInstant();
}
}