Я использую 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)
})
// (...)
@ 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
прежде чем наносить слой крема поверх него.
Самый полезный комментарий
Может быть, мне стоит добавить то, что я делаю прямо сейчас, для других людей, приходящих из Google. Сейчас я использую
p-throttle
( репо ).