Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Что не так с GraphGL #21

Open
nin-jin opened this issue Sep 22, 2019 · 4 comments
Open

Что не так с GraphGL #21

nin-jin opened this issue Sep 22, 2019 · 4 comments

Comments

@nin-jin
Copy link
Owner

nin-jin commented Sep 22, 2019

Денормализованная выдача

Выдаётся всегда дерево в денормализованной форме. Если в графе есть циклы, то выдача может легко увеличиться на порядок за счёт дублирования поддеревьев.

Представление данных в виде слепков

Это несовместимо с с бесконфликтными алгоритмами слияния, так как теряет мета-информацию об изменениях.

Нестандартизированные параметры

GQL - это просто RPC. offset, limit, filter, sort и прочее реализуется всеми по разному. Из-за чего нельзя написать универсальный инструмент работы с разными АПИ.

DevTools браузера мало полезны

Все запросы POST-ом (или экранированным GET), все ответы с кодом 200. Соответственно браузер никак не помогает всё это дебажить.

HTTP кеширование не работает

RPC в принципе не кешируется. В лучшем случае кеширование реализуется клиентской библиотекой. Кеширование на прокси идёт лесом.

Много сложностей

Все эти типы, фрагменты, мутации и пр на собственном ограниченном языке, требующем писать много кода для простых вещей. Дженерики? Плиморфизм для мутаций? Переиспользование кода между запросами и мутациями? "Вам это не нужно". Без библиотек и спец-инструментов использовать очень сложно.

Нет загрузки файлов

Разве что через упаковку их в BASE64 и посылки текстом.

Потенциальный DOS

Легко простым запросом выгрузить на клиент всю базу, что положит сервер. Дизайн запросов такой, что сложно сделать ограниченное число запросов к базе на запрос к северу. А неограниченное число запросов к базе быстро убьёт производительность. Расстановка индексов становится нетривиальной задачей.

Кривой nullable

Все поля nullable по умолчанию. При этом невозможно отличить null от отсутствия поля, что важно при мутациях, чтобы не стирать данные, если поле не передано.

@izatop
Copy link

izatop commented Sep 22, 2019

Про загрузку файлов можно выкинуть. По крайней мере если исходить из парадигмы использования GraphQL over HTTP(S) https://blog.apollographql.com/file-uploads-with-apollo-server-2-0-5db2f3f60675

@izatop
Copy link

izatop commented Sep 22, 2019

HTTP кеширование не работает

GraphQL не про интерфейс и протокол, это про структуру данных. Как реализуют клиенты кэширование вообще отдельная тема. При необходимости можно даже HTTP кэш накинуть. Но в целом это решается через механизмы кэширования на клиенте или в WW.

@izatop
Copy link

izatop commented Sep 22, 2019

Потенциальный DOS

Есть уже способы работы со сложными системами на GraphQL чтобы учитывать query complexity, например https://github.com/slicknode/graphql-query-complexity

@zerkalica
Copy link

zerkalica commented Dec 1, 2021

Накину про серверсайд gql на ts:

  1. Отдельные реализации типов для аргументов-объектов (GraphQLInputObjectType), в которых не работают юнионы. Обсуждали 4 года [RFC] GraphQL Input Union type graphql/graphql-spec#488 и родили 15й стандарт: RFC: OneOf Input Objects graphql/graphql-spec#825 который еще 5 лет будут обсуждать, т.к. идейный вдохновитель ушел из facebook).
  2. GraphQLEnumType в typescript выводится как any: https://github.com/graphql/graphql-js/blob/main/src/type/definition.ts#L1362 class GraphQLEnumType /* <T> */ {, сложно использовать в аргументах, тем более что values может маппить как угодно входные значения
  3. Проблема курицы и яйца относительно типов ts на сервере, когда на ts пишется query, у него есть gql рантайм тип аргументов, но ts-тип этих аргументов не выводится сразу и в resolver приходится писать any. graphql-js преобразует gql-рантайм типы в schema.graphql, graphql-code-generator генерит из нее ts типы и уже эти сгенеренные типы вместо any пишутся в ресолвере.
  4. В случае юниона в респонсе, если в query перечисленны не все типы в юнионе, то сгенерится обопщенный ts-тип, где __typename: string: Adding __typename on a interface field generates generates string type instead of union type with constant strings relay-tools/relay-compiler-language-typescript#190
  5. Рекурсия - боль, например, что б в gql сгенерить такое: type Offer = { id: string; related: Offer[] }, надо отдельно вынести все поля без related в GraphQLObjectTypeConfig, создать OfferBase с этими типами без related и Offer с related.
  6. Типы не расширяются, т.к. описываются как объекты, а не классы, в публичном интерфейсе не представлен config типа, что б расширить, приходится его описывать отдельно и через спред генерить новый тип
  7. Автовывод ts-типов слабо задействован, постоянно приходится объявлять тонну генериков: new GraphQLObjectType<Snippet | Card, GraphqlContext, Args>
  8. В массивах элементы по-дефолту nullable. Надо постоянно писать new GraphQLList(new GraphQLNonNull(SomeType))
  9. если сделать в ресолвере Promise.resolve(new Error) (заметьте, не reject), то gql сконвертит это в throw. https://github.com/graphql/graphql-js/blob/29bf39faa670effd3c1561a1512ec7767658a63b/src/execution/execute.ts#L616
  10. Про дедупликацию json-а: есть стороннее решение: https://github.com/gajus/graphql-deduplicator, однако в апстриме подобного нет и вряд ли будет в ближайшем будущем (т.к. это потребует изменить протокол) Normalized Responses graphql/graphql-js#150 (comment)
  11. Неоднозначность в обработке ошибок. Если в query type описан, как non-nullable: new GraphQL.GraphQLNonNull(SomeType), то при его падении, весь запрос, который включал эту и другие квери, валится. При этом, без NonNull, вернется, то, что удалось загрузить и отдельно поле с errors.

@nin-jin nin-jin added HabHub and removed HabHub labels Feb 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants