Functions-samples: Error: read ECONNRESET when working with large data in Firebase Cloud functions

Created on 8 Nov 2017  路  1Comment  路  Source: firebase/functions-samples

I perform the following task, during the registration of users for the first few months we did not save images of users in Firebase Cloud Storage and took a link that was received from Facebook. Now faced with the problem that some links to images have become expired. Because of this, I decided to make the cloud function and run it once as a script, so that it went through to users who have only one link to the image (which means that this is the first link received from facebook), take the facebook user id and request current profile image. I got a json file with the given users from Firebase, then I get links for each user separately, if the user is deleted then I process this error in a separate catch so that it does not stop the work of other promises. But after running this cloud function, I ran into this error because of this, for almost all users this operation was not successful. Even I increased the memory size in cloud function to 2 gigabytes. Please tell me how it can be fixed?

{ Error: read ECONNRESET
    at exports._errnoException (util.js:1018:11)
    at TLSWrap.onread (net.js:568:26) code: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read' }

My function

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const account_file = require('../account_file.json');
var FB = require('fb');
const path = require('path');
const imageDownloader = require('image-downloader');
const os = require('os');
const shortid = require('shortid');
const imageManager = require('../../lib/Images/image-manager.js');

module.exports = functions.https.onRequest((req, res) => {
    const token = req.header('X-Auth-Token');

    var errorsCount = 0;

    return admin.auth().verifyIdToken(token)
        .then(function(decodedToken) {
            const adminID = decodedToken.uid;
            console.log('adminID is', adminID);

            const users = account_file['users'];

            var fixPhotoPromises = [];

            users.forEach(function(user) {
                const userID = user['localId']; 
                const fixPhotoPromise = fixPhoto(userID).catch(error => {
                    console.log(error);
                    errorsCount += 1;
                });
                fixPhotoPromises.push(fixPhotoPromise);
            });
            return Promise.all(fixPhotoPromises);
        }).then(results => {
            console.log('results.length', results.length, 'errorsCount', errorsCount);
            console.log('success all operations');
            const successJSON = {};
            successJSON["message"] = "Success operation";
            return res.status(200).send(successJSON);
        }).catch(error => {
            console.log(error);
            const errorJSON = {};
            errorJSON["error"] = error;
            return res.status(error.code).send(errorJSON);
        });
});

function fixPhoto(userID) {
    var authUser = {};
    var filename = '';
    return new Promise((resolve, reject) => {

        return admin.auth().getUser(userID)
            .then(userModel => {
                const user = userModel.toJSON();
                const facebookID = user['providerData'][0]['uid'];
                const userID = user['uid'];
                authUser = {'userID' : userID, 'facebookID' : facebookID};

                const userImagesPromise = admin.database().ref()
                    .child('userImages')
                    .child(userID)
                    .once('value');
                return Promise.all([userImagesPromise])
            }).then(results => {
                const userImagesSnap = results[0];
                if (userImagesSnap.val() !== null && userImagesSnap.val() !== undefined) {
                    const userProfileImagesDict = userImagesSnap.val()['userProfileImages'];
                    const keys = Object.keys(userProfileImagesDict);
                    var userProfileImages = [];
                    keys.forEach(function(key){
                        const userProfileImage = userProfileImagesDict[key];
                        userProfileImages.push(userProfileImage);
                    });
                    if (userProfileImages.length > 1) {
                        const status = 'user has more than one image';
                        return resolve(status);
                    }
                }
                const facebookAppID = functions.config().facebook.appid;
                const facebookAppSecret = functions.config().facebook.appsecret;

                const facebookAccessPromise = FB.api('oauth/access_token', {
                    client_id: facebookAppID,
                    client_secret: facebookAppSecret,
                    grant_type: 'client_credentials'
                });
                return Promise.all([facebookAccessPromise]);
            }).then(results => {
                const facebookResult = results[0];
                const facebookAccessToken = facebookResult['access_token'];

                const profileImageURL = 'https://graph.facebook.com/' + authUser.facebookID + '/picture?width=9999&access_token=' + facebookAccessToken;

                const shortID = shortid.generate() + shortid.generate() + shortid.generate();
                filename = shortID + ".jpg";
                const tempLocalFile = path.join(os.tmpdir(), filename);

                const options = {
                    url: profileImageURL,
                    dest: tempLocalFile                 // Save to /path/to/dest/image.jpg
                };

                const imageDownloaderPromise = imageDownloader.image(options);

                return Promise.all([imageDownloaderPromise])
            }).then(results => {
                const imageDownloaderResult = results[0];
                const userID = authUser.userID;
                const localImagePath = imageDownloaderResult['filename'];

                const imageManagerPromise = imageManager.saveUserImageToCloudStorage(localImagePath, filename, userID);

                return Promise.all([imageManagerPromise]);
            }).then(results => {
                const result = results[0];
                return resolve(result);
            }).catch(function(error) {
                reject(error)
            })
    });
}


exports.saveUserImageToCloudStorage = function saveUserImageToCloudStorage(localImagePath, filename, userID) {
    const bucketName = functions.config().googlecloud.defaultbacketname;
    const bucket = gcs.bucket(bucketName);

    const profileImagePath = path.normalize(path.join('userImages', userID, 'profileImages', filename));
    const profileImageFile = bucket.file(profileImagePath);

    return new Promise((resolve, reject) => {

        bucket.upload(localImagePath, {destination: profileImagePath})
            .then(() => {
                const config = {
                    action: 'read',
                    expires: '03-01-2500'
                };

                const userRefPromise = admin.database().ref()
                    .child('users')
                    .child(userID)
                    .once('value');

                return Promise.all([profileImageFile.getSignedUrl(config), userRefPromise])
            }).then(function(results) {
                const url = results[0][0];
                const userSnap = results[1];
                if (userSnap.val() === null || userSnap.val() === undefined) {
                    return resolve('user was deleted from database');
                }

                const userModel = userSnap.val();
                const userCheckID = userModel['id'];

                if (userCheckID !== userID) {
                    return reject("WARNING userCheckID !== userID");
                }

                // save to database

                const userImagesRef = admin.database().ref().child('userImages')
                    .child(userID)
                    .child('userProfileImages')
                    .push();

                const timeStamp = timestamp.now();
                const imageModelID = userImagesRef.key;
                const userImagesRefPromise = userImagesRef.update({
                    'path': url,
                    'id': imageModelID,
                    'fileName': filename,
                    'timeStamp': timeStamp
                });

                const userRef = admin.database().ref()
                    .child('users')
                    .child(userID)
                    .child('currentProfileImage');
                const userRefPromise = userRef.update({
                    'path': url,
                    'id': imageModelID,
                    'fileName': filename,
                    'timeStamp': timeStamp
                });

                return Promise.all([userImagesRefPromise, userRefPromise]);
            }).then(() => {
                const successJSON = {};
                successJSON["message"] = "Success operation";
                return resolve(successJSON);
            }).catch(function(error) {
                return reject(error);
            });
    });
};

Most helpful comment

I added this code when init google cloud storage and I did not have this error anymore.

var gcs = require('@google-cloud/storage')({keyFilename: "service-account-credentials.json"});
gcs.interceptors.push({
    request: function(reqOpts) {
        reqOpts.forever = false
        return reqOpts
    }
});

>All comments

I added this code when init google cloud storage and I did not have this error anymore.

var gcs = require('@google-cloud/storage')({keyFilename: "service-account-credentials.json"});
gcs.interceptors.push({
    request: function(reqOpts) {
        reqOpts.forever = false
        return reqOpts
    }
});
Was this page helpful?
0 / 5 - 0 ratings