Git Product home page Git Product logo

conf-talks's People

Contributors

akasybe avatar bautrukevich avatar denisix avatar denys-bushulyak avatar dependabot[bot] avatar dmitrymakhnev avatar edk55 avatar edward101701 avatar endorphin82 avatar evilsprut avatar frankiepo avatar ivshalin avatar iyudincev avatar lex111 avatar mctep avatar moondef avatar n0xff avatar nmvikings avatar nodkz avatar pfrankov avatar uxname avatar yzevm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

conf-talks's Issues

Mutation chaining

Можно попробовать

В 6.1. объединять мутации не просто в namespace-типы, которые возвращают {} (что приводит к тому, что корень - пустой объект), а делегировать логику по "поиску" объекта, над которым будет произведена мутация, этому самому namespace-типу?

То есть:

mutation {
  post(id: 4) {
    like { ... }
  }
}

И, например, если поста с id 4 не существует, то просто возвращаем null на post и на этом мутация завершится, избавив нас от потенциальных багов.

А что, если...

Возвращать тот самый namespace тип в качестве поля результата мутации? Мы получим чейнинг :)

mutation {
  post {
    create(...) {
      ...
      post { // Здесь мы имеем дело с только что созданным постом
        like { ... }
      }
    }
  }
}

Таким образом мы можем проделать некие операции с только что созданной сущностью, не совершая лишних запросов с одной стороны и не плодить всевозвожные комбинации мутаций в схеме, тем самым делая её чище.

When to use: REST, GraphQL, gRPC

  • gRPC is a good choice for performance critical components of your architecture
  • GraphQL a better choice for complex quickly evolving APIs where development speed comes at a premium.
  • REST a stateless architecture for data transfer that is dependent on hypermedia.

gRPC is about 10 times faster than GraphQL without Keep-alive. With Keep-Alive the same speed.
Proof: https://github.com/Q42Philips/protobuf-vs-graphql

gRPC is lightweight, highly performant, difficult to debug, difficult to detect breaking schema changes (schema is based on a numbered position rather than a field name. This means you need to never rename positions - if you want to deprecate fields you just loose the numbering), lots of magic going on to learn compared to REST or GraphQL.

GraphQL is much heavier, easier to test and debug and has some performance optimisations like data loader and is better for multiple clients to consume. I’d say it’s easier to manage schema changes but it’s probably not empirical.

picking-a-paradigm

Resources:

Batch операции + уникальные payload типы для мутаций

Возник вопрос, ответ на который кмк должен быть где-то в тексте.

Если мы используем 6.3. Рассмотрите возможность выполнения мутаций сразу над несколькими элементами (однотипные batch-изменения) чтобы иметь возможность выполнять batch-операции, то это выглядит красиво и удобно, но вот если мы к этому добавим следущее по тексту правило 6.6. Мутация должна возвращать свой уникальный Payload-тип то возникает вопрос как это лучше сделать. Union тип для record и recordId ? Или record и рядом recordCollection? Или всё-таки не юзать List Input Coercion и сделать отдельную batch мутацию? Есть ли решение обкатанное в бою?

Query в мутациях

Замет, что изпользование Query в mutation приводит к двойному выполнению запроса на apollo-server (заметил задваивание записей в базе. После изъятия поля с mutation запроса - проблема пропала). Пожалуйста - прокоментируейте.

  mutation ( $data : SomeInput! ) {
    myMutation ( input: $data ) {
      entity
      query: { #Проблемное место
         someQuery{
            # ...
         }
      }
      errors{
       # ....
      }
  }

Prisma

Призма ведь ORM
Так как сказано про призму можно сказать про любую ORM, возможна разница в зрелости
Все же это удобнее чем писать все самому
Если что то работает не так, всегда есть резолвер

GraphQL fields are nullable by design

The GraphQL documentation provides this explanation:

... in a GraphQL type system, every field is nullable by default. This is because there are many things which can go awry in a networked service backed by databases and other services. A database could go down, an asynchronous action could fail, an exception could be thrown. Beyond simply system failures, authorization can often be granular, where individual fields within a request can have different authorization rules.

Вобщем тут графкуэль добряк – вернуть хоть что-нибудь. Старается вернуть как можно больше, даже если что-то где-то отвалилось.

Apollo GraphQL больше не включает в себя GraphQL Uploads

https://github.com/nodkz/conf-talks/tree/master/articles/graphql/fileUploads

Некоторое время назад graphql-upload был сломан, и теперь есть рекомендация не использовать встроенную имплементацию, а использовать внешнюю:

apollographql/apollo-server#3508 (comment)

Поэтому стоит обновить этот кусок файла.

6.3. Рассмотрите возможность выполнения мутаций сразу над несколькими элементами (однотипные batch-изменения).

@IvanGoncharov from Skype conversation:

Все прикольно и по теме но не нужна плодить мутации для батчинга

у Графкюл списков есть коершен из скаляра в масив
https://facebook.github.io/graphql/June2018/#sec-Type-System.List

type ArctleMutation {
  deleteArticle(ids: [Int]!): Payload
}

можна вызывать
deleteArticle(ids: 1)
или
deleteArticle(ids: [1, 2, 3])


Дополнения к правилу 6.3

Безопасная загрузка файлов

Я полностью поддерживаю подход, что файлы нужно грузить на REST эндпоинты и передавать ссылку на файлы в GraphQL мутацию.
Единственное хотелось бы добавить о безопасности такого запроса, для того чтобы не проверять был ли файл в прошлом уже назначен объекту (а если в бэкэнде есть проверка на дубликаты и один файл может назначен нескольким объектам тогда такая проверка не поможет).
Рекомендуемый выход из данной ситуации это вместе с ссылкой передавать подписанный токен JWT с указанием ID: файла в объектном хранилище или можно ссылку засунуть внутрь JWT.
Сервер проверяет токен и только после этого назначает ссылку. В противном случае есть вероятность, что злоумышленник начнет перебор ссылок или ID файла для того, чтобы получить доступ к файлу (если конечно стоит ограничение на то, что только определенные группы пользователей имеют доступ к файлу).

Как в ресторане или как в армии

GraphQL - как в ресторане:

  • Вот вам пожалуйста меню, выбирайте.
  • Будьте любезны салатик, рыбки на пару и бокальчик белого. Спасибо.

REST API - как в армии:

  • Жри что дали, а то голодным останешься, - и наваливаю кучу чего-то

Вроде и те и те наелись, но как мы видим есть ньюанс 😜

Холивар: Prisma, Join-monster, Hasura, Postgraphile

Подводим итог общения с Максимом (api.fastcup.io):

  • 3 человека воевали с GraphQL на бэкенде
  • 30 моделей/табличек
  • убито времени:
    — На призму 5 дней (Итог: просто охерел от того, насколько она популярна при ее днищенской функциональности)
    — На джоинмонстер 2 недели (Итог: join-monster тормозной)
    — На хазуру 3 дня (Итог: В хазуре все предельно ясно и понятно)
    — Переезд 1 неделя с join-monster на hasura (camelCase потеряли, underscore получили)

Disclaimer: Это субъективный опыт одной команды. Объективной оценки вам никто не даст. Кому-то Prisma, либо join-monster может зайти лучше чем Hasura.


Максим Макаров, телеграм @Maxpain177

Rule 5.4: Пагинация – Двойные источники истины, неконсистентные структуры, избыточные данные

Конструктивная критика от @greabock

Двойные источники истины, неконсистентные структуры, избыточные данные — в общем, весьма спорные рекомендации касательно структурирования. Блин, да банально взять пагинацию:

type PaginationInfo {
  # А то мы не умеем в арифметику. И не можем поделить total на perPage 
  # Да и на камень дикие вычислительные нагрузки при делении - ужс. Пусть этим сервак занимается.
  # Нам лень считать.
  pageCount: Int

  # Total number of items
  itemCount: Int

  # Мы прост потерялись ваще - нам бэк должен сказать, где мы, а то уже забыли что запрашивали
  currentPage: Int!

  # Говорю же - были пьяны и не помним ничего
  perPage: Int!

  # Пля... это просто жесть в логику я тоже не хочу. Пусть сервак думает.
  hasNextPage: Boolean

  # Та вы издеваетесь?
  hasPreviousPage: Boolean
}

Михаил Новиков: правки в правило 6.8 – ошибки мутаций

Mikhail, [Feb 1, 2019 at 6:19:55 PM]:

6.8. Мутации должны возвращать поле errors с типизированными пользовательскими ошибками.

обычный паттерн не через errors

а SuccessPayload | ErrorPayload1 | ErrorPayload2

и все ErrorPayload одного интерфейса чтобы можно было сделать на них спред

Pavel @nodkz, [Feb 1, 2019 at 6:20:57 PM]:

Найс! Хорошая правка

Mikhail, [Feb 1, 2019 at 6:21:21 PM]:

и query типа

... on SuccessPayload {} ...on ErrorInterface (чтобы forwards compatible) ... on ConcreteError1 (специфичный хендлинг)

Новое правило: использовать markdown в правилах

@IvanGoncharov:

сейчас копаюсь в коде printSchema и придумал тебе еще одно правило
в дескрипшенах типов/филдов/... можна использовать маркдаун
https://facebook.github.io/graphql/June2018/#sec-Descriptions

графикл и все остальные нормальные клиенты рендерят дескрипшн как маркдаун

В каких случаях вы не стали бы использовать GraphQL?

Uxname, [Feb 10, 2019 at 3:01:38 AM]:
моё мнение (на все пунты сразу):

  • когда и так всё устраивает
  • когда лид против перехода на графкл
  • когда нужно будет предоставлять api третьим лицам (гос. учреждения например), а там кроме как rest в лучшем случае ничего и не умеют больше
  • когда нет времени вникать
  • когда много работы с файлами (больше чем с текстовыми данными)
  • когда на проект планируется брать джунов на поддержку (на рест они везде учились, а на графкл придётся учиться уже на проекте скорее всего
    (+ ещё пару кейсов, но голова не варит ночью)

о, аналогию придумал пока писал, graphql - это как линукс, если нет рядом знакомого линуксоида. то лучше наверное и не переходить на него

хотя я бы всем рекомендовал перейти на graphql, по крайней мере это следает api НЕ ХУЖЕ (если писать топорно, как в rest)

Группировка взаимосвязанных полей вместе в новый output-тип

Выносите взаимосвязанные поля на уровень ниже в новый output-тип. Берем поля phone и operatorCode и группируем их в типе ClaimByPhone ... ... ...

Возможно в данном случае лучше использовать Union type:

union Claim = ClaimByPhone | ClaimByMail

type ClaimByPhone {
  text: String!
  phone: String!
  operatorCode: String!
}

type ClaimByMail {
  text: String!
  email: String!
}

Имхо, получается более элегантно. В своей схеме я использую как раз такой подход.

Производительность GraphQL RPS

Из чата https://t.me/graphql_ru

Den @a7kOJ4nQHnUebLasKtRFOe0hIUTM0a6d

Ребят, посоветуйте пожалуйста наиболее шуструю по перформансу реализацию graphql, на node + cluster + apollo server на core i5, смог выжать ~15к rps на статической query ok : String => "OK"

@egoarka

fastify + GraphQL jit
Хотя есть результаты получше
https://github.com/benawad/node-graphql-benchmarks/blob/master/README.md

Den @a7kOJ4nQHnUebLasKtRFOe0hIUTM0a6d

Пробовал, правда golang + net/http ~22k rps, есть прирост, 46%, ожидал правда больше, попробую прикрутить к fasthttp..
core-graphql-jit-str + ok: () => 'OK' + cluster => 18 522 rps (за счет кластера +4к)
c pm2 - 17171 rps

@egoarka

что думаешь по тесту и если параллель с го провести?

Den @a7kOJ4nQHnUebLasKtRFOe0hIUTM0a6d

на golang все ядра заюзывались, теоретический максимум на моей машине (кол-во raw http запросов по сути) - 232 K rps, а с github.com/graph-gophers/graphql-go ~ 22.7 K rps, то есть нужно чтото думать с логикой graphql
замерял простые запросы http, с помощью ab, c использованием require('http') => 22 K rps, require('net') => 25 K rps
плюс еще нашел что core-graphql-git использует кеш от запроса, если его убрать вообще уныло - 7 K rps, + добавить cluster => 10.9 K rps
это 72% на логику graphql приходится

Указать особенности выполнения мутаций

6.1. Используйте Namespace-типы для группировки мутаций в рамках одного ресурса!

Необходимо указать, что при таком подходе порядок выполнения нескольких мутаций в рамках одного запроса не гарантируется

Например,

mutation {
 doStuff1() {
   id
 }
 doStuff2() {
   id
 },
}

Здесь гарантируется, что doStuff2 будет выполнена после doStuff1.

При использовании неймспейсов, если с клиента послать запрос:

mutation {
 namespace {
   doStuff1() {
     id
   }
   doStuff2() {
     id
   },
 }
}

Порядок выполнения мутаций не гарантируется

Мутация должна возвращать свой уникальный Payload-тип

Результат выполнения мутации тоже необходимо возвращать в виде вложенного Payload-типа с уникальным именем ... ... ...

Позволю себе немного дополнить правило.
Любая мутация меняет что-либо в том или ином ресурсе (например, статус заказа), поэтому на выходе мутации удобно знать:

  1. Успешно или нет были внесены изменения
  2. Список ошибок, если что-то пошло не так
  3. Сам измененный ресурс

В своем API я решил, что все мутации обязательно возвращают объект "операция", который, кроме полей выше, содержит автора и время когда была проведена собственно модификация ресурса:

type OrderOperationUpdate {
  status: OrderOperationUpdateStatus! # fail, success, etc
  order: Order
  createdAt: Int! # Unix-timestamp
  createdBy: User!
  errors: [OrderOperationUpdateError!]!
}

Получаем несколько плюсов:

  1. Результат мутации приобретает вполне себе опред. смысл и, как следствие, фронтендеру легче "въехать" в логику API.
  2. Операцию можно не просто возвращать, а хранить в БД и сразу получить механизм логгирования.
  3. Ссылку на операцию можно передавать в событиях, которые генерируются в мутации (в операцию нужно будет добавить поле с идентификатором)
  4. Так-как есть соглашение о том, что все мутации на выходе дают операции, то это дисциплинирует разработчика, перед созданием мутации ему приходится думать "а какую операцию я верну на выходе? какой у нее бизнесовый смысл?"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.