我有一个谷歌云功能,可以向 firebase 主题发送通知。
该功能一直工作正常,直到突然,它开始同时发送多个通知 2 或 3。联系 Firebase 支持团队后,他们告诉我我应该使函数幂等,但我不知道如何,因为它是一个可调用函数。
更多细节,这是一个参考问题,包含有关该案例的更多详细信息。
下面是该函数的代码。
这是 admin sdk 中的一个错误,他们在上一个版本中解决了它。
UPDATE
该函数已经是幂等的因为它是一个事件驱动函数
上面的链接包含函数 log as prof 它只运行一次。
经过 2 个月的往返后,它出现了firebase admin sdk 的问题功能代码getMessaging().sendToTopic()
重试 4 次,原始请求重试 5 次,然后抛出错误并终止函数。因此,重复通知的原因是管理 SDK 有时由于某种原因无法到达 FCM 服务器。它尝试向所有订阅者发送通知,但在中途或发送所有通知之前,它会收到错误,因此它会从一开始,一些用户收到一个通知,一些用户收到 2、3、4 个通知。
现在的问题是如何防止这些默认重试,或者如何使重试从出现错误的地方继续。可能我会问一个单独的问题。
现在我做了一个简单的解决方案,防止来自接收者(移动客户端)的重复通知。如果一分钟内收到多个具有相同内容的通知,则仅显示一个。
const functions = require("firebase-functions");
// The Firebase Admin SDK to access Firestore.
const admin = require("firebase-admin");
const {getMessaging} = require("firebase-admin/messaging");
const serviceAccount = require("./serviceAccountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://mylinktodatabase.firebaseio.com",
});
exports.callNotification = functions.https.onCall( (data) => {
// Grab the text parameter.
const indicator = data.indicator;
const mTitle = data.title;
const mBody = data.body;
// topic to send to
const topic = "mytopic";
const options = {
"priority": "high",
"timeToLive": 3600,
};
let message;
if (indicator != null ) {
message = {
data: {
ind: indicator,
},
};
} else {
message = {
data: {
title: mTitle,
body: mBody,
},
};
}
// Send a message to devices subscribed to the provided topic.
return getMessaging().sendToTopic(topic, message, options)
.then(() => {
if (indicator != null ) {
console.log("Successfully sent message");
return {
result: "Successfully sent message", status: 200};
} else {
console.log("Successfully sent custom");
return {
result: "Successfully sent custom", status: 200};
}
})
.catch((error) => {
if (indicator != null ) {
console.log("Error sending message:", error);
return {result: `Error sending message: ${error}`, status: 500};
} else {
console.log("Error sending custom:", error);
return {result: `Error sending custom: ${error}`, status: 500};
}
});
});