use of io.reactivx.mantis.operators.DropOperator in project mantis by Netflix.
the class WorkerMetricHandler method start.
private void start() {
final AtomicReference<List<Subscription>> ref = new AtomicReference<>(new ArrayList<>());
masterClientApi.schedulingChanges(jobId).doOnNext(jobSchedulingInfo -> {
final Map<Integer, WorkerAssignments> workerAssignments = jobSchedulingInfo.getWorkerAssignments();
for (Map.Entry<Integer, WorkerAssignments> workerAssignmentsEntry : workerAssignments.entrySet()) {
final WorkerAssignments workerAssignment = workerAssignmentsEntry.getValue();
logger.debug("setting numWorkers={} for stage={}", workerAssignment.getNumWorkers(), workerAssignment.getStage());
numWorkersByStage.put(workerAssignment.getStage(), workerAssignment.getNumWorkers());
workerHostsByStage.put(workerAssignment.getStage(), new ArrayList<>(workerAssignment.getHosts().values()));
}
}).subscribe();
logger.info("Starting worker metric handler with autoscale config {}", autoScaleMetricsConfig);
metricDataSubject.groupBy(metricData -> metricData.getStage()).lift(new DropOperator<>(WorkerMetricHandler.class.getName())).doOnNext(go -> {
final Integer stage = go.getKey();
final Subscription s = go.lift(new StageMetricDataOperator(stage, lookupNumWorkersByStage, autoScaleMetricsConfig)).subscribe();
logger.info("adding subscription for stage {} StageMetricDataOperator", stage);
ref.get().add(s);
}).doOnUnsubscribe(() -> {
for (Subscription s : ref.get()) s.unsubscribe();
}).subscribe();
}
use of io.reactivx.mantis.operators.DropOperator in project mantis by Netflix.
the class RemoteObservable method createTcpConnectionToServer.
private static <K, V> Observable<GroupedObservable<K, V>> createTcpConnectionToServer(final ConnectToGroupedObservable<K, V> params, final RemoteUnsubscribe remoteUnsubscribe, final RxMetrics metrics, final Action0 connectionDisconnectCallback, Observable<Integer> closeTrigger) {
final Decoder<K> keyDecoder = params.getKeyDecoder();
final Decoder<V> valueDecoder = params.getValueDecoder();
loadFastProperties();
return RxNetty.createTcpClient(params.getHost(), params.getPort(), new PipelineConfiguratorComposite<RemoteRxEvent, List<RemoteRxEvent>>(new PipelineConfigurator<RemoteRxEvent, List<RemoteRxEvent>>() {
@Override
public void configureNewPipeline(ChannelPipeline pipeline) {
if (enableNettyLogging) {
// uncomment to enable debug logging
pipeline.addFirst(new LoggingHandler(LogLevel.ERROR));
}
if (enableHeartBeating) {
pipeline.addLast("idleStateHandler", new IdleStateHandler(10, 2, 0));
pipeline.addLast("heartbeat", new HeartbeatHandler());
}
if (enableCompression) {
pipeline.addLast("gzipInflater", new JdkZlibEncoder(ZlibWrapper.GZIP));
pipeline.addLast("gzipDeflater", new JdkZlibDecoder(ZlibWrapper.GZIP));
}
// 4 bytes to encode length
pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
// max frame = half MB
pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(maxFrameLength, 0, 4, 0, 4));
}
}, new BatchedRxEventPipelineConfigurator())).connect().flatMap(new Func1<ObservableConnection<RemoteRxEvent, List<RemoteRxEvent>>, Observable<RemoteRxEvent>>() {
@Override
public Observable<RemoteRxEvent> call(final ObservableConnection<RemoteRxEvent, List<RemoteRxEvent>> connection) {
// send subscribe event to server
connection.writeAndFlush(RemoteRxEvent.subscribed(params.getName(), params.getSubscribeParameters()));
remoteUnsubscribe.setConnection(connection);
return connection.getInput().lift(new DropOperator<RemoteRxEvent>("incoming_" + RemoteObservable.class.getCanonicalName() + "_createTcpConnectionToServerGroups"));
}
}).doOnCompleted(new Action0() {
@Override
public void call() {
// connection completed
logger.warn("Detected connection completed when trying to connect to host: " + params.getHost() + " port: " + params.getPort());
connectionDisconnectCallback.call();
}
}).onErrorResumeNext(new Func1<Throwable, Observable<RemoteRxEvent>>() {
@Override
public Observable<RemoteRxEvent> call(Throwable t1) {
logger.warn("Detected connection error when trying to connect to host: " + params.getHost() + " port: " + params.getPort(), t1);
connectionDisconnectCallback.call();
// complete if error occurs
return Observable.empty();
}
}).takeUntil(closeTrigger).map(new Func1<RemoteRxEvent, Notification<byte[]>>() {
@Override
public Notification<byte[]> call(RemoteRxEvent rxEvent) {
if (rxEvent.getType() == RemoteRxEvent.Type.next) {
metrics.incrementNextCount();
return Notification.createOnNext(rxEvent.getData());
} else if (rxEvent.getType() == RemoteRxEvent.Type.error) {
metrics.incrementErrorCount();
return Notification.createOnError(fromBytesToThrowable(rxEvent.getData()));
} else if (rxEvent.getType() == RemoteRxEvent.Type.completed) {
metrics.incrementCompletedCount();
return Notification.createOnCompleted();
} else {
throw new RuntimeException("RemoteRxEvent of type:" + rxEvent.getType() + ", not supported.");
}
}
}).<byte[]>dematerialize().groupBy(new Func1<byte[], K>() {
@Override
public K call(byte[] bytes) {
ByteBuffer buff = ByteBuffer.wrap((byte[]) bytes);
// ignore notification type in key selector
buff.get();
int keyLength = buff.getInt();
byte[] key = new byte[keyLength];
buff.get(key);
return keyDecoder.decode(key);
}
}, new Func1<byte[], Notification<V>>() {
@Override
public Notification<V> call(byte[] bytes) {
ByteBuffer buff = ByteBuffer.wrap((byte[]) bytes);
byte notificationType = buff.get();
if (notificationType == 1) {
int keyLength = buff.getInt();
int end = buff.limit();
int dataLength = end - 4 - 1 - keyLength;
byte[] valueBytes = new byte[dataLength];
buff.position(4 + 1 + keyLength);
buff.get(valueBytes, 0, dataLength);
V value = valueDecoder.decode(valueBytes);
return Notification.createOnNext(value);
} else if (notificationType == 2) {
return Notification.createOnCompleted();
} else if (notificationType == 3) {
int keyLength = buff.getInt();
int end = buff.limit();
int dataLength = end - 4 - 1 - keyLength;
byte[] errorBytes = new byte[dataLength];
buff.position(4 + 1 + keyLength);
buff.get(errorBytes, 0, dataLength);
return Notification.createOnError(fromBytesToThrowable(errorBytes));
} else {
throw new RuntimeException("Notification encoding not support: " + notificationType);
}
}
}).map(new Func1<GroupedObservable<K, Notification<V>>, GroupedObservable<K, V>>() {
@Override
public GroupedObservable<K, V> call(GroupedObservable<K, Notification<V>> group) {
return GroupedObservableUtils.createGroupedObservable(group.getKey(), group.<V>dematerialize());
}
}).doOnEach(new Observer<GroupedObservable<K, V>>() {
@Override
public void onCompleted() {
logger.info("RemoteRxEvent, name: {} onCompleted()", params.getName());
}
@Override
public void onError(Throwable e) {
logger.error("RemoteRxEvent, name: {} onError()", params.getName(), e);
}
@Override
public void onNext(GroupedObservable<K, V> group) {
if (logger.isDebugEnabled()) {
logger.debug("RemoteRxEvent, name: {} new key: {}", params.getName(), group.getKey());
}
}
});
}
use of io.reactivx.mantis.operators.DropOperator in project mantis by Netflix.
the class RemoteObservable method createTcpConnectionToGOServer.
private static <K, V> Observable<MantisGroup<K, V>> createTcpConnectionToGOServer(final ConnectToGroupedObservable<K, V> params, final RemoteUnsubscribe remoteUnsubscribe, final RxMetrics metrics, final Action0 connectionDisconnectCallback, Observable<Integer> closeTrigger, final SpscArrayQueue<MantisGroup<?, ?>> inputQueue) {
final Decoder<K> keyDecoder = params.getKeyDecoder();
final Decoder<V> valueDecoder = params.getValueDecoder();
loadFastProperties();
return RxNetty.createTcpClient(params.getHost(), params.getPort(), new PipelineConfiguratorComposite<RemoteRxEvent, List<RemoteRxEvent>>(new PipelineConfigurator<RemoteRxEvent, List<RemoteRxEvent>>() {
@Override
public void configureNewPipeline(ChannelPipeline pipeline) {
if (enableNettyLogging) {
// uncomment to enable debug logging
pipeline.addFirst(new LoggingHandler(LogLevel.ERROR));
}
if (enableHeartBeating) {
pipeline.addLast("idleStateHandler", new IdleStateHandler(10, 2, 0));
pipeline.addLast("heartbeat", new HeartbeatHandler());
}
if (enableCompression) {
pipeline.addLast("gzipInflater", new JdkZlibEncoder(ZlibWrapper.GZIP));
pipeline.addLast("gzipDeflater", new JdkZlibDecoder(ZlibWrapper.GZIP));
}
// 4 bytes to encode length
pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
// max frame = half MB
pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(maxFrameLength, 0, 4, 0, 4));
}
}, new BatchedRxEventPipelineConfigurator())).connect().flatMap(new Func1<ObservableConnection<RemoteRxEvent, List<RemoteRxEvent>>, Observable<RemoteRxEvent>>() {
@Override
public Observable<RemoteRxEvent> call(final ObservableConnection<RemoteRxEvent, List<RemoteRxEvent>> connection) {
// send subscribe event to server
connection.writeAndFlush(RemoteRxEvent.subscribed(params.getName(), params.getSubscribeParameters()));
remoteUnsubscribe.setConnection(connection);
return connection.getInput().lift(new DropOperator<RemoteRxEvent>("incoming_" + RemoteObservable.class.getCanonicalName() + "_createTcpConnectionToServerGroups"));
}
}).doOnCompleted(new Action0() {
@Override
public void call() {
// connection completed
logger.warn("Detected connection completed when trying to connect to host: " + params.getHost() + " port: " + params.getPort());
connectionDisconnectCallback.call();
}
}).onErrorResumeNext(new Func1<Throwable, Observable<RemoteRxEvent>>() {
@Override
public Observable<RemoteRxEvent> call(Throwable t1) {
logger.warn("Detected connection error when trying to connect to host: " + params.getHost() + " port: " + params.getPort(), t1);
connectionDisconnectCallback.call();
// complete if error occurs
return Observable.empty();
}
}).takeUntil(closeTrigger).filter(new Func1<RemoteRxEvent, Boolean>() {
@Override
public Boolean call(RemoteRxEvent rxEvent) {
return (rxEvent.getType() == RemoteRxEvent.Type.next);
}
}).map(new Func1<RemoteRxEvent, Notification<byte[]>>() {
@Override
public Notification<byte[]> call(RemoteRxEvent rxEvent) {
metrics.incrementNextCount();
return Notification.createOnNext(rxEvent.getData());
}
}).<byte[]>dematerialize().map(new Func1<byte[], MantisGroup<K, V>>() {
@Override
public MantisGroup<K, V> call(byte[] bytes) {
ByteBuffer buff = ByteBuffer.wrap((byte[]) bytes);
// ignore notification type in key selector
buff.get();
int keyLength = buff.getInt();
byte[] key = new byte[keyLength];
buff.get(key);
K keyVal = keyDecoder.decode(key);
V value = null;
buff = ByteBuffer.wrap((byte[]) bytes);
byte notificationType = buff.get();
if (notificationType == 1) {
// int keyLength = buff.getInt();
int end = buff.limit();
int dataLength = end - 4 - 1 - keyLength;
byte[] valueBytes = new byte[dataLength];
buff.position(4 + 1 + keyLength);
buff.get(valueBytes, 0, dataLength);
value = valueDecoder.decode(valueBytes);
} else {
throw new RuntimeException("Notification encoding not support: " + notificationType);
}
return new MantisGroup<K, V>(keyVal, value);
}
}).doOnEach(new Observer<MantisGroup<K, V>>() {
@Override
public void onCompleted() {
logger.info("RemoteRxEvent, name: " + params.getName() + " onCompleted()");
}
@Override
public void onError(Throwable e) {
logger.error("RemoteRxEvent, name: " + params.getName() + " onError()", e);
}
@Override
public void onNext(MantisGroup<K, V> group) {
if (logger.isDebugEnabled()) {
logger.debug("RemoteRxEvent, name: " + params.getName() + " new key: " + group.getKeyValue());
}
}
});
}
use of io.reactivx.mantis.operators.DropOperator in project mantis by Netflix.
the class RemoteObservable method createTcpConnectionToServer.
private static <T> Observable<T> createTcpConnectionToServer(final ConnectToObservable<T> params, final RemoteUnsubscribe remoteUnsubscribe, final RxMetrics metrics, final Action0 connectionDisconnectCallback, Observable<Integer> closeTrigger) {
final Decoder<T> decoder = params.getDecoder();
loadFastProperties();
return RxNetty.createTcpClient(params.getHost(), params.getPort(), new PipelineConfiguratorComposite<RemoteRxEvent, List<RemoteRxEvent>>(new PipelineConfigurator<RemoteRxEvent, List<RemoteRxEvent>>() {
@Override
public void configureNewPipeline(ChannelPipeline pipeline) {
if (enableNettyLogging) {
// uncomment to enable debug logging
pipeline.addFirst(new LoggingHandler(LogLevel.ERROR));
}
if (enableHeartBeating) {
pipeline.addLast("idleStateHandler", new IdleStateHandler(10, 2, 0));
pipeline.addLast("heartbeat", new HeartbeatHandler());
}
if (enableCompression) {
pipeline.addLast("gzipInflater", new JdkZlibEncoder(ZlibWrapper.GZIP));
pipeline.addLast("gzipDeflater", new JdkZlibDecoder(ZlibWrapper.GZIP));
}
// 4 bytes to encode length
pipeline.addLast("frameEncoder", new LengthFieldPrepender(4));
// max frame = half MB
pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(maxFrameLength, 0, 4, 0, 4));
}
}, new BatchedRxEventPipelineConfigurator())).connect().flatMap(new Func1<ObservableConnection<RemoteRxEvent, List<RemoteRxEvent>>, Observable<RemoteRxEvent>>() {
@Override
public Observable<RemoteRxEvent> call(final ObservableConnection<RemoteRxEvent, List<RemoteRxEvent>> connection) {
// send subscribe event to server
connection.writeAndFlush(RemoteRxEvent.subscribed(params.getName(), params.getSubscribeParameters()));
remoteUnsubscribe.setConnection(connection);
return connection.getInput().lift(new DropOperator<RemoteRxEvent>("incoming_" + RemoteObservable.class.getCanonicalName() + "_createTcpConnectionToServer"));
}
}).doOnCompleted(new Action0() {
@Override
public void call() {
// connection completed
logger.warn("Detected connection completed when trying to connect to host: " + params.getHost() + " port: " + params.getPort());
connectionDisconnectCallback.call();
}
}).onErrorResumeNext(new Func1<Throwable, Observable<RemoteRxEvent>>() {
@Override
public Observable<RemoteRxEvent> call(Throwable t1) {
logger.warn("Detected connection error when trying to connect to host: " + params.getHost() + " port: " + params.getPort(), t1);
connectionDisconnectCallback.call();
// complete if error occurs
return Observable.empty();
}
}).takeUntil(closeTrigger).map(new Func1<RemoteRxEvent, Notification<T>>() {
@Override
public Notification<T> call(RemoteRxEvent rxEvent) {
if (rxEvent.getType() == RemoteRxEvent.Type.next) {
metrics.incrementNextCount();
return Notification.createOnNext(decoder.decode(rxEvent.getData()));
} else if (rxEvent.getType() == RemoteRxEvent.Type.error) {
metrics.incrementErrorCount();
return Notification.createOnError(fromBytesToThrowable(rxEvent.getData()));
} else if (rxEvent.getType() == RemoteRxEvent.Type.completed) {
metrics.incrementCompletedCount();
return Notification.createOnCompleted();
} else {
throw new RuntimeException("RemoteRxEvent of type: " + rxEvent.getType() + ", not supported.");
}
}
}).<T>dematerialize().doOnEach(new Observer<T>() {
@Override
public void onCompleted() {
logger.info("RemoteRxEvent: " + params.getName() + " onCompleted()");
}
@Override
public void onError(Throwable e) {
logger.error("RemoteRxEvent: " + params.getName() + " onError()", e);
}
@Override
public void onNext(T t) {
if (logger.isDebugEnabled()) {
logger.debug("RemoteRxEvent: " + params.getName() + " onNext(): " + t);
}
}
});
}
use of io.reactivx.mantis.operators.DropOperator in project mantis by Netflix.
the class ServerSentEventRequestHandler method handle.
@Override
public Observable<Void> handle(HttpServerRequest<ByteBuf> request, final HttpServerResponse<ServerSentEvent> response) {
InetSocketAddress socketAddress = (InetSocketAddress) response.getChannel().remoteAddress();
LOG.info("HTTP SSE connection received from " + socketAddress.getAddress() + ":" + socketAddress.getPort() + " queryParams: " + request.getQueryParameters());
final String socketAddrStr = socketAddress.getAddress().toString();
final WritableEndpoint<String> sn = new WritableEndpoint<>(socketAddress.getHostString(), socketAddress.getPort(), Endpoint.uniqueHost(socketAddress.getHostString(), socketAddress.getPort(), null));
final Map<String, List<String>> queryParameters = request.getQueryParameters();
final SlotAssignmentManager<String> slotMgr = ssm.registerServer(sn, queryParameters);
final AtomicLong lastResponseFlush = new AtomicLong();
lastResponseFlush.set(-1);
final AtomicLong lastResponseSent = new AtomicLong(-1);
// copy reference, then apply request specific filters, sampling
Observable<T> requestObservable = observableToServe;
// decouple the observable on a separate thread and add backpressure handling
// ServiceRegistry.INSTANCE.getPropertiesService().getStringValue("sse.decouple", "false");
String decoupleSSE = "false";
if ("true".equals(decoupleSSE)) {
final BasicTag sockAddrTag = new BasicTag("sockAddr", Optional.ofNullable(socketAddrStr).orElse("none"));
requestObservable = requestObservable.lift(new DropOperator<T>("outgoing_ServerSentEventRequestHandler", sockAddrTag)).observeOn(Schedulers.io());
}
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();
String uniqueClientId = socketAddrStr;
if (queryParameters != null && queryParameters.containsKey(CLIENT_ID_PARAM)) {
// enablePings
uniqueClientId = queryParameters.get(CLIENT_ID_PARAM).get(0);
}
if (queryParameters != null && queryParameters.containsKey(FORMAT_PARAM)) {
format = queryParameters.get(FORMAT_PARAM).get(0);
}
if (queryParameters != null && requestPreprocessor != null) {
requestPreprocessor.call(queryParameters, context);
}
// apply sampling, milli, then seconds
if (queryParameters != null && queryParameters.containsKey(SAMPLE_PARAM_MSEC)) {
// apply sampling rate
int samplingRate = Integer.parseInt(queryParameters.get(SAMPLE_PARAM_MSEC).get(0));
requestObservable = requestObservable.sample(samplingRate, TimeUnit.MILLISECONDS);
}
if (queryParameters != null && queryParameters.containsKey(SAMPLE_PARAM)) {
// apply sampling rate
int samplingRate = Integer.parseInt(queryParameters.get(SAMPLE_PARAM).get(0));
requestObservable = requestObservable.sample(samplingRate, TimeUnit.SECONDS);
}
if (queryParameters != null && queryParameters.containsKey(ENABLE_PINGS_PARAM)) {
// enablePings
String enablePings = queryParameters.get(ENABLE_PINGS_PARAM).get(0);
if ("true".equalsIgnoreCase(enablePings)) {
pingsEnabled = true;
} else {
pingsEnabled = false;
}
}
if (queryParameters != null && queryParameters.containsKey("delay")) {
// apply flush
try {
int flushInterval = Integer.parseInt(queryParameters.get("delay").get(0));
if (flushInterval >= 50) {
flushIntervalMillis = flushInterval;
} else {
LOG.warn("delay parameter too small " + flushInterval + " min. is 100");
}
} catch (Exception e) {
e.printStackTrace();
}
}
final byte[] delimiter = queryParameters != null && queryParameters.containsKey(MantisSSEConstants.MANTIS_COMPRESSION_DELIMITER) && queryParameters.get(MantisSSEConstants.MANTIS_COMPRESSION_DELIMITER).get(0) != null ? queryParameters.get(MantisSSEConstants.MANTIS_COMPRESSION_DELIMITER).get(0).getBytes() : null;
Tag[] tags = new Tag[2];
final String clientId = Optional.ofNullable(uniqueClientId).orElse("none");
final String sockAddr = Optional.ofNullable(socketAddrStr).orElse("none");
tags[0] = new BasicTag("clientId", clientId);
tags[1] = new BasicTag("sockAddr", sockAddr);
Metrics sseSinkMetrics = new Metrics.Builder().id("ServerSentEventRequestHandler", tags).addCounter("processedCounter").addCounter("pingCounter").addCounter("errorCounter").addCounter("droppedCounter").addCounter("flushCounter").build();
final Counter msgProcessedCounter = sseSinkMetrics.getCounter("processedCounter");
final Counter pingCounter = sseSinkMetrics.getCounter("pingCounter");
final Counter errorCounter = sseSinkMetrics.getCounter("errorCounter");
final Counter droppedWrites = sseSinkMetrics.getCounter("droppedCounter");
final Counter flushCounter = sseSinkMetrics.getCounter("flushCounter");
// get predicate, defaults to return true for all T
Func1<T, Boolean> filterFunction = new Func1<T, Boolean>() {
@Override
public Boolean call(T t1) {
return true;
}
};
if (queryParameters != null && predicate != null) {
filterFunction = predicate.getPredicate().call(queryParameters);
}
final Subscription timerSubscription = Observable.interval(1, TimeUnit.SECONDS).doOnNext(new Action1<Long>() {
@Override
public void call(Long t1) {
long currentTime = System.currentTimeMillis();
if (pingsEnabled && (lastResponseSent.get() == -1 || currentTime > lastResponseSent.get() + PING_INTERVAL)) {
pingCounter.increment();
response.writeStringAndFlush(PING);
lastResponseSent.set(currentTime);
}
}
}).subscribe();
return requestObservable.filter(filterFunction).map(encoder).lift(new DisableBackPressureOperator<String>()).buffer(flushIntervalMillis, TimeUnit.MILLISECONDS).flatMap(new Func1<List<String>, Observable<Void>>() {
@Override
public Observable<Void> call(List<String> valueList) {
if (response.isCloseIssued() || !response.getChannel().isActive()) {
LOG.info("Client closed detected, throwing closed channel exception");
return Observable.error(new ClosedChannelException());
}
List<String> filteredList = valueList.stream().filter(e -> {
return slotMgr.filter(sn, e.getBytes());
}).collect(Collectors.toList());
if (response.getChannel().isWritable()) {
flushCounter.increment();
if (format.equals(BINARY_FORMAT)) {
boolean useSnappy = true;
try {
String compressedList = delimiter == null ? CompressionUtils.compressAndBase64Encode(filteredList, useSnappy) : CompressionUtils.compressAndBase64Encode(filteredList, useSnappy, delimiter);
StringBuilder sb = new StringBuilder(3);
sb.append(SSE_DATA_PREFIX);
sb.append(compressedList);
sb.append(TWO_NEWLINES);
msgProcessedCounter.increment(valueList.size());
lastResponseSent.set(System.currentTimeMillis());
return response.writeStringAndFlush(sb.toString());
} catch (Exception e) {
LOG.warn("Could not compress data" + e.getMessage());
droppedWrites.increment(valueList.size());
return Observable.empty();
}
} else {
int noOfMsgs = 0;
StringBuilder sb = new StringBuilder(valueList.size() * 3);
for (String s : filteredList) {
sb.append(SSE_DATA_PREFIX);
sb.append(s);
sb.append(TWO_NEWLINES);
noOfMsgs++;
}
msgProcessedCounter.increment(noOfMsgs);
lastResponseSent.set(System.currentTimeMillis());
return response.writeStringAndFlush(sb.toString());
}
} else {
//
droppedWrites.increment(filteredList.size());
}
return Observable.empty();
}
}).onErrorResumeNext(new Func1<Throwable, Observable<? extends Void>>() {
@Override
public Observable<? extends Void> call(Throwable throwable) {
Throwable cause = throwable.getCause();
// ignore closed channel exceptions, this is
// when the connection was closed on the client
// side without informing the server
errorCounter.increment();
if (cause != null && !(cause instanceof ClosedChannelException)) {
LOG.warn("Error detected in SSE sink", cause);
if (errorEncoder != null) {
// write error out on connection
// response.writeAndFlush(errorEncoder.call(throwable));
ByteBuf errType = response.getAllocator().buffer().writeBytes("error: ".getBytes());
ByteBuf errRes = response.getAllocator().buffer().writeBytes((errorEncoder.call(throwable)).getBytes());
response.writeAndFlush(ServerSentEvent.withEventType(errType, errRes));
}
throwable.printStackTrace();
}
if (requestPostprocessor != null && queryParameters != null) {
requestPostprocessor.call(queryParameters, context);
}
ssm.deregisterServer(sn, queryParameters);
timerSubscription.unsubscribe();
return Observable.error(throwable);
}
});
}
Aggregations