I'd like to resize an image stored in Firebase Storage with Firebase Functions.
Based on this example : https://github.com/firebase/functions-samples/blob/master/quickstarts/thumbnails/functions/index.js I try to write a function triggered by a Database event.
Here is the most interesting part of the code :
const gcs = require('@google-cloud/storage')();
...
const bucket = gcs.bucket('...appspot.com');
const originalFilepath = myObject.picture1Url;
const tempFilePath = '/tmp/myThumbnail';
console.log('1');
return bucket
.file(originalFilepath)
.download({
destination: tempFilePath
})
.then(() => {
console.log('2');
});
Everything looks fine to me. However the code never go to the console.log('2'); and I get this error :
Error: read ECONNRESET
at exports._errnoException (util.js:1026:11)
at TCP.onread (net.js:569:26)
Does somebody know what could be the error?
Thank you
I got an econn error with my realtime database function, perhaps my fix could help you debug your issue? (See example of logs occuring after function terminates: https://github.com/firebase/firebase-functions/issues/18#issuecomment-288375709
As @ahaverty said can you make sure you return a Promise correctly in your code. From your snippet your code looks OK though but it's missing some parts of it we can't be sure.
Thank guys, you are right. I did some test and the problem really seems to be a problem with a return.
I don't really understand when I have to return something. I want to do something like this :
exports.myFunction =
functions
.database
.ref('...')
.onWrite(event => {
...
// Create thumbnails
createThumbnail(1, ...);
createThumbnail(2, ...);
createThumbnail(3, ...);
...
return; // <- Is this necessary ?
});
function createThumbnail(...) {
...
return bucket
.file(originalFilepath)
.download({
destination: tempFilePath
})
.then(() => {
...
// Generate a thumbnail using ImageMagick.
return spawn('convert', [tempFilePath, '-thumbnail', dimension + 'x' + dimension + '>', tempFilePath])
.then(() => {
....
// Uploading the thumbnail.
return bucket.upload(tempFilePath, {
destination: thumbnailUrl
})
.then(() => {
...
// Save thumbnailUrl in database
return admin.database().ref(...).set(thumbnailUrl);
});
});
});
}
This code doesn't work. I tried to remove some of these return but either I have a read ECONNRESET or a TimeOut.
If you can give me any advice, I'd be very thankful
Yes the issue is what @ahaverty described.
When you do this:
createThumbnail(1, ...);
createThumbnail(2, ...);
createThumbnail(3, ...);
...
return;
You are starting 3 asynchronous processes but you are returning right away. Therefore the instance gets shut down and your 3 createThumbnail don;t have time to complete.
Each of these returns a Promise. What you need to do is this instead:
const listOfAsyncJobs = [];
listOfAsyncJobs.push(createThumbnail(1, ...));
listOfAsyncJobs.push(createThumbnail(2, ...));
listOfAsyncJobs.push(createThumbnail(3, ...));
...
return Promise.all(listOfAsyncJobs); // This will ensure we wait for the end of the three aync tasks above.
PS: I'll also reply on your Stack Overflow post.
Thanks a lot. You have saved my day !
Most helpful comment
Yes the issue is what @ahaverty described.
When you do this:
You are starting 3 asynchronous processes but you are returning right away. Therefore the instance gets shut down and your 3
createThumbnaildon;t have time to complete.Each of these returns a
Promise. What you need to do is this instead: