Мы работаем над приложением, которое использует новые облачные функции Firebase. В настоящее время происходит то, что транзакция помещается в узел очереди. Затем функция удаляет этот узел и помещает его в правильный узел. Это было реализовано из-за возможности работы в автономном режиме.
Наша текущая проблема - это скорость функции. Сама функция занимает около 400 мс, так что ничего страшного. Но иногда функции занимают очень много времени (около 8 секунд), когда запись уже была добавлена в очередь.
Мы подозреваем, что серверу требуется время для загрузки, потому что, когда мы выполняем действие еще раз после первого. На это уходит меньше времени.
Есть ли способ решить эту проблему? Здесь я добавил код нашей функции. Мы подозреваем, что в этом нет ничего плохого, но добавили на всякий случай.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
const database = admin.database();
exports.insertTransaction = functions.database
.ref('/userPlacePromotionTransactionsQueue/{userKey}/{placeKey}/{promotionKey}/{transactionKey}')
.onWrite(event => {
if (event.data.val() == null) return null;
// get keys
const userKey = event.params.userKey;
const placeKey = event.params.placeKey;
const promotionKey = event.params.promotionKey;
const transactionKey = event.params.transactionKey;
// init update object
const data = {};
// get the transaction
const transaction = event.data.val();
// transfer transaction
saveTransaction(data, transaction, userKey, placeKey, promotionKey, transactionKey);
// remove from queue
data[`/userPlacePromotionTransactionsQueue/${userKey}/${placeKey}/${promotionKey}/${transactionKey}`] = null;
// fetch promotion
database.ref(`promotions/${promotionKey}`).once('value', (snapshot) => {
// Check if the promotion exists.
if (!snapshot.exists()) {
return null;
}
const promotion = snapshot.val();
// fetch the current stamp count
database.ref(`userPromotionStampCount/${userKey}/${promotionKey}`).once('value', (snapshot) => {
let currentStampCount = 0;
if (snapshot.exists()) currentStampCount = parseInt(snapshot.val());
data[`userPromotionStampCount/${userKey}/${promotionKey}`] = currentStampCount + transaction.amount;
// determines if there are new full cards
const currentFullcards = Math.floor(currentStampCount > 0 ? currentStampCount / promotion.stamps : 0);
const newStamps = currentStampCount + transaction.amount;
const newFullcards = Math.floor(newStamps / promotion.stamps);
if (newFullcards > currentFullcards) {
for (let i = 0; i < (newFullcards - currentFullcards); i++) {
const cardTransaction = {
action: "pending",
promotion_id: promotionKey,
user_id: userKey,
amount: 0,
type: "stamp",
date: transaction.date,
is_reversed: false
};
saveTransaction(data, cardTransaction, userKey, placeKey, promotionKey);
const completedPromotion = {
promotion_id: promotionKey,
user_id: userKey,
has_used: false,
date: admin.database.ServerValue.TIMESTAMP
};
const promotionPushKey = database
.ref()
.child(`userPlaceCompletedPromotions/${userKey}/${placeKey}`)
.push()
.key;
data[`userPlaceCompletedPromotions/${userKey}/${placeKey}/${promotionPushKey}`] = completedPromotion;
data[`userCompletedPromotions/${userKey}/${promotionPushKey}`] = completedPromotion;
}
}
return database.ref().update(data);
}, (error) => {
// Log to the console if an error happened.
console.log('The read failed: ' + error.code);
return null;
});
}, (error) => {
// Log to the console if an error happened.
console.log('The read failed: ' + error.code);
return null;
});
});
function saveTransaction(data, transaction, userKey, placeKey, promotionKey, transactionKey) {
if (!transactionKey) {
transactionKey = database.ref('transactions').push().key;
}
data[`transactions/${transactionKey}`] = transaction;
data[`placeTransactions/${placeKey}/${transactionKey}`] = transaction;
data[`userPlacePromotionTransactions/${userKey}/${placeKey}/${promotionKey}/${transactionKey}`] = transaction;
}