public RxServer createServer()

in mantis-network/src/main/java/io/reactivex/mantis/network/push/PushServerSse.java [107:324]


    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;
                        String availabilityZone = 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.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 (MQLServer.parses(query)) {
                                    Query q = MQLServer.parse(query);
                                    predicateFunction = (T datum) -> datum instanceof Map ? q.matches((Map) datum) : true;
                                }
                            }

                            if (queryParameters.containsKey(MantisSSEConstants.AVAILABILITY_ZONE)) {
                                availabilityZone = queryParameters.get(MantisSSEConstants.AVAILABILITY_ZONE).get(0);
                            }
                        }

                        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, availabilityZone);
                    }
                })
            .pipelineConfigurator(PipelineConfigurators.serveSseConfigurator())
            .channelOption(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(1024 * 1024, 5 * 1024 * 1024))

            .build();
        return server;
    }