0

I want to deleted a child after a certain time. I know that you need Firebase function to achief this. This is what I got so far:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

exports.removeOldMessages = functions.https.onRequest((req, res) => {
    const timeNow = Date.now();
    const Ref = admin.database().ref('/Feed');
    Ref.once('value', (snapshot) => {
        snapshot.forEach((child) => {
            if (1000*(Number(child.val()['timestamp']) + Number(child.val()['duration'])) >= timeNow) {
               child.ref.set(null);
            }
        });
    });
    return res.status(200).end();
});

I want to deleted the child when the duration is over (the duration is in seconds). This is my structure: Firebase Structure

Thanks!

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807

1 Answers1

0

You're sending a response to the caller at the end of the function, which will be executed before the data from the database is returned. And Cloud Functions will stop executing your code straight after that res.status(200).end(), so the database cleanup never happens.

To prevent this, only send a response to the caller after all data has been deleted from the database:

exports.removeOldMessages = functions.https.onRequest((req, res) => {
    const timeNow = Date.now();
    const Ref = admin.database().ref('/Feed');
    return Ref.once('value', (snapshot) => {
        let updates = [];
        snapshot.forEach((child) => {
            if (1000*(child.val().timestamp + child.val().duration) >= timeNow) {
               updates[child.key] = null;
            }
        });
        return Ref.update(updates).then(() => {
            return res.status(200).end();
        });
    });
});

I highly recommend storing an additional property in your child nodes though, with the precalculated value of timestamp + duration. By having such a property, you can run a query on the nodes that have expired, instead of having to read all child nodes and then filtering in code.

For an example of this, see my answer to Delete firebase data older than 2 hours, and the Cloud Functions example that was based on that.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thanks for your response. When I try to deploy this code I'll get 2 errors: `error Expected catch() or return promise/catch-or-return` and `error Each then() should return a value or throw promise/always-return`. – Poephoofd Lol Feb 15 '20 at 19:42
  • Hmm... I thought HTTPS functions didn't need to return a promise. But anyway: I updated the answer to return the bubbled up promises. – Frank van Puffelen Feb 15 '20 at 19:43
  • That's just a lint warning. It's more readable to return null inside `then` and `catch` callback to explicitly say the promise chain yields nothing, instead of returning some unknown value (in this case, undefined). There is nothing about HTTP functions that require a promise to be returned. – Doug Stevenson Feb 15 '20 at 19:56
  • After deploying the function, it will remove all of the "Feed" childs and not only the childs that need to be deleted. – Poephoofd Lol Feb 15 '20 at 19:58
  • That logic is unchanged from what you initially posted. You might want to run the same query in a regular Node.js script or a Web client, and see what's going wrong in your `if` condition. – Frank van Puffelen Feb 15 '20 at 21:39