Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retry logic when rate-limited #525

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

darraghmckay
Copy link

This PR adds optional logic that will retry every request that returns in a 429 response.
A 429 means you have been rate-limited according to these usage-limits

This is off by default and is only enabled by running

doc.setRetryOptions(retries, retryDelay)

It felt kinda weird setting it on a doc level rather than a library level but I wasn't sure what was best. Definitely open to suggestions there.

Fixes: #418

@wingedfox
Copy link

This is quite a must-have option, without the library-level support for the back-offs it's almost impossible to develop anything.

@TaylorFacen
Copy link

Checking in on the status of this PR. Built-in retry logic would be very helpful.

@darraghmckay
Copy link
Author

It doesn't seem like there's been any activity on this project in quite a while unfortunately
I can't merge this without approval from the repo admin

@agladysh
Copy link

NB: Google Sheets API lists rate limits and suggests a specific backoff algorithm to follow:

https://developers.google.com/sheets/api/limits

@charlesgardyn
Copy link

charlesgardyn commented Dec 18, 2023

While this is not merged, you can use axios-retry:

import { AxiosInstance } from 'axios'
import axiosRetry from 'axios-retry'
import { JWT } from 'google-auth-library'
import { GoogleSpreadsheet } from 'google-spreadsheet'
import _ from 'lodash'

function retry(axiosInstance: AxiosInstance) {
  axiosRetry(axiosInstance, {
    retries: 7,
    retryDelay: retryCount => {
      const randomNumberMS = _.random(1000, 8000)
      return Math.min(4 ** retryCount + randomNumberMS, maximumBackoff)
    },
    retryCondition: error => error.response.status === 429,
  })
}

const auth = new JWT({
    email: client_email,
    key: private_key,
    scopes: ['https://www.googleapis.com/auth/spreadsheets'],
  })
const doc = new GoogleSpreadsheet(sheetId, auth)

retry(doc.sheetsApi)
retry(doc.driveApi)

@ruscon
Copy link
Contributor

ruscon commented Jan 31, 2024

While this is not merged, you can use this retry approach for downloadAsTSV

  // node@^15 
  import { setTimeout } from 'node:timers/promises'
  import type { GoogleSpreadsheetWorksheet } from 'google-spreadsheet'

  async downloadAsTSV(sheet: GoogleSpreadsheetWorksheet): Promise<ArrayBuffer> {
    try {
      return await sheet.downloadAsTSV()
    } catch (error) {
      // axios@^1.0.0
      if (error instanceof AxiosError && error.response?.status === 429) {
        await setTimeout(10000)
        console.warn(`retry downloadAsTSV for "${sheet.title}"`)

        return downloadAsTSV(sheet)
      }

      throw error
    }
  }

@steveoh
Copy link

steveoh commented Aug 19, 2024

ping @theoephraim 🦗

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Check API status / Automated retry logic
7 participants