Как закрыть сокетное соединение для подписки на GraphQL в Apollo

У меня есть подписки GraphQL на моем сервере Apollo, которые я хочу закрыть после выхода пользователя из системы. Первоначальный вопрос заключается в том, должны ли мы закрывать эти (сокетные) соединения на стороне клиента или в бэкэнде.

Во внешнем интерфейсе я использую Angular с клиентом Apollo и обрабатываю подписки на GraphQL, расширяя класс Subscription из apollo-angular. Я могу закрыть каналы подписки с помощью типичной реализации takeUntil rxjs:

this.userSubscription
  .subscribe()
  .pipe(takeUntil(this.subscriptionDestroyed$))
  .subscribe(
    ({ data }) => {
      // logic goes here
    },
    (error) => {
      // error handling
   }
);
  

Однако это не закрывает веб-сокет на сервере, что, если я прав, приведет к утечке памяти подписки.

Сервер Apollo (и экспресс) настраивается для подписок следующим образом:

const server = new ApolloServer({
  typeDefs,
  resolvers,
  subscriptions: {
    onConnect: (connectionParams, webSocket, context) => {
      console.info('on connect');
      const payload = getAuthPayload(connectionParams.accessToken);
      if (payload instanceof Error) {
        webSocket.close();
      }
      return { user: payload };
    },
    onDisconnect: (webSocket, context) => {
      console.info('on Disconnect');
    }
  },
  context: ({ req, res, connection }) => {
    if (connection) {
      // set up context for subscriptions...
    } else {
      // set up context for Queries, Mutations...
    }

Когда клиент регистрирует новую подписку на GraphQL, я всегда вижу console.info('on connect'); в журналах сервера, но никогда не вижу console.info('on Disconnect');, пока не закрою внешнее приложение.

Я не видел ни одного примера того, как закрыть веб-сокет для подписок с помощью Apollo. В основном я хочу сделать это, чтобы завершить реализацию выхода из системы.

Я что-то упустил здесь? Заранее спасибо!

Вы смогли в этом разобраться?

p4sh4 06.01.2021 09:58

@ p4sh4 p4sh4 да, я опубликую решение сегодня позже

chris 08.01.2021 17:19
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
2
4 484
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я основал свое решение на основе этого поста

По сути, мы создали подписку с помощью сокетов, используя subscriptions-transport-ws

export const webSocketClient: SubscriptionClient = new 
SubscriptionClient(
  `${environment.WS_BASE_URL}/graphql`,
  {
    reconnect: true,
    lazy: true,
    inactivityTimeout: 3000,
    connectionParams: () => ({
      params: getParams()
    })
  }
);

Как указано в вопросе, я хотел отменить подписку на все каналы и закрыть соединение сокета подписки перед выходом пользователя из системы. Мы делаем это с помощью webSocketClient SubscriptionClient в функции выхода из системы и вызываем:

webSocketClient.unsubscribeAll();
webSocketClient.close();

Другие вопросы по теме