node.js - 如果我故意让我的 Google Cloud Functions 出现多个错误,可以吗?
问题描述
我有这样的收藏和子收藏
users/{userID}/followers/{followerID}
每次在关注者子集合中删除关注者文档时,它都会触发下面的这个firestore触发器以减少numberOfFollowers
用户文档中的字段。当用户单击取消关注按钮时触发
exports.onDeleteFollower = functions
.firestore.document("users/{userID}/followers/{followerID}")
.onDelete((snapshot, context) => {
// normally triggered after a user push unfollow button
// then update the user document
const userID = context.params.userID;
const updatedData = {
numberOfFollowers: admin.firestore.FieldValue.increment(-1),
};
return db.doc(`users/${userID}`).update(updatedData);
});
现在我有这样的情况....
如果用户删除了他们的帐户,那么我将删除用户文档( users/{userID} ),但是如果我删除用户文档,它不会自动删除其子集合中的所有文档,对吧
所以在我删除用户文档后,我有另一个功能可以删除关注者子集合中的所有文档。
但问题是,onDeleteFollower
上面的triggers函数会被执行多次,并且会多次抛出错误,因为用户文档已被删除(上面的函数将用于更新已删除用户文档中的字段)
我将在函数模拟器中出现此错误
⚠ functions: Error: 5 NOT_FOUND: no entity to update: app: "myApp"
path <
Element {
type: "users"
name: "u1-HuWQ5hoCQnOAwh0zRQM0nOe96K03"
}
>
⚠ Your function was killed because it raised an unhandled error.
我实际上可以编写一个逻辑来检查用户文档是否仍然存在。如果存在则更新numberOfFollowers
字段
但是如果与用户单击取消关注按钮相比,删除用户文档是非常罕见的,我认为它不是很有效。
我有这样的计划,我会故意让错误发生。说一个用户有1000个follower,那么就会触发onDeleteFollower
上面的函数,那么我就会有1000个函数错误
我的问题是......
如果我在短时间内出现多个错误,可以吗?谷歌云功能会终止我的功能,还是......我不知道,我担心会发生我不知道的坏事
据我所知,云函数在被杀死后会自动再次运行该函数,我的函数会在出现这样的错误后再次准备好吗?
我不能让关注者直接从客户端应用程序更新组织者(用户)文档,因为它不安全。创建安全规则来促进这一点很复杂,而且似乎容易出错
解决方案
您是否考虑过users/{userID}/followers/{followerID}
创建“关注请求”系统而不是直接设置/删除?
"users/{userID}/followRequests/{requestID}": { // requestID would be auto-generated
user: "{followerID}",
follow: true // true = add user as follower, false = remove user as follower
}
然后,这允许您使用单个onCreate
触发器来更新您的关注者列表,从而无需您的当前onCreate
和onDelete
触发器users/{userID}/followers/{followerID}
。通过此功能,您可以对关注其他用户实施限制,例如关注限制或拒绝被阻止用户的关注请求。
export const newFollowRequest = functions.firestore
.document('users/{userId}/followRequests/{requestId}')
.onCreate(async (snap, context) => {
const request = snap.data();
const followingUserId = request.user;
const followedUserId = context.params.userId;
const db = admin.firestore();
const userDocRef = db.doc(`users/${followedUserId}`);
const followerDocRef = userDocRef.child(`followers/${followingUserId}`);
// /users/${followingUserId}/following/${followedUserId} ?
try {
if (request.follow) {
// Example restriction: Is the user who is attempting to follow
// blocked by followedUserId?
// await assertUserIDHasNotBlockedUserID(followedUserId, followingUserId);
// following
db.update(userDocRef, {
numberOfFollowers: admin.firestore.FieldValue.increment(1),
});
db.set(followerDocRef, {
/* ... */
});
} else {
// unfollowing
db.update(userDocRef, {
numberOfFollowers: admin.firestore.FieldValue.increment(-1),
});
db.delete(followerDocRef);
}
// delete this request when successful
db.delete(snap.ref);
// commit database changes
await db.commit();
console.log(`@${followingUserId} ${request.follow ? "followed" : "unfollowed"} @${followedUserId} successfully`);
} catch (err) {
// something went wrong, update this document with a failure reason (to show on the client);
let failureReason = undefined;
switch (err.message) {
case "other user is blocked":
failureReason = "You are blocked by @otherUser";
break;
case "user is blocked":
failureReason = "You have blocked @otherUser";
break;
}
return db.ref(snap.ref)
.update({
failureReason: failureReason || "Unknown server error";
})
.then(() => {
if (failureReason) {
console.log("REQUEST REJECTED: " + failureReason);
} else {
console.error("UNEXPECTED ERROR:", err)
}
},
(err) => {
console.error("UNEXPECTED FIRESTORE ERROR:", err);
});
}
});
推荐阅读
- c# - Telerik:.Net Core 的搜索栏组件未显示/未定位
- excel - 比较不是真的;但发送到 MsgBox 的值显示它应该是
- python - 无法从外部访问应用程序时处理 Microsoft 身份验证响应
- python - 向量化将 2D numpy 数组中的列转换为字节字符串
- python-3.x - 在简单的 SysTray PyQt5 应用程序中使用 While 循环
- html - 我正在尝试从原始 servlet 的 html 调用 servlet
- sql - 如何在 Access 中进行查询将 tempvar 识别为有效字段(参数)
- php - 如何从 Laravel 缓存中检索 Laravel 媒体库包的数据
- reactjs - Next.js 在所有 npm run 命令上都给出了缺失的脚本
- php - 将图像二进制数据转换为字母数字数据而不增加大小