use of io.mantisrx.mql.jvm.core.Query in project mantis by Netflix.
the class PushServerSse method createServer.
@Override
public RxServer<?, ?> createServer() {
RxServer<HttpServerRequest<String>, HttpServerResponse<ServerSentEvent>> server = RxNetty.newHttpServerBuilder(port, new RequestHandler<String, ServerSentEvent>() {
@Override
public Observable<Void> handle(HttpServerRequest<String> request, final HttpServerResponse<ServerSentEvent> response) {
final Map<String, List<String>> queryParameters = request.getQueryParameters();
final Counter sseProcessedCounter;
final Counter sseDroppedCounter;
// heartbeat state
boolean enableHeartbeats = false;
boolean enableBinaryOutput = false;
final AtomicLong heartBeatReadIdleSec = new AtomicLong(2);
SerializedSubject<String, String> metaMsgSubject = PublishSubject.<String>create().toSerialized();
final AtomicLong metaMessagesFreqMSec = new AtomicLong(1000);
boolean enableMetaMessages = false;
final AtomicLong lastWriteTime = new AtomicLong();
Subscription heartbeatSubscription = null;
Subscription metaMsgSubscription = null;
// sample state
boolean enableSampling = false;
long samplingTimeMsec = 0;
// client state
String groupId = null;
String slotId = null;
String id = null;
Func1<T, Boolean> predicateFunction = null;
if (predicate != null) {
predicateFunction = predicate.call(queryParameters);
}
byte[] delimiter = CompressionUtils.MANTIS_SSE_DELIMITER_BINARY;
if (queryParameters != null && !queryParameters.isEmpty()) {
if (queryParameters.containsKey(MantisSSEConstants.ID)) {
id = queryParameters.get(MantisSSEConstants.ID).get(0);
}
if (queryParameters.containsKey(MantisSSEConstants.SLOT_ID)) {
slotId = queryParameters.get(MantisSSEConstants.SLOT_ID).get(0);
}
// support groupId and clientId for grouping
if (queryParameters.containsKey(MantisSSEConstants.GROUP_ID)) {
groupId = queryParameters.get(MantisSSEConstants.GROUP_ID).get(0);
}
if (queryParameters.containsKey(MantisSSEConstants.CLIENT_ID)) {
groupId = queryParameters.get(MantisSSEConstants.CLIENT_ID).get(0);
}
if (queryParameters.containsKey(MantisSSEConstants.HEARTBEAT_SEC)) {
heartBeatReadIdleSec.set(Long.parseLong(queryParameters.get(MantisSSEConstants.HEARTBEAT_SEC).get(0)));
if (heartBeatReadIdleSec.get() < 1) {
throw new IllegalArgumentException("Sampling rate too low: " + samplingTimeMsec);
}
enableHeartbeats = true;
}
if (queryParameters != null && queryParameters.containsKey(MantisSSEConstants.MANTIS_ENABLE_COMPRESSION)) {
String enableBinaryOutputStr = queryParameters.get(MantisSSEConstants.MANTIS_ENABLE_COMPRESSION).get(0);
if ("true".equalsIgnoreCase(enableBinaryOutputStr)) {
logger.info("Binary compression requested");
enableBinaryOutput = true;
}
}
if (queryParameters.containsKey(MantisSSEConstants.ENABLE_PINGS)) {
String enablePings = queryParameters.get(MantisSSEConstants.ENABLE_PINGS).get(0);
if ("true".equalsIgnoreCase(enablePings)) {
enableHeartbeats = true;
}
}
if (queryParameters.containsKey(MantisSSEConstants.ENABLE_META_MESSAGES)) {
String enableMetaMessagesStr = queryParameters.get(MantisSSEConstants.ENABLE_META_MESSAGES).get(0);
if ("true".equalsIgnoreCase(enableMetaMessagesStr)) {
enableMetaMessages = true;
}
}
if (queryParameters.containsKey(MantisSSEConstants.META_MESSAGES_SEC)) {
metaMessagesFreqMSec.set(Long.parseLong(queryParameters.get(MantisSSEConstants.META_MESSAGES_SEC).get(0)));
if (metaMessagesFreqMSec.get() < 250) {
throw new IllegalArgumentException("Meta message frequence rate too low: " + metaMessagesFreqMSec.get());
}
enableMetaMessages = true;
}
if (queryParameters.containsKey(MantisSSEConstants.SAMPLE)) {
samplingTimeMsec = Long.parseLong(queryParameters.get(MantisSSEConstants.SAMPLE).get(0)) * 1000;
if (samplingTimeMsec < 50) {
throw new IllegalArgumentException("Sampling rate too low: " + samplingTimeMsec);
}
enableSampling = true;
}
if (queryParameters.containsKey(MantisSSEConstants.SAMPLE_M_SEC)) {
samplingTimeMsec = Long.parseLong(queryParameters.get(MantisSSEConstants.SAMPLE_M_SEC).get(0));
if (samplingTimeMsec < 50) {
throw new IllegalArgumentException("Sampling rate too low: " + samplingTimeMsec);
}
enableSampling = true;
}
if (queryParameters.containsKey(MantisSSEConstants.MANTIS_COMPRESSION_DELIMITER)) {
String rawDelimiter = queryParameters.get(MantisSSEConstants.MANTIS_COMPRESSION_DELIMITER).get(0);
if (rawDelimiter != null && !rawDelimiter.isEmpty()) {
delimiter = rawDelimiter.getBytes();
}
}
if (queryParameters.containsKey(MantisSSEConstants.MQL)) {
String query = queryParameters.get(MantisSSEConstants.MQL).get(0);
if ((Boolean) mqlParses.invoke(query)) {
Query q = (Query) mqlMakeQuery.invoke(groupId, query);
predicateFunction = (T datum) -> datum instanceof Map ? q.matches((Map) datum) : true;
}
}
}
InetSocketAddress socketAddress = (InetSocketAddress) response.getChannel().remoteAddress();
Metrics metrics;
if (groupId == null) {
String address = socketAddress.getAddress().toString();
metrics = registerSseMetrics(address, address);
} else {
metrics = registerSseMetrics(groupId, socketAddress.getAddress().toString());
}
sseProcessedCounter = metrics.getCounter(PROCESSED_COUNTER_METRIC_NAME);
sseDroppedCounter = metrics.getCounter(DROPPED_COUNTER_METRIC_NAME);
response.getHeaders().set("Access-Control-Allow-Origin", "*");
response.getHeaders().set("content-type", "text/event-stream");
response.getHeaders().set("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate");
response.getHeaders().set("Pragma", "no-cache");
response.flush();
if (queryParameters != null && requestPreprocessor != null) {
requestPreprocessor.call(queryParameters, processorState);
}
if (enableMetaMessages && metaMessagesFreqMSec.get() > 0) {
logger.info("Enabling Meta messages, interval : " + metaMessagesFreqMSec.get() + " ms");
metaMsgSubscription = metaMsgSubject.throttleLast(metaMessagesFreqMSec.get(), TimeUnit.MILLISECONDS).doOnNext((String t) -> {
if (t != null && !t.isEmpty()) {
long currentTime = System.currentTimeMillis();
ByteBuf data = response.getAllocator().buffer().writeBytes(t.getBytes());
response.writeAndFlush(new ServerSentEvent(data));
lastWriteTime.set(currentTime);
}
}).subscribe();
}
if (enableHeartbeats && heartBeatReadIdleSec.get() > 0) {
logger.info("Enabling hearts, interval: " + heartBeatReadIdleSec);
heartbeatSubscription = Observable.interval(2, heartBeatReadIdleSec.get(), TimeUnit.SECONDS).doOnNext((Long t1) -> {
long currentTime = System.currentTimeMillis();
long diff = (currentTime - lastWriteTime.get()) / 1000;
if (diff > heartBeatReadIdleSec.get()) {
ByteBuf data = response.getAllocator().buffer().writeBytes("ping".getBytes());
response.writeAndFlush(new ServerSentEvent(data));
lastWriteTime.set(currentTime);
}
}).subscribe();
}
Action0 connectionClosedCallback = null;
if (queryParameters != null && requestPostprocessor != null) {
connectionClosedCallback = new Action0() {
@Override
public void call() {
requestPostprocessor.call(queryParameters, processorState);
}
};
}
class SubscribeCallback implements Action0 {
@Override
public void call() {
if (queryParameters != null && subscribeProcessor != null) {
subscribeProcessor.call(queryParameters, processorState);
}
}
}
return manageConnectionWithCompression(response, socketAddress.getHostString(), socketAddress.getPort(), groupId, slotId, id, lastWriteTime, enableHeartbeats, heartbeatSubscription, enableSampling, samplingTimeMsec, metaMsgSubject, metaMsgSubscription, predicateFunction, connectionClosedCallback, sseProcessedCounter, sseDroppedCounter, new SubscribeCallback(), enableBinaryOutput, true, delimiter);
}
}).pipelineConfigurator(PipelineConfigurators.serveSseConfigurator()).channelOption(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(1024 * 1024, 5 * 1024 * 1024)).build();
return server;
}
use of io.mantisrx.mql.jvm.core.Query in project mantis by Netflix.
the class MQL method makeSupersetProjector.
@SuppressWarnings("unchecked")
public static Function<Map<String, Object>, Map<String, Object>> makeSupersetProjector(HashSet<Query> queries) {
ArrayList<String> qs = new ArrayList<>(queries.size());
for (Query query : queries) {
qs.add(query.getRawQuery());
}
IFn ssProjector = (IFn) cljSuperset.invoke(new ArrayList(qs));
return (datum) -> (Map<String, Object>) (ssProjector.invoke(datum));
}
use of io.mantisrx.mql.jvm.core.Query in project mantis by Netflix.
the class AbstractAckableTaggingStage method tagData.
@SuppressWarnings("unchecked")
protected List<TaggedData> tagData(Map<String, Object> d, Context context) {
List<TaggedData> taggedDataList = new ArrayList<>();
boolean metaEvent = isMetaEvent(d);
Metrics metrics = context.getMetricsRegistry().getMetric("mql");
Collection<Query> queries = MQLQueryManager.getInstance().getRegisteredQueries();
Iterator<Query> it = queries.iterator();
while (it.hasNext()) {
Query query = it.next();
try {
if (metaEvent) {
TaggedData tg = new TaggedData(d);
tg.addMatchedClient(query.getSubscriptionId());
taggedDataList.add(tg);
} else if (query.matches(d)) {
Map<String, Object> projected = query.project(d);
projected.put(MANTIS_META_SOURCE_NAME, d.get(MANTIS_META_SOURCE_NAME));
projected.put(MANTIS_META_SOURCE_TIMESTAMP, d.get(MANTIS_META_SOURCE_TIMESTAMP));
TaggedData tg = new TaggedData(projected);
tg.addMatchedClient(query.getSubscriptionId());
taggedDataList.add(tg);
}
} catch (Exception ex) {
if (ex instanceof ClassNotFoundException) {
logger.error("Error loading MQL: " + ex.getMessage());
ex.printStackTrace();
metrics.getCounter(MQL_CLASSLOADER_ERROR).increment();
} else {
ex.printStackTrace();
metrics.getCounter(MQL_FAILURE).increment();
logger.error("MQL Error: " + ex.getMessage());
logger.error("MQL Query: " + query.getRawQuery());
logger.error("MQL Datum: " + d);
}
} catch (Error e) {
metrics.getCounter(MQL_FAILURE).increment();
if (!errorLogged.get()) {
logger.error("caught Error when processing MQL {} on {}", query.getRawQuery(), d.toString(), e);
errorLogged.set(true);
}
}
}
return taggedDataList;
}
use of io.mantisrx.mql.jvm.core.Query in project mantis by Netflix.
the class MQLQueryManager method registerQuery.
public void registerQuery(String id, String query) {
query = MQL.transformLegacyQuery(query);
Query q = MQL.makeQuery(id, query);
queries.put(id, q);
}
use of io.mantisrx.mql.jvm.core.Query in project mantis by Netflix.
the class TaggingStage method tagData.
private List<TaggedData> tagData(Map<String, Object> d, Context context) {
List<TaggedData> taggedDataList = new ArrayList<>();
Metrics metrics = context.getMetricsRegistry().getMetric(new MetricGroupId("mql"));
Collection<Query> queries = MQLQueryManager.getInstance().getRegisteredQueries();
Iterator<Query> it = queries.iterator();
while (it.hasNext()) {
Query query = it.next();
try {
if (query.matches(d)) {
Map<String, Object> projected = query.project(d);
projected.put(MANTIS_META_SOURCE_NAME, SYNTHETIC_REQUEST_SOURCE);
projected.put(MANTIS_META_SOURCE_TIMESTAMP, System.currentTimeMillis());
TaggedData tg = new TaggedData(projected);
tg.addMatchedClient(query.getSubscriptionId());
taggedDataList.add(tg);
}
} catch (Exception ex) {
if (ex instanceof ClassNotFoundException) {
log.error("Error loading MQL: " + ex.getMessage());
ex.printStackTrace();
metrics.getCounter(MQL_CLASSLOADER_ERROR).increment();
} else {
ex.printStackTrace();
metrics.getCounter(MQL_FAILURE).increment();
log.error("MQL Error: " + ex.getMessage());
log.error("MQL Query: " + query.getRawQuery());
log.error("MQL Datum: " + d);
}
} catch (Error e) {
metrics.getCounter(MQL_FAILURE).increment();
if (!errorLogged.get()) {
log.error("caught Error when processing MQL {} on {}", query.getRawQuery(), d.toString(), e);
errorLogged.set(true);
}
}
}
return taggedDataList;
}
Aggregations