4
votes

I developed a Firebase Cloud function that processes several manipulations on uploaded images. My code is based on this documentation article and this Cloud Function example. Hence, it is using Google Cloud Storage package.

It is working fine almost all the time, but sometimes I am getting this error when uploading to or deleting from Storage :

 Error: read ECONNRESET
    at exports._errnoException (util.js:1026:11)
    at TLSWrap.onread (net.js:569:26)

I am using the default bucket of my application, referenced by event.data.bucket.

Let me know if you need additional information or code snippets, even if my code is really close to the Function example I linked before.

I found this GitHub issue, but I checked that I am returning a promise everytime. For example, here is the deletion part that triggers the error :

index.js

exports.exampleFunction = functions.storage.object().onChange(event => {
    return f_thumbnails.exampleFunction(event);
});

example_function.js

module.exports = exports = function (_admin, _config) {
    admin = _admin;
    config = _config;

    return {
        "exampleFunction": function (event) {
            return exampleFunction(event);
        }
    };
};

const exampleFunction = function (event) {
    const gcsSourceFilePath = event.data.name;
    const gcsSourceFilePathSplit = gcsSourceFilePath.split('/');
    const gcsBaseFolder = gcsSourceFilePathSplit.length > 0 ? gcsSourceFilePathSplit[0] : '';
    const gcsSourceFileName = gcsSourceFilePathSplit.pop();
    const gceSourceFileDir = gcsSourceFilePathSplit.join('/') + (gcsSourceFilePathSplit.length > 0 ? '/' : '');

    // Not an image
    if (!event.data.contentType.startsWith('image/')) {
        console.log('Not an image !');
        return;
    }

    // Thumbnail
    if (gcsSourceFileName.startsWith(config.IMAGES_THUMBNAIL_PREFIX)) {
        console.log('Thumbnail !');
        return;
    }

    const bucket = gcs.bucket(event.data.bucket);
    const gcsThumbnailFilePath = gceSourceFileDir + config.IMAGES_THUMBNAIL_PREFIX + gcsSourceFileName;


    // File deletion
    if (event.data.resourceState === 'not_exists') {
        console.log('Thumbnail deletion : ' + gcsThumbnailFilePath);
        return bucket.file(gcsThumbnailFilePath).delete().then(() => {
            console.log('Deleted thumbnail ' + gcsThumbnailFilePath);
        });
    }
    ...
1
Any Chance we can see what happens after the ... ?Nicolas Garnier
You have all the code corresponding to a thumbnail deletion. My function should stop at the return bucket.file(gcsThumbnailFilePath).delete(). part. I get the previous console.log('Thumbnail deletion : ' + gcsThumbnailFilePath); in Firebase backend but not the promise success completion one.OlivierH
I don't see any reasons why an ECONNRESET would happen actually. Does this happens frequently?Nicolas Garnier
Are you still affected by this issue? If so, given that ECONNRESET errors suggest an abruptly terminated connection, it would seem that the other end is closing the connection or too overloaded to handle it. In this case, the other end is the Cloud Storage servers. How frequently do/did you get these connection errors? Within what time frame?Nicholas
Yes, I'm still affected by this issue. It seems to be random, and when it happens it lasts for several minutes Forr example yesterday, between 8:16 PM and 8:23PM (UTC+2) , every upload finished with ECONNRESETOlivierH

1 Answers

2
votes

This seems to be related to the google-cloud-node library's handling of sockets, and the default socket timeout in the Cloud Functions environment.

One solution verified by a user is to modify the way the library invokes requests, to not keep the socket open forever by specifying forever: false, eg.

var request = require('request').defaults({
  timeout: 60000,
  gzip: true,
  forever: false,
  pool: {
    maxSockets: Infinity
  }
});

This is hardcoded in packages/common/src/utils.js, so you'll need to vendor a copy of the modified library into your project rather than include it as an NPM dependency. See the related public issue for more details on the issue and a link to a fork with the patch applied.