All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.leangen.graphql.spqr.spring.web.apollo.PerConnectionApolloHandler Maven / Gradle / Ivy

The newest version!
package io.leangen.graphql.spqr.spring.web.apollo;

import graphql.GraphQL;
import io.leangen.graphql.spqr.spring.web.mvc.websocket.GraphQLWebSocketExecutor;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.SubProtocolCapable;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.ConcurrentWebSocketSessionDecorator;

import jakarta.annotation.PreDestroy;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class PerConnectionApolloHandler implements WebSocketHandler, SubProtocolCapable {

    private final GraphQL graphQL;
    private final GraphQLWebSocketExecutor executor;
    private final TaskScheduler taskScheduler;
    private final int keepAliveInterval;
    private final int sendTimeLimit;
    private final int sendBufferSizeLimit;
    private final Map handlers;

    private static final List GRAPHQL_WS = Collections.singletonList("graphql-ws");

    public PerConnectionApolloHandler(GraphQL graphQL, GraphQLWebSocketExecutor executor,
                                      TaskScheduler taskScheduler, int keepAliveInterval,
                                      int sendTimeLimit, int sendBufferSizeLimit) {
        this.graphQL = graphQL;
        this.executor = executor;
        this.taskScheduler = taskScheduler;
        this.keepAliveInterval = keepAliveInterval;
        this.sendTimeLimit = sendTimeLimit;
        this.sendBufferSizeLimit = sendBufferSizeLimit;
        this.handlers = new ConcurrentHashMap<>();
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        ApolloProtocolHandler handler = new ApolloProtocolHandler(graphQL, executor, taskScheduler, keepAliveInterval);
        HandlerProxy proxy = new HandlerProxy(handler, decorateSession(session));
        this.handlers.put(session, proxy);
        proxy.afterConnectionEstablished();
    }

    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage message) throws Exception {
        getHandler(session).handleMessage(message);
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) {
        getHandler(session).handleTransportError(exception);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) {
        try {
            getHandler(session).afterConnectionClosed(closeStatus);
        }
        finally {
            this.handlers.remove(session);
        }
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

    @Override
    public List getSubProtocols() {
        return GRAPHQL_WS;
    }

    @PreDestroy
    public void cancelAll() {
        this.handlers.forEach((session, handler) -> {
            try {
                session.close(CloseStatus.GOING_AWAY);
            } catch (IOException ignored) {
                /*no-op*/
            }
            handler.cancelAll();
        });
    }

    protected WebSocketSession decorateSession(WebSocketSession session) {
        return new ConcurrentWebSocketSessionDecorator(session, sendTimeLimit, sendBufferSizeLimit);
    }

    private HandlerProxy getHandler(WebSocketSession session) {
        HandlerProxy handler = this.handlers.get(session);
        if (handler == null) {
            throw new IllegalStateException("WebSocketHandler not found for " + session);
        }
        return handler;
    }

    private static class HandlerProxy {

        private final ApolloProtocolHandler handler;
        private final WebSocketSession session;

        HandlerProxy(ApolloProtocolHandler handler, WebSocketSession session) {
            this.handler = handler;
            this.session = session;
        }

        void afterConnectionEstablished() throws Exception {
            handler.afterConnectionEstablished(session);
        }

        void handleMessage(WebSocketMessage message) throws Exception {
            handler.handleMessage(session, message);
        }

        void handleTransportError(Throwable exception) {
            handler.handleTransportError(session, exception);
        }

        void afterConnectionClosed(CloseStatus closeStatus) {
            handler.afterConnectionClosed(session, closeStatus);
        }

        void cancelAll() {
            handler.cancelAll();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy