package qa.qcri.aidr.predict.communication;
import java.io.IOException;
import java.util.List;
import org.apache.log4j.Logger;
import qa.qcri.aidr.predict.DataStore;
import qa.qcri.aidr.predict.common.PipelineProcess;
import qa.qcri.aidr.predict.common.Serializer;
import qa.qcri.aidr.predict.common.TaggerConfigurationProperty;
import qa.qcri.aidr.predict.common.TaggerConfigurator;
import qa.qcri.aidr.predict.data.Document;
import qa.qcri.aidr.predict.data.DocumentJSONConverter;
import redis.clients.jedis.Jedis;
/**
* OutputMatcher listens to a Redis queue for Documents that are ready for
* output to consumers. Documents are matched against connected clients based on
* the filters they provided on connection.
*
* @author jrogstadius
*/
public class OutputMatcher extends PipelineProcess {
public int inputCount = 0;
public int outputCount = 0;
private static Logger logger = Logger.getLogger(OutputMatcher.class);
public void run() {
while (true) {
if (Thread.interrupted())
return;
// Get an item from the input queue
Document doc = getItem();
inputCount++;
if (doc == null)
continue;
pushToTaskWriteQueue(doc);
//logger.info("Going to add nominal_labels before final output to REDIS");
String jsonDoc = DocumentJSONConverter.getDocumentSetJson(doc);
pushToClients(doc, jsonDoc);
//logger.info("Going to push into REDIS json String: " + jsonDoc);
PushToRedisStream(doc.getCrisisCode(), jsonDoc);
outputCount++;
}
}
private Document getItem() {
Jedis jedis = DataStore.getJedisConnection();
List<byte[]> byteDoc = jedis
.blpop(60,
TaggerConfigurator
.getInstance()
.getProperty(
TaggerConfigurationProperty.REDIS_FOR_OUTPUT_QUEUE)
.getBytes());
DataStore.close(jedis);
if (byteDoc == null) // This is null if the blpop timed out
return null;
try {
return Serializer.deserialize(byteDoc.get(1));
} catch (ClassNotFoundException | IOException e) {
logger.error("Exception when parsing document set from stream.");
return null;
}
}
private void pushToTaskWriteQueue(Document doc) {
Jedis jedis = DataStore.getJedisConnection();
try {
jedis.rpush(
TaggerConfigurator
.getInstance()
.getProperty(
TaggerConfigurationProperty.REDIS_LABEL_TASK_WRITE_QUEUE)
.getBytes(), Serializer.serialize(doc));
} catch (IOException e) {
logger.warn("Exception while serializing DocumentSet.");
}
DataStore.close(jedis);
}
private void pushToClients(Document doc, String docJson) {
List<HttpOutputWorker> workers = HttpOutputWorkerIndex.getInstance()
.getWorkers(doc.getCrisisCode());
// log(LogLevel.INFO, "Matching clients for event " + doc.getCrisisID()
// + ": " + workers.size() + " (checking filters)");
for (HttpOutputWorker worker : workers) {
// Pass to stream if the consumer has not specified any filters
// beyond the event ID
// OR if any filter matches the labels of the document
// if (worker.filter.crisisCode == doc.getCrisisCode() &&
// (!worker.filter.hasAttributeFilters() || worker.filter.match(doc.getLabels(DocumentLabel.class)))) {
if (worker.filter.crisisCode.equals(doc.getCrisisCode())) {
worker.push(docJson);
}
}
}
public static void PushToRedisStream(String crisisCode, String docJson) {
Jedis redis = DataStore.getJedisConnection();
redis.publish(
TaggerConfigurator
.getInstance()
.getProperty(
TaggerConfigurationProperty.REDIS_OUTPUT_CHANNEL_PREFIX)
+ "." + crisisCode, docJson);
DataStore.close(redis);
}
@Override
protected void processItem(Document item) {
run();
}
}