Apollo-link-rest: Maneira elegante de enfileirar as solicitações de descanso do servidor? Simultaneidade máxima, distância de tempo, estrangulamento 🚙⟷🚕⟷🚗?

Criado em 20 jan. 2019  ·  7Comentários  ·  Fonte: apollographql/apollo-link-rest

Estou usando o apollo-link-rest para criar chamadas para uma API de descanso gratuita de terceiros. Acho que é um ótimo caso de uso.

No entanto, como todos sabemos, as apis de terceiros devem ser tratadas com _respeito em relação à simultaneidade de solicitações e lacunas de segurança mínimas entre solicitações de APIs sucessivas_. Ou seja, certificando-se de que você está acessando o servidor não mais frequentemente do que a cada 100 ms.

Como Apollo está assumindo as ligações, eu queria saber se existe uma boa maneira de distribuir as ligações ao longo do tempo . Por acidente, não é preciso muito para criar uma consulta que dispara solicitações adicionais para resolver a solicitação completa. Por exemplo, usando a diretiva @export .

_Duas ligações de uma vez_ 🚀🚀

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
      }
    }
  }
`;

Para mitigar casos leves de problema de consulta n + 1 (ou seja, buscar todos os produtos, além da descrição de cada produto), gostaria de poder ter uma rede de segurança para erros do servidor 429 (falha devido à limitação de taxa do servidor).

_O que eu faço agora: Wrapping 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. 🚙⟷🚕⟷🚗 
    })
})

No momento, estou envolvendo o processo de busca na lógica de fila personalizada, mas existe uma "maneira mais elegante" de integrar isso? Tenho certeza de que muitas pessoas estariam interessadas em ter algum controle da carga de saída sem necessariamente falhar nas consultas imediatamente.

Comentários muito úteis

Talvez eu deva adicionar o que faço agora para outras pessoas que vêm do Google. Agora eu uso p-throttle ( repo ).

// (...)
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)
})

// (...)

Todos 7 comentários

Talvez eu deva adicionar o que faço agora para outras pessoas que vêm do Google. Agora eu uso p-throttle ( repo ).

// (...)
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 Eu ia sugerir customFetch, mas você já fez isso!

Não tenho certeza se isso realmente deve ser um recurso diretamente configurável do Apollo-link-rest, mas apoiaria a inclusão de um trecho como este nos documentos.

Você pode me indicar um bom lugar no documento para fazer a RP dessas informações como um exemplo do que se pode fazer com customFetch? Eu acho que você está certo; jogar configurabilidade como essa no apollo-link-rest acopla metodologias de busca que não são muito elegantes.

No PR, eu chutaria a fila-p para obter um exemplo mais elaborado para iniciantes lendo. Qualquer pessoa usando apollo-link-rest como uma droga de porta de entrada no GraphQL terá a necessidade de _alguma gestão de simultaneidade / eliminação_ em algum ponto.

Ei @ D1no , você pode encontrar os documentos aqui . Eu sugiro que ele fique no título Options , acima de Complete options .

Obrigado @tombarton. Olhando mais de perto o problema novamente, pode ser uma boa ideia poder ter uma opção de aceleração simples para a chamada de busca de qualquer maneira.

Embora eu tenha dito originalmente sua busca por acoplamento, na verdade isso não é verdade. É a chamada para (qualquer) metodologia de busca arbitrária que está se espalhando aqui. Para ser capaz de controlar a execução cegamente / ansiosa de apollo-link-rest, algumas opções simples de simultaneidade e limite de ms, como visto acima , podem não ser uma ideia tão ruim no final.

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

e / ou ser capaz de especificá-lo na consulta

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
      }
    }
  }
`;

Afinal, por que uma metodologia de busca deve gerenciar a frequência com que é chamada (não deve se importar com o que está acontecendo no andar de cima). Vou pensar um pouco sobre isso. De qualquer forma, customFetch deve receber algumas informações sobre a consulta atual e não apenas uma solicitação em branco (para poder tomar decisões inteligentes se as pessoas realmente precisarem).

Talvez um dos mantenedores / equipe (@fbartho) possa contribuir? Eu ficaria feliz em dedicar um tempo para uma RP se seu mérito for aprovado.

@ D1no Sinceramente, gostei da sua sugestão de incluir na documentação. - O enfileiramento é o oposto da maneira como queríamos fazer as coisas no aplicativo da nossa empresa. (A desduplicação foi uma que eu construí, por exemplo).

Separadamente, como os terminais podem ser totalmente diferentes, hesito em definir "maxConcurrency / minThrottle" como preocupações globais.

ApolloLinkRest é sobre "conectar coisas ao Apollo" - essas preocupações que você descreveu realmente parecem que deveriam estar na camada de rede, também conhecida como busca personalizada. - Além disso, acho improvável que você queira personalizar esses valores para cada caminho de consulta, portanto, incorporar suas configurações no GraphQL parece barulhento.

Tudo bem - primeiro farei uma RP de um acréscimo à documentação. Devemos chegar ao fundo de customFetch primeiro, antes de aplicar creme em cima dele.

Esta página foi útil?
0 / 5 - 0 avaliações