Laszlo
Laszlo

Reputation: 63

Cloud Functions for Firebase Could not handle the request after a successful request

TLDR: After writing a JSON (successfully) to my Firestore, the next request will give me Internal Server Error (500). I have a suspicion that the problem is that inserting is not yet complete.

So basically, I have this code:

const jsonToDb = express();
exports.jsondb = functions.region('europe-west1').https.onRequest(jsonToDb);
jsonToDb.post('', (req, res) => {
    let doc;
    try {
        doc = JSON.parse(req.body);
    } catch(error) {
        res.status(400).send(error.toString()).end();
        return;
    }
    myDbFuncs.saveMyDoc(doc);
    res.status(201).send("OK").end();
}

The database functions are in another JS file.

module.exports.saveMyDoc = function (myDoc) {
    let newDoc = db.collection('insertedDocs').doc(new Date().toISOString());
    newDoc.set(myDoc).then().catch();
    return;
};

So I have several theories, maybe one of them is not wrong, but please help me with this. (Also if I made some mistakes in this little snippet, just tell me.)

Reproduction:

  1. I send the first request => everything is OK, Json in the database.

  2. I send a second request after the first request give me OK status => it does not do anything for a few secs, then 500: Internal Server Error.

Logs: Function execution took 4345 ms, finished with status: 'connection error'.

I just don't understand. Let's imagine I'm using this as an API, several requests simultaneously. Can't it handle? (I suppose it can handle, just I do something stupid.) Deliberately, I'm sending the second request after the first has finished and this occurs. Should I make the saveMyDoc async?

Upvotes: 0

Views: 4128

Answers (1)

Doug Stevenson
Doug Stevenson

Reputation: 317342

saveMyDoc isn't returning a promise that resolves when all the async work is complete. If you lose track of a promise, Cloud Functions will shut down the work and clean up before the work is complete, making it look like it simply doesn't work. You should only send a response from an HTTP type function after all the work is fully complete.

Minimally, it should look more like this:

module.exports.saveMyDoc = function (myDoc) {
    let newDoc = db.collection('insertedDocs').doc(new Date().toISOString());
    return newDoc.set(myDoc);
};

Then you would use the promise in your main function:

myDbFuncs.saveMyDoc(doc).then(() => {
    res.status(201).send("OK").end();
}

See how the response is only sent after the data is saved.

Read more about async programming in Cloud Functions in the documentation. Also watch this video series that talks about working with promises in Cloud Functions.

Upvotes: 3

Related Questions