运行一堆 Firebase 查询 60 秒后 Cloud Function for Firebase 超时 [英] Cloud Function for Firebase timeout after 60 seconds while running a bunch of Firebase queries

查看:15
本文介绍了运行一堆 Firebase 查询 60 秒后 Cloud Function for Firebase 超时的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将 Firebase 用于群组协作应用程序(如 Whatsapp),并且我正在使用云函数来确定哪些电话联系人也在使用我的应用程序(再次类似于 Whatsapp).Cloud Function 运行良好,直到我开始在 Functions Log 中看到以下日志以进行某些调用.

I am using Firebase for a group collaboration app (like Whatsapp) and I am using a Cloud Function to figure out which of the phone contacts are also using my app (again similar to Whatsapp). The Cloud Function ran fine till I started to see the following log in the Functions Log for some invocations.

函数执行耗时 60023 毫秒,完成状态为:'timeout'

我做了一些调试,发现对于这个特定的用户,他的手机通讯录上有很多联系人,因此很明显,找出哪些联系人正在使用该应用程序所需的工作也增加了,以至于花了60多秒.下面是云函数的代码

I did some debugging and found that for this particular user, he has a lot of contacts on his phone's contacts book and so obviously the work required to figure out which of those contacts are using the app also increased to a point that it took more than 60 secs. Below is the code for the Cloud Function

      // contactsData is an array of contacts on the user's phone
      // Each contact can contain one more phone numbers which are
      // present in the phoneNumbers array. So, essentially, we need
      // to query over all the phone numbers in the user's contact book
      contactsData.forEach((contact) => {
        contact.phoneNumbers.forEach((phoneNumber) => {
          // Find if user with this phoneNumber is using the app
          // Check against mobileNumber and mobileNumberWithCC
          promises.push(ref.child('users').orderByChild("mobileNumber").
            equalTo(phoneNumber.number).once("value").then(usersSnapshot => {
              // usersSnapshot should contain just one entry assuming
              // that the phoneNumber will be unique to the user
              if(!usersSnapshot.exists()) {
                return null
              }
              var user = null
              usersSnapshot.forEach(userSnapshot => {
                user = userSnapshot.val()
              })
              return {
                name: contact.name,
                mobileNumber: phoneNumber.number,
                id: user.id
              }
            }))
          promises.push(ref.child('users').orderByChild("mobileNumberWithCC").
            equalTo(phoneNumber.number).once("value").then(usersSnapshot => {
              // usersSnapshot should contain just one entry assuming
              // that the phoneNumber will be unique to the user
              if(!usersSnapshot.exists()) {
                return null
              }
              var user = null
              usersSnapshot.forEach(userSnapshot => {
                user = userSnapshot.val()
              })
              return {
                name: contact.name,
                mobileNumber: phoneNumber.number,
                id: user.id
              }
            }))
        });
      });
      return Promise.all(promises)
    }).then(allContacts => {
      // allContacts is an array of nulls and contacts using the app
      // Get rid of null and any duplicate entries in the returned array
      currentContacts = arrayCompact(allContacts)

      // Create contactsObj which will the user's contacts that are using the app
      currentContacts.forEach(contact => {
        contactsObj[contact.id] = contact
      })
      // Return the currently present contacts
      return ref.child('userInfos').child(uid).child('contacts').once('value')
    }).then((contactsSnapshot) => {
      if(contactsSnapshot.exists()) {
        contactsSnapshot.forEach((contactSnapshot) => {
          previousContacts.push(contactSnapshot.val())
        })
      }
      // Update the contacts on firease asap after reading the previous contacts
      ref.child('userInfos').child(uid).child('contacts').set(contactsObj)

      // Figure out the new, deleted and renamed contacts
      newContacts = arrayDifferenceWith(currentContacts, previousContacts, 
        (obj1, obj2) => (obj1.id === obj2.id))
      deletedContacts = arrayDifferenceWith(previousContacts, currentContacts,
        (obj1, obj2) => (obj1.id === obj2.id))
      renamedContacts = arrayIntersectionWith(currentContacts, previousContacts,
        (obj1, obj2) => (obj1.id === obj2.id && obj1.name !== obj2.name))
      // Create the deletedContactsObj to store on firebase
      deletedContacts.forEach((deletedContact) => {
        deletedContactsObj[deletedContact.id] = deletedContact
      })
      // Get the deleted contacts
      return ref.child('userInfos').child(uid).child('deletedContacts').once('value')
    }).then((deletedContactsSnapshot) => {
      if(deletedContactsSnapshot.exists()) {
        deletedContactsSnapshot.forEach((deletedContactSnapshot) => {
          previouslyDeletedContacts.push(deletedContactSnapshot.val())
        })
      }
      // Contacts that were previously deleted but now added again
      restoredContacts = arrayIntersectionWith(newContacts, previouslyDeletedContacts,
        (obj1, obj2) => (obj1.id === obj2.id))
      // Removed the restored contacts from the deletedContacts
      restoredContacts.forEach((restoredContact) => {
        deletedContactsObj[restoredContact.id] = null
      })
      // Update groups using any of the deleted, new or renamed contacts
      return ContactsHelper.processContactsData(uid, deletedContacts, newContacts, renamedContacts)
    }).then(() => {
      // Set after retrieving the previously deletedContacts
      return ref.child('userInfos').child(uid).child('deletedContacts').update(deletedContactsObj)
    })

以下是一些示例数据

// This is a sample contactsData
[
  {
    "phoneNumbers": [
      {
        "number": "12324312321",
        "label": "home"
      },
      {
        "number": "2322412132",
        "label": "work"
      }
    ],
    "givenName": "blah5",
    "familyName": "",
    "middleName": ""
  },
  {
    "phoneNumbers": [
      {
        "number": "1231221221",
        "label": "mobile"
      }
    ],
    "givenName": "blah3",
    "familyName": "blah4",
    "middleName": ""
  },
  {
    "phoneNumbers": [
      {
        "number": "1234567890",
        "label": "mobile"
      }
    ],
    "givenName": "blah1",
    "familyName": "blah2",
    "middleName": ""
  }
]



// This is how users are stored on Firebase. This could a lot of users
  "users": {
    "id1" : {
      "countryCode" : "91",
      "id" : "id1",
      "mobileNumber" : "1231211232",
      "mobileNumberWithCC" : "911231211232",
      "name" : "Varun"
    },
    "id2" : {
      "countryCode" : "1",
      "id" : "id2",
      "mobileNumber" : "2342112133",
      "mobileNumberWithCC" : "12342112133",
      "name" : "Ashish"
    },
    "id3" : {
      "countryCode" : "1",
      "id" : "id3",
      "mobileNumber" : "123213421",
      "mobileNumberWithCC" : "1123213421",
      "name" : "Pradeep Singh"
    }
  }

在这种特殊情况下,contactsData 包含 1046 条目,其中一些条目有两个 phoneNumbers.因此,假设我需要检查总共 1500 个电话号码.我正在创建查询以与数据库中用户的 mobileNumbermobileNumberWithCC 进行比较.因此,在 Promise 完成之前,该函数将进行总共 3000 个查询,我猜想完成所有这些查询需要 60 多秒,因此 Cloud Function 超时.

In this particular case, the contactsData contained 1046 entries and for some of those entries, there were two phoneNumbers. So, let's assume there were a total of 1500 phone numbers that I need to check. I am creating queries to compare against the mobileNumber and mobileNumberWithCC for the users in the database. So, there are a total of 3000 queries that the function will make before the promise finishes and I am guessing it is taking more than 60 seconds to finish up all those queries and hence the Cloud Function timed out.

我的几个问题是:

  1. 是否所有这些查询都需要超过 60 秒?鉴于它在 Firebase 基础架构中运行,我希望它能够更快地完成.
  2. 有没有办法增加函数的超时限制?我目前正在使用 Blaze 计划.

我还将感谢上述功能的任何替代实施建议,以缓解问题.谢谢!

I will also appreciate any alternate implementation suggestions for the above function in order alleviate the problem. Thanks!

推荐答案

如果无法避免查询这么多数据,可以在Cloud Console 用于您的项目,使用左侧的 Functions 产品.目前,您必须在每次新部署时重置超时.

If you cannot avoid querying so much data, you can change the timeout of a function in the Cloud Console for your project using the Functions product on the left. Currently, you will have to reset the timeout with each new deploy.

这篇关于运行一堆 Firebase 查询 60 秒后 Cloud Function for Firebase 超时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆