Error: Socket hang up inside google cloud (nodejs) function

Viewed 890

I'm using a google cloud function to get an token from Firestore, check if it is still active, if so return access token. Else:

  1. Get refresh token from secretmanager
  2. Refresh
  3. Update refresh token in secret manager
  4. Update access token in firebase

Now i get this error sometimes... This function is minimally called every 15 minutes from an different cloud function. The error occurs like 5 times a day. I've seen this post but can't wrap my head around to get this translated to my code.

Error:

FetchError: request to https://europe-west1-project.cloudfunctions.net/getToken failed, reason: socket hang up
        at ClientRequest.<anonymous> (/workspace/node_modules/node-fetch/lib/index.js:1461:11)
        at ClientRequest.emit (events.js:315:20)
        at ClientRequest.EventEmitter.emit (domain.js:467:12)
        at TLSSocket.socketOnEnd (_http_client.js:493:9)
        at TLSSocket.emit (events.js:327:22)
        at TLSSocket.EventEmitter.emit (domain.js:529:15)
        at endReadableNT (internal/streams/readable.js:1327:12)
        at processTicksAndRejections (internal/process/task_queues.js:80:21) 

Code:

const { SecretManagerServiceClient } = require("@google-cloud/secret-manager");
const client = new SecretManagerServiceClient();
const name = `projects/${process.env["PROJECT"]}/secrets/TOKEN/versions/latest`;

const axios = require("axios");
const milliseconds = new Date().getTime()
const now = Math.round(milliseconds / 1000);

const { Firestore } = require("@google-cloud/firestore");
const firestore = new Firestore();
const tokens = firestore.collection("tokens");

module.exports = async function getToken() {
  let responseData;

  await tokens.where("system", "==", "x").limit(1).get()
    .then((res) => {
      res.forEach((snap) => {
        responseData = snap.data();
      });
    })
    .catch((err) => {
      console.error(JSON.stringify(err));
    });
  
  console.log(`custom_log: now = ${now}`)
  console.log(JSON.stringify(responseData))
  
  if (now - responseData.timestamp < 250) {
    console.log(`custom_log: Returning access token from Firebase`)
    return responseData.access_token;
  } else {
    console.log(`custom_log: Return new access token`)
    return await refreshToken();
  }
};

async function refreshToken() {
  const [version] = await client.accessSecretVersion({ name: name });
  const secret = version.payload.data.toString();

  const config = {
    method: "post",
    url: "https://login.webpage.com/token?grant_type=client_credentials",
    headers: {
      Authorization: `Basic ${secret}`,
    },
  };
  return axios(config)
    .then((response) => {
      updateAccesToken(response.data.access_token)
      return response.data.access_token;
    })
    .catch((error) => {
      console.error(`custom_error: Error refresh token: ${error.message}`);
    });
}

async function updateAccesToken(token) {
  await tokens.doc('token').update({
    timestamp: now,
    access_token: token,
    dateTime: new Date(milliseconds).toISOString()
  })
  console.log('custom_log: access_token updated in Firestore')
}

Screenshot error reporting

1 Answers

2021/09/13 updated, even i made a new cloud function without setting the timeout (with the same codes), the error doesn't occur anymore; I updated google-auth-library from 6.1.6 to 7.9.1 just in case, and so far it works

2021/09/10 updated, in order to test how much time my program needs, i changed timeout back to 60 secs, but it still works...finding way to reproduce now

the original message: I encountered the same error at cloud function (it works in local env).

After I set the timeout of cloud function to 80 secs, the error seems resolved.

These are the steps my program does, just for your reference

  1. getting data from secret manager
  2. using google-api to read 2 spreadsheets
  3. using google-api to update 1 spreadsheet

With the previous version (getting data from secret-manager and then read 1 spreadsheet and update it), this error didn't occur.

Related