0

I have a full stack app that takes input from a user and posts the data to a Google Spreadsheet using their API service.

The service was working perfectly until a few months ago where one of the requests from a client failed to post and gave us the error: 2020-03-09T11:42:49.035293+00:00 app[web.1]: The API returned an error: Error: The service is currently unavailable.

After investigating, this error refers to a 503 and the solution would be to retry, so I decided to use an npm package called 'retry' and added this inside the "listMajors" function (see Spreadsheets API sample in: https://developers.google.com/sheets/api/quickstart/nodejs), like this:

   function listMajors(auth) {
     const sheets = google.sheets({version: 'v4', auth});
     // 3 Attempt wrapper
     function listMajorsWrapper(callback) {
       operation.attempt(function(currentAttempt) {
         sheets.spreadsheets.values.append({
           spreadsheetId: config.spreadsheetId,
           range: 'Requests',
           valueInputOption: 'USER_ENTERED',
           insertDataOption: 'INSERT_ROWS',
           resource: {
             "values":
             [
               data
             ]
           }
         }, (err, res) => {
           if (operation.retry(err)) {
               return;
           }
           callback(err ? operation.mainError() : null, res);
           //if (err) return console.log('The API returned an error: ' + err);
         });
       })
     }
     listMajorsWrapper(function(err, result) {
       console.log(err, result);
     });
   }

The retry options are:

   // RETRY configuration
   var operation = retry.operation({
     retries: 2,            // try 1 time and retry 2 times if needed, total = 3
     minTimeout: 10 * 1000, // the number of milliseconds before starting the first retry
     maxTimeout: 60 * 1000  // the maximum number of milliseconds between two retries
   });

Yesterday, I did around 5 tests and two of them gave me a duplicate.

After searching the logs, I found "retry: true".

2020-05-14T13:46:52.070771+00:00 app[web.1]: 'Content-Type': 'application/json',

2020-05-14T13:46:52.070772+00:00 app[web.1]: Accept: 'application/json' },

2020-05-14T13:46:52.070772+00:00 app[web.1]: params:

2020-05-14T13:46:52.070772+00:00 app[web.1]: { valueInputOption: 'USER_ENTERED',

2020-05-14T13:46:52.070773+00:00 app[web.1]: insertDataOption: 'INSERT_ROWS' },

2020-05-14T13:46:52.070773+00:00 app[web.1]: validateStatus: [Function],

2020-05-14T13:46:52.070773+00:00 app[web.1]: retry: true,

Questions:

  1. Does Google offer a retry option? If so, how many retries do they have?
  2. Is this a good way to code a retry for Spreadsheets API or should I be doing something different (do you have examples)?

Edit after Alessandro's response: npm retry uses an exponential backoff <-- this is the right retry approach

New --> "Added a timeout"

Will this wait for a Google retry to happen first and avoid the duplicate or just delays the initial check?

I did several tests yesterday and I didn't see a duplicate, but that doesn't mean that it's still correct. I'm not 100% sure.

    setTimeout(function() {
       if (operation.retry(err)) {
         return;
       }
       callback(err ? operation.mainError() : null, res);
    }, 10000)
Abak
  • 41
  • 1
  • 11

1 Answers1

1

Approach

Since the nature of the error 503 is transient is a good approach to implement a retry logic in your application. Google recommends a strategy called Exponential Backoff. It is used to improve bandwidth usage and maximize throughput of requests in concurrent environments.

Examples

Google Exponential Backoff - Theory

Google Exponential Backoff - Samples

Alessandro
  • 2,848
  • 1
  • 8
  • 16
  • Thank you for this answer. Even though this is aimed at Cloud IoT and not Spreadsheets API, this pointed me in the right direction. The retry npm package does exactly what they're saying exponential backoff should do... The only thing different that I did was to add a timeout before checking the error. That way, it wouldn't trigger a duplicate if Google also has a retry. Hopefully this solves the problem or just delays the initial check. – Abak May 19 '20 at 13:08