Ошибка времени ожидания push-уведомлений Firestore Уведомление не всегда отправляется
Я вызываю функцию из своего приложения, которая отправляет уведомление определенному пользователю в приложении. В большинстве случаев уведомление отправляется успешно, но в большинстве случаев оно не отправляется. Когда он не приходит, я проверяю журналы, чтобы увидеть
Выполнение функции заняло 60003 мс, завершено со статусом «тайм-аут».
Я попытался поиграть с моими обещаниями / async await, но мне не повезло, поскольку я подозреваю, что в этом и заключается проблема.
Вот как сейчас выглядит мой облачный код
exports.sendNotification = functions.https.onRequest(async (request, response) => {
if (request.method !== "POST") {
response.status(400).send("Send it using post request");
return;
}
var toUid = request.body.toUid
var fcm = request.body.fcm
var fromUid = request.body.fromUid
var type = request.body.type
var fromName = request.body.fromName
var messageText = request.body.message
if (toUid === "" || fromUid === "" || fcm === "") {
response.status(400).send("Parameter is missing!");
return;
}
// common data for both platforms
const notification = {
title: fromName,
body: messageText,
}
const fcmToken = fcm
// ios specific headers
const apns = {
headers: {
"apns-collapse-id": 'toUid'
},
payload: {
aps: {
sound: 'default'
},
"data": {
"fromUid": fromUid,
"type": type
}
}
}
// final message
const message = {
token: fcmToken,
notification: notification,
apns: apns,
}
// send message
try {
return await admin.messaging().send(message);
response.status(200).send("Done");
} catch(e) {
console.log('Error sending message:', e);
}
});
Я вызываю функцию из приложения следующим образом
AF.request("https://myproject.net/sendNotification", method: .post, parameters: parameters, encoding: JSONEncoding.default)
.responseString { response in
print(response)
DispatchQueue.main.async {
completion("done")
}
}
Я видел другие вопросы о stackoverflow с похожими вопросами, где предлагалось использовать .post и JSONEncoding.default, и это то, что у меня есть сейчас.
2 ответа
Из https://firebase.google.com/docs/functions/http-events#terminate_http_functions :
В вашем блоке catch нет вызова
.send()
или любой эквивалент, поэтому по ссылке выше:
Всегда завершайте функцию HTTP с помощью send(), redirect() или end(). В противном случае ваша функция может продолжать работать и быть принудительно завершена системой. См. также Синхронизация, асинхронность и обещания.
Также лучше обернуть весь код в
onRequest
обратный вызов в try/catch.
Вот код с предлагаемыми исправлениями:
exports.sendNotification = functions.https.onRequest(async (request, response) => {
try {
if (request.method !== "POST") {
response.status(400).send("Send it using post request");
return;
}
var toUid = request.body.toUid
var fcm = request.body.fcm
var fromUid = request.body.fromUid
var type = request.body.type
var fromName = request.body.fromName
var messageText = request.body.message
if (toUid === "" || fromUid === "" || fcm === "") {
response.status(400).send("Parameter is missing!");
return;
}
// common data for both platforms
const notification = {
title: fromName,
body: messageText,
}
const fcmToken = fcm
// ios specific headers
const apns = {
headers: {
"apns-collapse-id": 'toUid'
},
payload: {
aps: {
sound: 'default'
},
"data": {
"fromUid": fromUid,
"type": type
}
}
}
// final message
const message = {
token: fcmToken,
notification: notification,
apns: apns,
}
// send message
await admin.messaging().send(message); // do not return here
response.status(200).send("Done");
} catch (e) {
response.status(500).send(e) // note the .send() wich terminates the request
}
});
Я ни в коем случае не эксперт по узлам, но некоторое время играл с Firebase Messaging и придумал работающее асинхронное решение для отправки уведомления на основе создания данных в базе данных реального времени. Единственное другое отличие, помимо триггера, которое я действительно вижу, это то, что я еще не отправляю специальный заголовок APNS ...
Я также вспоминаю, что у меня периодически возникала проблема с тайм-аутом, когда я пытался использовать асинхронный
exports.onMessageCreate = functions.database
.ref('/users/{userId}/notifications/unread/{notificationId}')
.onCreate(async (snapshot, context) => {
const message = snapshot.val()
const category = message.category
const title = category + ": " + message.title
const text = message.text
const forUserId = message.forUserId
const date = message.date
const token = await getUserToken(forUserId)
if (token == null) {
throw new functions.https.HttpsError('unavailable', 'The token is nil, unable to send message')
}
const notification = {
notification: {
title: title,
body: text
},
data: {
category: category,
title: message.title,
text: text,
forUserId: forUserId,
date: date.toString()
},
token: token
}
return admin.messaging().send(notification)
.then((response) => {
console.log('Successfully sent notification:', response)
})
.catch((error) => {
console.log('Error sending notification:', error)
})
})