Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

in firebase cloud function the bucket.upload promise resolves too early

I wrote a function that work like this

onNewZipFileRequested
{get all the necessary data}
.then{download all the files}
.then{create a zipfile with all those file}
.then{upload that zipfile} (*here is the problem)
.than{update the database  with the signedUrl of the file}

Here is the relevant code

[***CREATION OF ZIP FILE WORKING****]
}).then(() =>{
    zip.generateNodeStream({type:'nodebuffer',streamFiles:true})
    .pipe(fs.createWriteStream(tempPath))
    .on('finish', function () {
        console.log("zip written.");
        return bucket.upload(tempPath, {    //**** problem****
            destination: destinazionePath
        });
    });
}).then(()=>{
    const config = {
        action:'read',
        expires:'03-09-2391'
    }
    return bucket.file(destinazionePath).getSignedUrl(config)
}).then(risultato=>{
    const daSalvare ={
        signedUrl: risultato[0],
        status : 'fatto',
        dataInserimento : zipball.dataInserimento
    }
    return event.data.ref.set(daSalvare)
})

On the client side, as soon as the app see the status change and the new Url, a download button (pointing to the new url) appears

Everything is working, but if I try to download the file immediately... there is no file yet!!!

If I wait same time and retry the file is there.

I noted that the time I have to wait depend on the size of the zipfile.

The bucket.upload promise should resolve on the end of the upload, but apparently fires too early. Is there a way to know exactly when the file is ready? I may have to make same very big file, it's not a problem if the process takes several minutes, but I need to know when it's over.

* EDIT *

there was a unnecessary nesting in the code. While it was not the error (results are the same before and after refactoring) it was causing some confusion in the answers, so i edited it out.

Id' like to point out that i update the database only after getting the signed url, and i get that only after the upload (i could not otherwise), so to get any result at all the promise chain MUST work, and in fact it does. When on the client side the download button appears (happens when 'status' become 'fatto') it is already linked to the correct signed url, but if i press it too early the file is not there (Failed - No file). If i wait some second (the bigger the file the longer i have to wait) then the file is there.

(English is not my mother language, if i have been unclear ask and i will try to explain myself better)

like image 410
Stefano Marchesi Avatar asked Oct 27 '25 05:10

Stefano Marchesi


1 Answers

It looks like the problem could be that the braces are not aligned properly, causing a then statement to be embedded within another. Here is the code with the then statements separated:

[***CREATION OF ZIP FILE WORKING****]}).then(() => {
    zip.generateNodeStream({type: 'nodebuffer', streamFiles: true})
    .pipe(fs.createWriteStream(tempPath))
    .on('finish', function () {
        console.log('zip written.')
        return bucket.upload(tempPath, { 
            destination: destinazionePath
        })
    })
}).then(() => {
    const config = {
        action: 'read',
        expires: '03-09-2391'
    }
    return bucket.file(destinazionePath).getSignedUrl(config)
}).then(risultato => {
        const daSalvare = {
            signedUrl: risultato[0],
            status : 'fatto',
            dataInserimento : zipball.dataInserimento
    }
    return event.data.ref.set(daSalvare)
})
like image 179
Jen Person Avatar answered Oct 29 '25 21:10

Jen Person



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!