如何解决当用户连续执行多个graphql突变时防止竞争条件
我有一个异步GraphQL突变,它可以执行以下操作:
- 通过ID查找照片,并将其从db中删除(mongoDB,使用猫鼬)。
- 通过id查找用户,从用户照片列表中删除照片,然后保存用户。
因此,我有一个用于照片的数据库,一个用于用户的数据库。所有照片都是在photos-db中的单独文档,并且带照片ID的文件也会保存到user-db中。
问题是,如果我快速运行多次,它确实会从photo-db中删除照片,但是无法从user-db中删除photo-id。它会删除第一个photo-id,但不会删除后续的photo-id。
以下代码:
deletePhoto: async (_root: undefined,args: { id: string },context: UserInContext): Promise<Photo | null> => {
const currentUser = context.currentUser;
const id = args.id;
const isOwnPhoto = currentUser.photos.includes(id);
console.log('user',currentUser.id);
if (!currentUser || (!currentUser.isAdmin && !isOwnPhoto)) {
throw new AuthenticationError('Not authenticated');
}
const photo = await PhotoModel.findByIdAndDelete(args.id);
const user = await UserModel.findById(currentUser.id);
if (user) {
console.log('photo removed,id:',id);
user.photos = user.photos.filter(item => item != id);
try {
await user.save();
console.log('user saved');
} catch (error) {
console.log('error',error.message);
}
}
return photo;
}
尝试删除5张照片的输出:
user 5f058ca0bf08318028019059
user 5f058ca0bf08318028019059
user 5f058ca0bf08318028019059
user 5f058ca0bf08318028019059
user 5f058ca0bf08318028019059
photo removed,id: 5f3cf6fdbe09d26e70efcd95
photo removed,id: 5f3cf700be09d26e70efcd96
photo removed,id: 5f3cf705be09d26e70efcd97
photo removed,id: 5f3cf709be09d26e70efcd98
photo removed,id: 5f3cf70cbe09d26e70efcd99
user saved
error No matching document found for id "5f058ca0bf08318028019059" version 116 modifiedPaths "photos"
error No matching document found for id "5f058ca0bf08318028019059" version 116 modifiedPaths "photos"
error No matching document found for id "5f058ca0bf08318028019059" version 116 modifiedPaths "photos"
error No matching document found for id "5f058ca0bf08318028019059" version 116 modifiedPaths "photos"
下面的GraphQL模式:
type User {
username: String!
password: String!
email: String!
fullname: String!
isAdmin: Boolean!
photos: [Photo!]
id: ID!
}
type Photo {
mainUrl: String!
thumbUrl: String!
filename: String!
thumbFilename: String!
originalFilename: String!
name: String!
description: String
dateAdded: String
user: User!
id: ID!
}
type Mutation {
deletePhoto(id: ID!): Photo
}
因此,用户已更新一次,但随后的4次更新失败。如何防止这种情况发生?
解决方法
对我来说解决方案就是这个。我正在使用UserModel
运算符使用函数findByIdAndUpdate
更新$pullAll
,因为它可以确保在获取和保存对象之间不会对其进行修改。
deletePhoto: async (_root: undefined,args: { id: string },context: UserInContext): Promise<Photo | null> => {
const currentUser = context.currentUser;
const id = args.id;
const isOwnPhoto = currentUser.photos.includes(id);
if (!currentUser || (!currentUser.isAdmin && !isOwnPhoto)) {
throw new AuthenticationError('Not authenticated');
}
const photo = await PhotoModel.findByIdAndDelete(args.id);
await UserModel.findByIdAndUpdate({ _id: currentUser.id },{ $pullAll: { photos: [id] } });
return photo;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。