Мы работаем в приложении, которое включает чат в реальном времени, и мы используем Firebase и React-Native. Пользователь будет использовать свои номера телефонов для аутентификации, поэтому мы используем сервис аутентификации телефонных номеров.
Когда пользователи открывают приложение, мы извлекаем их контактную информацию и отправляем проанализированные / отфильтрованные телефонные номера в облачную функцию, эта функция должна обрабатывать все телефонные номера, отправленные в запросе, и помечать в качестве друзей тех пользователей, чей номер телефона соответствует один из контактных телефонов. Тот же процесс, что и WhatsApp.
Для этого мы попробовали два подхода:
После того, как функция получает запрос, она перебирает массив телефонных номеров контакта и запрашивает коллекцию users
в базе данных Cloud Firestore. Если запрос возвращает результат, функция извлекает эту информацию о пользователе и добавляет ее в подгруппу friends
запрашивающего пользователя.
/**
*
* @param {string} userId - Firebase id of user that made the request
* @param {Array<string>} contacts - Array of user's contacts phone numbers in E.164 format
* @returns {Array<object>} Array containing registered contacts data
*/
exports.searchFriends = (userId, contacts) => {
const registeredContacts = contacts.map(phoneNumber =>
db.collection(constants.usersPublicCollection)
.where('phoneNumber', '==', phoneNumber)
.get()
.then(snapshot => snapshot.docs.map((doc) => {
if (doc.id !== userId) {
return doc.data();
}
return null;
})));
return Promise.all(registeredContacts)
.then(friends => friends.filter(friend => friend !== null));
.then(friends => friends.reduce((prev, next) => [...prev, ...next], [])); // flatten array of arrays
};
Второй подход - тот же процесс, но он запрашивает службу аутентификации с помощью метода getUserByPhonenumber()
.
/**
*
* @param {string} userId - Firebase id of user that made the request
* @param {Array<string>} contacts - Array of user's contacts phone numbers in E.164 format
* @returns {Array<object>} Array containing registered contacts data
*/
exports.searchFriends = (userId, contacts) => {
const registeredContacts = contacts.map(phoneNumber =>
admin.auth().getUserByPhoneNumber(phoneNumber)
.then((user) => {
if (user.uid !== userId) {
return getUsersRef(user.uid).get();
}
return null;
})
.then((userProfile) => {
if (!userProfile) {
return null;
}
return userProfile.data();
})
.catch((err) => {
if (err.code !== 'auth/user-not-found') {
console.log(phoneNumber);
console.error(err);
}
return null;
}));
return Promise.all(registeredContacts)
.then(friends => friends.filter(friend => friend !== null));
};
Первый подход не сработал, потому что, когда мы проводили тестирование с пользователем с контактами 2k, мы обнаружили, что этот метод, возможно (и один раз) потреблял все ограничения на чтение в облачном хранилище файлов в день (50k).
Итак, мы попробовали со вторым подходом. Этот метод, кажется, работает, но после пары вызовов функции мы получаем ошибку, указывающую, что мы достигли предела для SocketConnectNonbillable
, мы попытались примерно через 2 часа, и он снова заработал, но после вызова произошел точно так же. Однако мы проверили страницу квот, и эта конкретная квота была хорошей, в то время мы выполняли только 30 подключений в день и только 0,3472 за 100 секунд.
Кто-нибудь знает решение этой проблемы?
Любая обратная связь приветствуется, если кто-либо обнаружит проблему с этими подходами или если у него есть идея решить проблему с контактами / друзьями (мы знаем, что они определенно не самые лучшие).
Спасибо!