Проблема параллелизма при вставке и обновлении элементов массива с помощью драйвера MongoDb - PullRequest
0 голосов
/ 27 июня 2019

У меня есть встроенный массив сообщений со следующей схемой

{ 
"_id" : NumberInt(5), 
"CurrentOwnerId" : NumberInt(9), 
"LastSent" : ISODate("2019-06-21T11:57:32.861+0000"), 
"Messages" : [
    {
        "_id" : BinData(3, "nuC1iYTKtkGzSuv7pVHsKg=="), 
        "MessageContent" : "Hi There", 
        "Status" : "Pending", 
        "DateSent" : ISODate("2019-06-21T11:57:32.861+0000"), 
        "Method" : "Slack",
        "TimeStamp" : "Its Time to party!"
    }
 ]
}

У меня есть требование, чтобы при вставке я проверял предыдущее сообщение в массиве, удалял отметку времени и добавлял новую к новому сообщению (для внешнего интерфейса). Нравится Ниже

{ 
"_id" : NumberInt(5), 
"CurrentOwnerId" : NumberInt(9), 
"LastSent" : ISODate("2019-06-21T11:57:32.861+0000"), 
"Messages" : [
    {
        "_id" : BinData(3, "nuC1iYTKtkGzSuv7pVHsKg=="), 
        "MessageContent" : "Hi There", 
        "Status" : "Pending", 
        "DateSent" : ISODate("2019-06-21T11:57:32.861+0000"), 
        "Method" : "Slack",
        "TimeStamp" : "" // Gone 
    }
      {
        "_id" : BinData(3, "nuC1iYTKtkGzSuv7pVHsKg=="), 
        "MessageContent" : "Hello Back", 
        "Status" : "Pending", 
        "DateSent" : ISODate("2019-06-21T11:58:32.861+0000"), 
        "Method" : "Slack",
        "TimeStamp" : "Its the new Time to party!" // New one 
    }
 ]
}

Вот так выглядит мой код

       var message = Message.CreateToContactMessage(messageType, content);
       var latestMessage = await _conversationRepository.FindLatestMessageByContactIdAsync(contactId);

        Message.DiscernTimeStampByRef(message, latestMessage);
        if (latestMessage == null)
        {
            //This means its the first message
            await _conversationRepository.InsertMessageAsync(contactId, message);
        }
        else
        {
            await _conversationRepository.UpdateMessage(contactId, latestMessage);
            await _conversationRepository.InsertMessageAsync(contactId, message);
        }

Это отлично работает во время отладки, но под нагрузкой мы начинаем видеть проблемы параллелизма, такие как временные метки, неправильно установленные из-за условий гонки между обновлением и вставкой.

Я попробовал множество вещей: вытащить, вставить один и тот же запрос (монго не нравится) или добавить, а затем удалить, используя сеанс и транзакции, но ни одна из них не смогла помочь. в массивы, но это, по-видимому, невозможно.

В настоящее время я не вижу способа обойти это без изменения моей схемы и помещения моих сообщений в отдельную коллекцию, где я могу их затем сохранить.

Мне как-то нужно сделать это последовательно, чтобы обеспечить поддержание правильного порядка.

Будем благодарны за любые примеры или материалы для чтения.

...