Нужно найти ошибку при подключении подписки с прошивкой схемы
Я использую apollo-server-express для графического сервера. Я собираюсь обрабатывать там только мутации, но я хочу перенаправить запрос и подписку на hasura посредством сшивания схемы с самоанализом. Запросы через apollo-server к hasura работают нормально и возвращают ожидаемые данные.
Но подписки не работают, и я получаю эту ошибку: "Ожидается итерируемая, но не найдена для поля subscription_root.users".
И кроме того, сервер hasura получает события:
Но apollo-server возмущается ответом от hasura. Я не первый день страдаю от этого, и я не могу понять, в чем проблема.
В редакторе hasura работают подписки.
Если вам нужна дополнительная информация, я с удовольствием предоставлю ее вам.
import {
introspectSchema,
makeExecutableSchema,
makeRemoteExecutableSchema,
mergeSchemas,
transformSchema,
FilterRootFields
} from 'graphql-tools';
import { HttpLink } from 'apollo-link-http';
import nodeFetch from 'node-fetch';
import { resolvers } from './resolvers';
import { hasRoleResolver } from './directives';
import { typeDefs } from './types';
import { WebSocketLink } from 'apollo-link-ws';
import { split } from 'apollo-link';
import { getMainDefinition } from 'apollo-utilities';
import { SubscriptionClient } from 'subscriptions-transport-ws';
import * as ws from 'ws';
import { OperationTypeNode } from 'graphql';
interface IDefinitionsParams {
operation?: OperationTypeNode,
kind: 'OperationDefinition' | 'FragmentDefinition'
}
const wsurl = 'ws://graphql-engine:8080/v1alpha1/graphql';
const getWsClient = function (wsurl: string) {
const client = new SubscriptionClient(wsurl, {
reconnect: true,
lazy: true
}, ws);
return client;
};
const wsLink = new WebSocketLink(getWsClient(wsurl));
const createRemoteSchema = async () => {
const httpLink = new HttpLink({
uri: 'http://graphql-engine:8080/v1alpha1/graphql',
fetch: (nodeFetch as any)
});
const link = split(
({ query }) => {
const { kind, operation }: IDefinitionsParams = getMainDefinition(query);
console.log('kind = ', kind, 'operation = ', operation);
return kind === 'OperationDefinition' && operation === 'subscription';
},
wsLink,
httpLink,
);
const remoteSchema = await introspectSchema(link);
const remoteExecutableSchema = makeRemoteExecutableSchema({
link,
schema: remoteSchema
});
const renamedSchema = transformSchema(
remoteExecutableSchema,
[
new FilterRootFields((operation, fieldName) => {
return (operation === 'Mutation') ? false : true; // && fieldName === 'password'
})
]
);
return renamedSchema;
};
export const createNewSchema = async () => {
const hasuraExecutableSchema = await createRemoteSchema();
const apolloSchema = makeExecutableSchema({
typeDefs,
resolvers,
directiveResolvers: {
hasRole: hasRoleResolver
}
});
return mergeSchemas({
schemas: [
hasuraExecutableSchema,
apolloSchema
]
});
};
1 ответ
Исправлено установкой graphql-tools 4-й версии. Выключает редактор, даже не заметил, что у меня нет этой зависимости, и просто взял версию node_modules, которая была установлена каким-то другим пакетом. Проблема была с версией 3.x. Запрос на извлечение - это место, где ошибка была исправлена.
У меня была та же проблема, но другая причина и решение.
Моя подписка работала хорошо, пока я не ввел ключ "разрешить" в свой преобразователь подписки:
Вот часть "Подписка" в Моем преобразователе:
Subscription: {
mySubName: {
resolve: (payload) => {
console.log('In mySubName resolver, payload:',payload)
return payload;
},
subscribe:() => pubSub.asyncIterator(['requestsIncomplete']),
// )
},
Console.log доказывает, что функция resolve() вызывается с хорошо структурированной полезной нагрузкой (в форме такой же, как мое определение схемы - в частности, объект с ключом, названным в честь подписчика graphQL, указывающий на массив (массив является повторяемым):
In mySubName resolver, payload: { mySubName:
[ { id: 41,
...,
},
{...},
{...}
...
...
]
Хотя я возвращал тот же неподдельный объект, это вызвало ошибку expected Iterable, but did not find one for field "Subscription.mySubName"
Когда я закомментировал эту функцию разрешения в целом, подписка сработала, что является еще одним свидетельством того, что мои полезные данные были хорошо структурированы, а правильный ключ указывал на итерацию.
Я, должно быть, неправильно использую поле разрешения. С https://www.apollographql.com/docs/graphql-subscriptions/subscriptions-to-schema/
При использовании поля подписки также можно управлять полезной нагрузкой события перед ее запуском через механизм выполнения GraphQL.
Добавьте метод разрешения рядом с вашей подпиской и измените полезную нагрузку по своему усмотрению
поэтому я не уверен, как правильно использовать эту функцию, в частности, не знаю, какой объект формы вернуть из нее, но использование его, как указано выше, нарушает подписку таким же образом, как вы описываете в своем вопросе.
Я уже использовал graphql-tools 4.0.0, я обновился до 4.0.8, но это не имело значения.