2
votes

I trigger a Cloud function for Firebase at certain time. This function is fired properly.

When the function still have to execute, in my scenario it is possible that the data where the function will write is deleted main while.

So after the data is deleted, a new path with the .update() data is created.

How can I avoid that behavior? Is there some function to call to stop a certain function?

Here is a sample of my code. The situation right now is about two functions:

  1. Get a Facebook long lived token, wich fires when a user loged in at first, only then Firebse gives a Facebook accesstoken :( It looks like:
        exports.getFacebookLongLivedAccessToken = functions.database.ref('/users/{uid}/...').onWrite(event => {
      const accessToken = event.data;

      if(event.data.val() !== null) {
        const baseFBUrl = "https://graph.facebook.com/oauth/access_token?client_id=...&client_secret=...&grant_type=fb_exchange_token&fb_exchange_token="
        const fbAccessTokenUrl = baseFBUrl + accessToken.val();

        axios.get(fbAccessTokenUrl)
          .then(function (response) {
            return accessToken.ref.parent.update({accessTokenLongLived: response.data.access_token});
          })
          .catch(function (error) {
            console.error(error);
            return accessToken.ref.parent.update({accessTokenLongLived: error + ' - ' + fbAccessTokenUrl});
        });
      } else {
        return;
      }
    });
  1. The second function I mentioned about, is a user deletion, this looks like:

    exports.cleanupUserData = functions.auth.user().onDelete(event => {
        const uid = event.data.uid;
        console.error(uid)
        console.error(event.data)
        return admin.database().ref('/users/' + uid).remove();
        //return uid.ref.parent.remove(uid);
    });
    

I know; the change of logged in and afterwards a deletion is not zo big, but I tend to make more functions and get more used and so on. So for me it is important to understand and get this right.

1
I'm not sure I understand what your situation is here. Can you edit the question and include the code you're working with, and more details about what isn't working the way you expect.? - Doug Stevenson
@Doug, thank you for your reaction. I added my code. - Johan Walhout
I think the existing answer here is what you are looking for. You should be writing some kind of flag value back to the database that you check on the second invocation to know if the data at that location was already processed. Yes, it still costs 2 function invocations, and the team is looking into ways of improving this. - Doug Stevenson
@Doug, thanks. I mean this the way around: when I invoke the second function, I what to stop the first. Is there a queue to access? - Johan Walhout
I'm not sure what you're trying to accomplish here. Typically you would expect functions to run to completion every time, and they would not be interrupted by other functions. If you need to protect an area from multiple concurrent writes, you use a transaction to make sure they don't overwrite each other in a bad way. - Doug Stevenson

1 Answers

2
votes

I think what you may be hitting here is a race condition with your cloud function.

Basically in one place or another you need to do either

a) an atomic database write OR

b) check for an update flag and not perform the update.

Have a look at this link https://youtu.be/7E13ZBCyKT0?t=5m

5mins into the video Jen Person explains how to ensure the updates are not triggered to the database and stuck in an infinite loop.

If you share some of you're code we may all be able to help further.