Избегайте ошибки 403 quotaExceeded для создания нескольких аксиос HTTP-запросов в Google API - PullRequest
0 голосов
/ 16 октября 2018

Мне нужно сделать большой цикл запросов в Google API с помощью axios в моем внутреннем NodeJS.

Но Google API блокируется в определенное время с ошибкой 403, когда вы заполняете его запросами.Как сказано в документации, нам нужно использовать метод экспоненциального отката https://developers.google.com/admin-sdk/directory/v1/limits

Повторить с использованием экспоненциального отката.Вам нужно замедлить скорость, с которой вы отправляете запросы.

Поток для реализации простого экспоненциального отката следующий:

Make a request to the API
Receive an error response that has a retry-able error code
Wait 1s + random_number_milliseconds seconds
Retry request
Receive an error response that has a retry-able error code
Wait 2s + random_number_milliseconds seconds
Retry request
Receive an error response that has a retry-able error code
Wait 4s + random_number_milliseconds seconds
Retry request
Receive an error response that has a retry-able error code
Wait 8s + random_number_milliseconds seconds
Retry request
Receive an error response that has a retry-able error code
Wait 16s + random_number_milliseconds seconds
Retry request
If you still get an error, stop and log the error.

Мой код ниже

const router = require("express").Router();
const axios = require("axios");
const { google } = require("googleapis");

const scopeGooleAPI = [
  "https://www.googleapis.com/auth/admin.directory.group.readonly",
  "https://www.googleapis.com/auth/admin.directory.group.member.readonly",
  "https://www.googleapis.com/auth/admin.directory.user.readonly",
  "https://www.googleapis.com/auth/admin.directory.resource.calendar",
  "https://www.googleapis.com/auth/calendar"
];

var clientGoogleAPI = new google.auth.JWT(
  client_email,
  null,
  private_key,
  scopeGooleAPI,
  "admin@admin.com"
);

router.post("/insertResourceHTTP", (req, res) => {
  if (!clientGoogleAPI)
    return res
      .status(500)
      .json("Google G Suite Credentials have not been found in the .env file");

  return clientGoogleAPI.authorize((err, tokens) => {
    if (err) return res.status(500).json(err);

    let config = {
      headers: { Authorization: "Bearer " + tokens.access_token }
    };

    let axiosArray = [];

    function callHttpRequestGoogle(i, s = 1) {
      return axios
        .post(
          "https://www.googleapis.com/admin/directory/v1/customer/my_customer/resources/calendars",
          {
            //json : true,
            resourceId: "resourceIdPromise" + i, // required
            resourceName: "resourceNamePromise" + i, // required
            // buildingId: "",
            // capacity: 0,
            // etags: "",
            // floorName: "",
            // floorSection: "",
            generatedResourceName: "generatedResourceNamePromise" + i,
            kind: "admin#directory#resources#calendars#CalendarResource",
            resourceCategory: "OTHER",
            resourceDescription: "resourceDescription",
            resourceEmail: "resourceEmail",
            resourceType: "resourceType",
            userVisibleDescription: "userVisibleDescription"
          },
          config
        )
        .then(responseCatched => {
          return { responseCatched: responseCatched };
        })
        .catch(errorCatched => {
          if (errorCatched.response.data.error.code === 403) {
            console.log(errorCatched.response.data.error.code, s, i);
            s += 1;
            return axiosArray.push(
              setTimeout(() => {
                callHttpRequestGoogle(i, s);
              }, s * 1000)
            );
          }
          return { errorCatched: errorCatched };
        });
    }

    for (let i = 12300; i < 12800; i++) {
      axiosArray.push(callHttpRequestGoogle(i));
    }

    Promise.all(axiosArray).then(OKK => {
      console.log("Array completed");
      axios
        .all(axiosArray)
        .then(
          axios.spread((...argsResponse) => {
            let responseArray = [];
            for (let i = 0; i < argsResponse.length; i++) {
              // 3 cases : There is an error, there is no error, or there is an unknown error
              if (argsResponse[i].hasOwnProperty("errorCatched")) {
                responseArray.push({
                  return: argsResponse[i].errorCatched.response.data.error,
                  data: JSON.parse(
                    argsResponse[i].errorCatched.response.config.data
                  )
                });
              } else if (argsResponse[i].hasOwnProperty("responseCatched")) {
                responseArray.push({
                  return: "Item well added statusCode 200",
                  data: argsResponse[i].responseCatched.data
                });
              } else {
                responseArray.push({
                  return: "unknown error, sorry about that"
                });
              }
            }
            res.status(200).json(responseArray);
          })
        )
        .catch(err => {
          res.status(500).json(err.message);
        });
    });
  });
});

Обещание не дожидается завершения конца массива let axiosArray = [];.Обещание относится только к первому циклу

for (let i = 12300; i < 12800; i++) {
  axiosArray.push(callHttpRequestGoogle(i));
}

Поскольку axiosArray подается во второй раз путем повторного нажатия, когда в .catch .catch(errorCatched => {})

было обнаружено отклонениепроблема в том, что эта строка console.log("Array completed"); выполняется и, как следствие, также res.status(200).json(responseArray);, которая выходит из сценария.

Я вижу, что он все еще работает в фоновом режиме, потому что console.log(errorCatched.response.data.error.code, s, i); возвращаются и иногда даже увеличиваются до 10 секунд.

axiosArray.push(
  setTimeout(() => {
    callHttpRequestGoogle(i, s);
  }, s * 1000)
);

Вы не сможете запустить этосценарий, если у вас нет учетной записи Google G Suite.А также ваши собственные учетные данные в классической учетной записи разработчика Google.

Но есть ли у вас какие-либо предложения, чтобы сказать мне, альтернатива?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...