Несоответствие данных с MongoDB с использованием mongo-go-driver
FindOneAndReplace может заменить или не заменить документ в MongoDB. Ответ указывает, что операция прошла успешно, но, глядя на MongoDB, она вообще не обновлялась.
Версия сервера MongoDB - версия сервера MongoDB: 3.2.0. Эта ошибка воспроизводима в Ubuntu 16.04 и macOS Mojave. Целевым хостом является Azure CosmosDB.
Версия драйвера: mongo-go-driver@v0.0.17
func (s *Service) DeleteFileMetadata(ctx context.Context, req *pb.DocumentRequest) (*pb.DocumentResponse, error) {
log.Println("[INFO] Requesting DeleteFileMetadata service")
if ok := isStateAvailable(); !ok {
log.Printf("[ERROR] %s\n", errServiceUnavailable.Error())
return nil, status.Error(codes.Unavailable, errServiceUnavailable.Error())
}
if err := refreshMongoDBConnection(mongoDBWriter, &conf.DocumentDB.Writer); err != nil {
log.Printf("[ERROR] %s\n", err.Error())
return nil, status.Error(codes.Internal, err.Error())
}
if req == nil {
log.Printf("[ERROR] %s\n", errNilRequest.Error())
return nil, status.Error(codes.InvalidArgument, errNilRequest.Error())
}
fileMetadataParameters := req.GetFileMetadataParameters()
if fileMetadataParameters == nil || fileMetadataParameters.GetDuid() == "" {
log.Printf("[ERROR] %s\n", errInvalidFileMetadataParameters.Error())
return nil, status.Error(codes.InvalidArgument, errInvalidFileMetadataParameters.Error())
}
if err := ValidateDUID(fileMetadataParameters.GetDuid()); err != nil {
log.Printf("[ERROR] %s\n", err.Error())
return nil, status.Error(codes.InvalidArgument, err.Error())
}
if err := ValidateUUID(fileMetadataParameters.GetUuid()); err != nil {
log.Printf("[ERROR] %s\n", err.Error())
return nil, status.Error(codes.InvalidArgument, err.Error())
}
if err := ValidateFUID(fileMetadataParameters.GetFuid()); err != nil {
log.Printf("[ERROR] %s\n", err.Error())
return nil, status.Error(codes.InvalidArgument, err.Error())
}
if fileMetadataParameters.Media > pb.FileType_VIDEO {
return nil, status.Error(codes.InvalidArgument, errMediaType.Error())
}
log.Printf("[INFO] FileMetadataParameters: \n%v\n\n", pretty.Sprint(req.GetFileMetadataParameters()))
// Get the specific lock if it already exists, else make the lock
lock, _ := duidClientLocker.LoadOrStore(fileMetadataParameters.GetDuid(), &sync.RWMutex{})
// Lock
lock.(*sync.RWMutex).Lock()
// Unlock before the function exits
defer lock.(*sync.RWMutex).Unlock()
collection := mongoDBWriter.Database(conf.DocumentDB.Name).Collection(conf.DocumentDB.Collection)
// Find all MongoDB documents for the specific uuid
filter := bson.NewDocument(
bson.EC.String("duid", fileMetadataParameters.GetDuid()),
bson.EC.String("uuid", fileMetadataParameters.GetUuid()),
)
bsonResult := collection.FindOne(context.Background(), filter)
if bsonResult == nil {
log.Printf("[ERROR] FindOne: %s\n", errNoDocumentFound.Error())
return nil, status.Error(codes.InvalidArgument, errNoDocumentFound.Error())
}
documentToUpdate := &pb.Document{}
if err := bsonResult.Decode(documentToUpdate); err != nil {
log.Printf("[ERROR] Document not found, duid: %s - uuid: %s - err: %s\n",
fileMetadataParameters.GetDuid(), fileMetadataParameters.GetUuid(), err.Error())
return nil, status.Errorf(codes.InvalidArgument,
"Document not found, duid: %s - uuid: %s",
fileMetadataParameters.GetDuid(), fileMetadataParameters.GetUuid())
}
log.Printf("[INFO] Document to update: \n%s\n\n", pretty.Sprint(documentToUpdate))
switch fileMetadataParameters.Media {
case pb.FileType_FILE:
delete(documentToUpdate.GetFileUrlsMap(), fileMetadataParameters.GetFuid())
case pb.FileType_AUDIO:
delete(documentToUpdate.GetAudioUrlsMap(), fileMetadataParameters.GetFuid())
case pb.FileType_IMAGE:
delete(documentToUpdate.GetImageUrlsMap(), fileMetadataParameters.GetFuid())
case pb.FileType_VIDEO:
delete(documentToUpdate.GetVideoUrlsMap(), fileMetadataParameters.GetFuid())
default:
return nil, status.Error(codes.InvalidArgument, errMediaType.Error())
}
documentToUpdate.UpdateTimestamp = time.Now().UTC().Unix()
// option to return the the document after update
option := findopt.ReplaceOneBundle{}
result := collection.FindOneAndReplace(context.Background(), filter, documentToUpdate,
option.ReturnDocument(mongoopt.After))
// Extract the updated MongoDB document
if result == nil {
log.Printf("[ERROR] Extracting updated document, duid: %s - uuid: %s\n",
documentToUpdate.GetDuid(), documentToUpdate.GetUuid())
return nil, status.Errorf(codes.Internal,
"Extracting updated document duid: %s - uuid: %s",
documentToUpdate.GetDuid(), documentToUpdate.GetUuid())
}
document := &pb.Document{}
if err := result.Decode(document); err != nil {
log.Printf("[ERROR] %s\n", err.Error())
return nil, status.Errorf(codes.Internal, err.Error())
}
log.Printf("[INFO] Updated document: \n%s\n\n", pretty.Sprint(document))
log.Printf("[INFO] Success deleting file metadata in document, duid: %s - uuid: %s - fuid: %s\n",
document.GetDuid(), document.GetUuid(), fileMetadataParameters.GetFuid())
return &pb.DocumentResponse{
Status: &pb.DocumentResponse_Code{Code: uint32(codes.OK)},
Message: codes.OK.String(),
Data: document,
}, nil
}
Я ожидаю, что ответ отражает фактическое состояние данных на сервере MongoDB.
Допустим, я хочу удалить метаданные файла с fuid 05ce38e7-a29a-485f-bf20-eef3501867f0
Я получаю этот ответ, указывающий, что он был удален. Ответ был декодирован из result := collection.FindOneAndReplace(context.Background(), filter, documentToUpdate, option.ReturnDocument(mongoopt.After))
ImageUrlsMap: {217706a5-2f88-4eb2-8a93-c1426c5ac944: "https://hwscdevstorage.blob.core.windows.net/images/hulkgif.png",
4ff30392-8ec8-45a4-ba94-5e22c4a686df: "https://hwscdevstorage.blob.core.windows.net/images/Rotating_earth_(large).gif"},
AudioUrlsMap: {4ff30392-8ec8-45a4-ba94-5e22c4a686df: "https://hwscdevstorage.blob.core.windows.net/audios/Milad Hosseini - Deli Asheghetam [128].mp3",
8fe5fea7-f683-4198-8c94-f27601a5e2d0: "https://hwscdevstorage.blob.core.windows.net/audios/Seger_Conga_CaboMexico_Tag_Acousonde_20140313_112313_8000_3_BreedingMigrating.wav"},
VideoUrlsMap: {4ff30392-8ec8-45a4-ba94-5e22c4a686de: "https://hwscdevstorage.blob.core.windows.net/videos/videoplayback.wmv",
4ff30392-8ec8-45a4-ba94-5e22c4a686df: "https://hwscdevstorage.blob.core.windows.net/videos/videoplayback.mp4",
e525ca9c-9813-4286-abda-8bd0eb6e94b4: "https://hwscdevstorage.blob.core.windows.net/videos/pusheen.mp4"},
FileUrlsMap: {13df1afa-4eee-470e-b9e2-60b2a7584994: "https://hwscdevstorage.blob.core.windows.net/videos/videoplayback.wmv",
4ff30392-8ec8-45a4-ba94-5e22c4a686df: "https://hwscdevstorage.blob.core.windows.net/videos/videoplayback.mp4",
b7a16e10-ac03-468f-9b6d-dcc684d1147f: "https://hwscdevstorage.blob.core.windows.net/videos/pusheen.mp4"},
RecordTimestamp: 1514764800,
CreateTimestamp: 1539831496,
UpdateTimestamp: 1546183549,
IsPublic: true,
XXX_NoUnkeyedLiteral: {},
XXX_unrecognized: [],
XXX_sizecache: 0}
2018/12/30 07:25:49 [INFO] Success deleting file metadata in document, duid: 1ChHfmKs8GX7D1XVf61lwVdisWf - uuid: 0XXXXSNJG0MQJHBF4QX1EFD6Y3 - fuid: 05ce38e7-a29a-485f-bf20-eef3501867f0
Но если я захожу в Azure CosmosDB или на свой локальный сервер, он все еще там. Скриншот