Daniel Watrous
Daniel Watrous

Reputation: 3861

Firebase cloud-function multiple executions

I have a firebase (Google) cloud-function as follows

// Initialize the Auth0 client
var AuthenticationClient = require('auth0').AuthenticationClient;
var auth0 = new AuthenticationClient({
    domain:       'familybank.auth0.com',
    clientID:     'REDACTED'
});

function getAccountBalance(app) {
    console.log('accessToken: ' + app.getUser().accessToken);
    auth0.getProfile(app.getUser().accessToken, function (err, userInfo) {
        if (err) {
            console.error('Error getting userProfile from Auth0: ' + err);
        }
        console.log('getAccountBalance userInfo:' + userInfo)

        let accountowner = app.getArgument(PARAM_ACCOUNT_OWNER);

        // query firestore based on user
        var transactions = db.collection('bank').doc(userInfo.email)
                          .db.collection('accounts').doc(accountowner)
                          .collection('transactions');
        var accountbalance = transactions.get()
            .then( snapshot => {
                var workingbalance = 0
                snapshot.forEach(doc => {
                    workingbalance = workingbalance + doc.data().amount;
                });

                app.tell(accountowner + " has a balance of $" + workingbalance)
            })
            .catch(err => {
                console.log('Error getting transactions', err);
                app.tell('I was unable to retrieve your balance at this time.')
            });
    });
}
actionMap.set(INTENT_ACCOUNT_BALANCE, getAccountBalance);
app.handleRequest(actionMap);

When this executes, I see the following logs

enter image description here

Notice that parts of the function are being executed multiple times, and the second execution is failing. If I close out the auth0.getProfile call after logging userInfo, then the function works, but obviously doesn't have userInfo.

Any idea why parts of this function are executing multiple times and why some calls would fail?

Upvotes: 2

Views: 980

Answers (1)

Prisoner
Prisoner

Reputation: 50701

The userInfo is undefined at point (2) because there has been an error (reported on the line right beneath it, which was the previous logged message). Your error block does not leave the function, so it continues to run with an invalid userInfo object.

But that doesn't explain why the callback is getting called twice - once with a valid userInfo and once with an err. The documentation (although not the example) for AuthenticationClient.getProfile() indicates that it returns a Promise (or undefined - although it doesn't say why it might return undefined), so I am wondering if this ends up calling the callback twice.

Since it returns a promise, you can omit the callback function and just handle it with something like this:

function getAccountBalance(app) {
    let accountowner = app.getArgument(PARAM_ACCOUNT_OWNER);
    console.log('accessToken: ' + app.getUser().accessToken);
    var accessToken = app.getUser().accessToken;
    auth0.getProfile( accessToken )

      .then( userInfo => {
        console.log('getAccountBalance userInfo:' + userInfo)

        // query firestore based on user
        var transactions = db.collection('bank').doc(userInfo.email)
                          .db.collection('accounts').doc(accountowner)
                          .collection('transactions');
        return transactions.get();
      })

      .then( snapshot => {
        var workingbalance = 0
        snapshot.forEach(doc => {
          workingbalance = workingbalance + doc.data().amount;
        });

        app.tell(accountowner + " has a balance of $" + workingbalance)
      })

      .catch( err => {
        console.error('Error:', err );
        app.tell('I was unable to retrieve your balance at this time.')
      })

    });
}

Upvotes: 1

Related Questions