Apollo-link-rest: Элегантный способ поставить в очередь запросы к серверу отдыха? Максимальный параллелизм, временное расстояние, регулирование 🚙⟷🚕⟷🚗?

Созданный на 20 янв. 2019  ·  7Комментарии  ·  Источник: apollographql/apollo-link-rest

Я использую apollo-link-rest для создания вызовов бесплатного стороннего api rest. Я считаю, что это отличный вариант использования.

Однако, как мы все знаем, сторонние api должны обрабатываться с _ уважением в отношении параллелизма запросов и минимальных пробелов в безопасности между последовательными запросами api. То есть убедитесь, что вы обращаетесь к серверу не чаще, чем каждые 100 мс.

Поскольку apollo принимает звонки, мне было интересно, есть ли хороший способ распределить звонки по времени ? Случайно не требуется много времени, чтобы создать запрос, который запускает дополнительные запросы для разрешения полного запроса. Например, с помощью директивы @export .

_Два звонка одновременно _ 🚀🚀

const QUERY = gql`
  query RestData($email: String!) {
    # 1) Query for user 🚀
    users @rest(path: '/users/email?{args.email}', method: 'GET', type: 'User') {
      id @export(as: "id")
      firstName
      lastName
      # 2) Sub query for friends fires immediately as well 🚀
      friends @rest(path: '/friends/{exportVariables.id}', type: '[User]') {
        firstName
        lastName
      }
    }
  }
`;

Чтобы смягчить легкие случаи проблемы с запросом n + 1 (т.е. получить все продукты, чем описание каждого продукта), я хотел бы иметь возможность иметь страховочную сетку для ошибок сервера 429 (сбой из-за ограничения скорости с сервера).

_Что я делаю сейчас: упаковка fetch_

const restProviders = new RestLink({
  endpoints: {
    mySlowEndpoint: baseUrl
  },
  customFetch: (...args) =>
    new Promise((resolve, reject) => {
      // 🚙⟷🚕⟷🚗 Implementing my queue logic to fire of fetches
        resolve(fetch(...args));
      // when enough time has elapsed. 🚙⟷🚕⟷🚗 
    })
})

Прямо сейчас я оборачиваю процесс выборки в логику настраиваемой очереди, но есть ли «более элегантный способ», который мы могли бы интегрировать? Я уверен, что многим людям было бы интересно иметь некоторый контроль над исходящей нагрузкой, не обязательно сразу же сбивая запросы.

Самый полезный комментарий

Может быть, мне стоит добавить то, что я делаю прямо сейчас, для других людей, приходящих из Google. Сейчас я использую p-throttle ( репо ).

// (...)
import pThrottle from "p-throttle";

const restProviders = new RestLink({
  endpoints: {
    mySlowEndpoint: baseUrl
  },
  // Throttle fetches to max 1 concurrent request 🚀 and
  //  min. delay of 0.5 seconds 🚙⟷🚕⟷🚗 .
  customFetch: pThrottle( (...args) => {
    return fetch(...args);
  }, 1, 500)
})

// (...)

Все 7 Комментарий

Может быть, мне стоит добавить то, что я делаю прямо сейчас, для других людей, приходящих из Google. Сейчас я использую p-throttle ( репо ).

// (...)
import pThrottle from "p-throttle";

const restProviders = new RestLink({
  endpoints: {
    mySlowEndpoint: baseUrl
  },
  // Throttle fetches to max 1 concurrent request 🚀 and
  //  min. delay of 0.5 seconds 🚙⟷🚕⟷🚗 .
  customFetch: pThrottle( (...args) => {
    return fetch(...args);
  }, 1, 500)
})

// (...)

@ D1no Я собирался предложить customFetch, но вы уже это сделали!

Я не уверен, что это действительно должна быть напрямую настраиваемая функция Apollo-link-rest, но я бы поддержал включение такого фрагмента в документацию.

Не могли бы вы указать мне на хорошее место в документации, чтобы PR этой информации как пример того, что можно сделать с customFetch? Я думаю ты прав; добавление такой настраиваемости в apollo-link-rest привело бы к объединению методологий выборки, что не очень элегантно.

В PR я бы исключил p-queue для более надуманного примера для читающих новичков. Любой, кто серьезно использует apollo-link-rest в качестве средства доступа к GraphQL, в какой-то момент будет нуждаться в некотором управлении параллелизмом / устранением ошибок.

Эй @ D1no, вы можете найти документы здесь . Я бы посоветовал разместить его в заголовке Options над Complete options .

Спасибо @tombarton. Присмотревшись к проблеме еще раз, было бы неплохо иметь возможность иметь простой параметр дросселирования для вызова fetch.

Хотя я изначально сказал, что это связанная выборка, на самом деле это не так. Это призыв к (любой произвольной) методологии выборки, которая здесь широко распространена. Чтобы иметь возможность приручить apollo-link-rest слепое / нетерпеливое выполнение, некоторые простые параметры параллелизма и ограничения ms, как показано выше , в конечном итоге могут быть не такой уж плохой идеей.

const restProviders = new RestLink({
  endpoints: {
    mySlowEndpoint: baseUrl
  },
  maxConcurrency: 2 // Max Concurrency 🚀🚀
  minThrottle: 500 // Handling Rate Limit in ms 🚙⟷🚕⟷🚗 
})

и / или возможность указать его в запросе

const QUERY = gql`
  query RestData($email: String!) {
    users @rest(path: '/users/email?{args.email}', method: 'GET', type: 'User') {
      id @export(as: "id")
      firstName
      lastName
      # NEW:       ⤥ 🚙⟷🚕     ⤥ 🚀🚀
      friends @rest(throttle: 500, concurrency: 2, path: '/friends/{exportVariables.id}', type: '[User]') {
        firstName
        lastName
      }
    }
  }
`;

В конце концов, почему методология выборки должна управлять тем, как часто она вызывается (ей все равно, что происходит наверху). Я немного подумаю об этом. В любом случае customFetch должен получить некоторую информацию о текущем запросе, а не только пустой запрос (чтобы иметь возможность принимать разумные решения, если людям это действительно нужно).

Может быть, кто-нибудь из сопровождающих / сотрудников (@fbartho) сможет вмешаться? Я был бы счастлив потратить время на пиар, если его достоинства будут одобрены.

@ D1no Мне искренне понравилось ваше предложение о включении в документацию. - Очередь - это противоположность тому, как мы хотели делать что-то в приложении нашей компании. (Например, я построил дедупликацию).

По отдельности, поскольку конечные точки могут быть совершенно разными, я не решаюсь установить «maxConcurrency / minThrottle» как глобальную проблему.

ApolloLinkRest предназначен для «подключения вещей к Apollo» - эти проблемы, которые вы описываете, действительно кажутся так, как будто они должны быть на сетевом уровне, также известном как пользовательская выборка. - Кроме того, я считаю маловероятным, что вы захотите настраивать эти значения для каждого пути запроса, поэтому встраивание их настроек в GraphQL кажется шумным.

Хорошо - сначала я буду пиарить дополнение к документации. Мы должны сначала довести до нижнего предела customFetch прежде чем наносить слой крема поверх него.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги