Slow firestore runTransaction call

Viewed 919

I'm currently writing an action that as a part of it, checks and increments an orderID value and responds with it in the conversation.

The code currently works, but part of the execution can take up to 10 seconds to execute, this can make action-on-google timeout the request and fail (along with being slow to reply to the user if at all). I'm using a runTransaction to make sure no other function instance on firebase can also be incrementing the ID. The code all functions and the value does increment, but the delay in the function responding means the intent it is responding to times out and gives the fall back response.

As you can see in my code below, I've added various console.log's to track down the delay, it is between before transaction and transaction started being output to the console that the 8-10 second delay happens. Can anyone say why?

const functions = require('firebase-functions');
const { dialogflow, Suggestions } = require('actions-on-google');
const admin = require('firebase-admin');

admin.initializeApp(functions.config().firebase);
const db = admin.firestore();
const settings = {timestampsInSnapshots: true};
db.settings(settings);

const app = dialogflow();

app.intent('order', (conv, {givenname: givenname}) => {
  console.log('starting function');
  return new Promise(function(resolvei, rejecti){
    if(givenname !== undefined){

        console.log('before db.collection');

        var idRef = db.collection('orderIDs').doc('opho9peCy54tjLR0YmVm');
        console.log('before transaction');
        var transaction = db.runTransaction(t => {
          console.log('transaction started');
          return t.get(idRef)
            .then(doc => {
              console.log('data gotten');
              var id = doc.data().ID + 1;
              if(id > 99){
                id = 1;
              }
              t.update(idRef, {ID: id});
              console.log('update made');
              return Promise.resolve(id);
            });
        }).then(result => {
          console.log(result);
          conv.close('Thank you, ' + givenname + '. Your order number is ' + result + '.');
          resolvei();
        }).catch(err => {
          console.log('Transaction failure:', err);
          rejecti();
        });
      }
    else{
      conv.close('Oops, something has gone wrong, try again.');
      resolve();
    }
  });
});

exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);
1 Answers

I've noticed that the first time you run your deployed function, runTransaction is slow and takes about 4.5 seconds to complete (even when you don't do any work in the transaction function). After that, runTransaction alone is much faster and takes < 200ms to complete. It's almost like the first time you run your newly deployed function, some additional cloud administration takes place for transactionable functions.

Related