Павел Черторогов - Строим GraphQL-сервер

Sdílet
Vložit
  • čas přidán 28. 03. 2019
  • Ближайшая конференция - HolyJS 2024 Autumn, 7 ноября (online), 14-15 ноября (Санкт-Петербург + трансляция).
    Подробности и билеты: jrg.su/K18Cxd
    - -
    . . Павел работает с GraphQL около 4 лет, является автором graphql-compose и действительно знает, как делать с GraphQL безумно крутые штуки. Готовясь к HolyJS, он собрал материала на книгу с небольшим, мы отобрали самые сливки из этого. Никаких интродакшнов! Только глубокие кейсы.
    REST API был хорош для своего времени и Swagger тоже. Кругом все обсуждают компонентный подход, поэтому в 2018 году бэкендерам сильно пора задуматься о GraphQL. По факту это новый стандарт мега-удобного API для фронтендеров и их компонентного подхода. Но что фронтендеру хорошо, то может стать болью для неподготовленного бэкендера.
    В докладе рассмотрим моменты, о которых стоит задуматься бэкендеру. Из каких кусочков собирается GraphQL-сервер: в интернетах уже много пакетов, хорошо бы понять, что необходимо установить и, самое главное, зачем. Что такое схема и как ее написать, чтобы все это дело зашуршало. Рассмотрим авторизацию, написание примитивного ACL. Затронем вопрос производительности и безопасности. Разберем тему загрузки файлов, генерации схем, документирования и всё ли хорошо с версионированием API.
    Доклад будет полезен разработчикам любого уровня, как уже использующим GraphQL, так и присматривающимся к данной перспективной технологии.
  • Věda a technologie

Komentáře • 7

  • @dimitro.cardellini
    @dimitro.cardellini Před 4 lety +25

    Павел -- лучшие доклады на русском по JS и GraphQL, которые я видел за крайние два года. Респект.
    По данному докладу есть ряд замечаний.
    1. По авторизации -- лучше вернуть токен явно в ответе, чем совать его в куки.
    Во-первых, куки (даже httpOnly) доступны расширениям (stackoverflow.com/questions/40064016/access-to-cookies-from-chrome-extensions).
    Во-вторых, правильная установка куков потребует от GraphQL-сервера знать всех своих клиентов (или завязаться всегда на работу на одном origin)
    В-третьих, это дело клиента, где и как хранить куки и для каких целей (для интернте-банков, например, можно вообще все хранить только в памяти, да, после рефреша страницы надо переавторизовываться, но с другой стороны -- "С -- секьюрити")
    2. По дата-лоадерам -- ids.map(id => results.find(item => item.id === id)) имеет сложность в O(n^2), а точнее n^2/2. Это означает, что если (ну так получилось) у нас 10 тыс. ids, то наш цикл будет на 50 млн.итераций. И даже вполне банальная сотня айдишек даст 5 тыс. итераций.
    Правильно делать так:
    const resultById = new Map();
    results.forEach(r => resultById.set(r.id, r));
    return ids.map(id => resultById.get(id));
    Такой подход имеет оценку уже в O(n). А если точнее, то 2n (stackoverflow.com/questions/33611509/es6-map-and-set-complexity-v8-implementation). Это значит, что уже для 4-х идешек мы получим такое же быстродействие, а на 5 уже будем быстрее, ну и очевидно, что 200 много быстрее, чем 5000.
    Кстати, там где поиск идет не по первичному, а по вторничному ключу: (например, надо в автора добавить все его статьи), то ids.map(id => results.filter(item => item.id === id)) уже будут давать чистые n * m (вместо n + m).
    3. Снова по дата-лоадерам. Дата лоадеры кешируют ответ от базы, но, т.к. мы в 99% случаев пользуемся ORM/ODM, то кешируется Модель. Это означает, что уникальность дата-лоадера должна быть на уровне request + model, а не request + resolver. Если модели из базы берутся, и по первичному, и по вторичнму ключам, то получается: request + model + keyField.
    4. И еще одно про кеши: Никогда! Никогда нельзя опираться на незадокументированные фичи. В данном случае нельзя в качетсве ключей кэша использовать info.fieldNodes, т.к. никто не давал гарантий того, что это поле будет ссылаться на один и тот же объект при разных вызовах резолвера.
    У нас код резолвера выглядит примерно вот так:
    fieldResolver = (_, { id }, { dataLoaders }) => dataLoaders(loaderFactory).load(id);
    где,
    dataLoaders -- это функция, которая обеспечивает кэширование лоадеров ну уровне одного запроса.
    loadFactory -- это функция, которая создает конкретный датаЛоадер. Собственно эта функция и используется в качестве ключа для кэша дата-лоадеров.
    Т.е. пример с дата-лоадерами я бы сделал вот таким:
    gist.github.com/DScheglov/fd17a6de80b527d977633ace0e3b217f (с поправкой на способ описания graphQL).
    Я бы так много не писал, если бы, когда пришел на новый проект, не увидел там несколько десятков резолверов, каждый из которых на 99% совпадает с приведенным примером (с поправкой на имена переменных). Т.е. внутри резолвера у нас все: и объявление дата-лоадера, и его кеширование, и запрос данных. И, я думаю, что таких проектов на просторах гитхаба и битбакета неимоверное множество.

  • @shamilmammadov8246
    @shamilmammadov8246 Před 4 lety +3

    Огромное спасибо за доклад. Просто великолепно!

  • @gdk111
    @gdk111 Před 5 lety +19

    Почему не дали ему два часа? Пришлось комкать, а так интересно

  • @bubblesort6368
    @bubblesort6368 Před 3 lety

    Идея с DataLoaders напоминает один огромный кАстыль в вашем коде продиктованный безысходностью...

  • @mackaybravo6770
    @mackaybravo6770 Před 3 lety +2

    Загрузка файлов через graphql просто проклятая тема.

  • @user-kr6ry1wm6p
    @user-kr6ry1wm6p Před rokem

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

  • @alexbaumgertner
    @alexbaumgertner Před 5 lety +1

    Классный доклад!
    Презентация nodkz.github.io/conf-talks/talks/2018.11.24-holyjs-moscow/