У меня есть подписки 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 p4sh4 да, я опубликую решение сегодня позже
Я основал свое решение на основе этого поста
По сути, мы создали подписку с помощью сокетов, используя 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();
Вы смогли в этом разобраться?