NServiceBus Saga несколько раз обрабатывает тип сообщения, что дает исключение параллелизма

У нас есть реализация NServiceBus, которая обрабатывает несколько типов сообщений:

public class StateCoordinator : Saga<MessageData>, 
                                IAmStartedByMessages<CreateMessage>, 
                                IAmStartedByMessages<ConfirmMessage>

MessageData выглядит примерно так:

public class FlowData : IContainSagaData
{
    [Unique]
    public Guid MappingId { get; set; }

    public Guid Id { get; set; }

    public string OriginalMessageId { get; set; }

    public string Originator { get; set; }

    public List<MessagePart> MessageParts { get; set; }
}

public MessagePart
{
    public int Id { get; set; }

    public string Status { get; set; }
}

CreateMessage имеет MessagePart, который добавляется к MessageParts в его обработчике. ConfirmMessage обновляет статус конкретной MessagePart.

Это сценарий:

1) Получено первое сообщение CreateMessage. Это создает Saga в Raven и добавляет MessagePart (со статусом «1») в MessageParts.

2) Получено первое сообщение ConfirmMessage. Это обновляет статус первого добавленного MessagePart в саге на «1 2». Это видно в браузере при переходе к документу в RavenDB.

3) Получено второе сообщение CreateMessage. Это добавляет второй MessagePart к MessageParts. При просмотре данных статус первого MessagePart по-прежнему равен «1», а не «1 2», и это создает исключение параллелизма (ActualETag не равен ExpectedETag):

A first chance exception of type 'Raven.Abstractions.Exceptions.ConcurrencyException' occurred in Raven.Client.Lightweight

Additional information: PUT attempted on document 'flow/79a7ee20-f090-4648-9b62-a3da00d87c93' using a non current etag

Похоже, что данные Saga кэшируются для каждого типа сообщения. Это так? Есть ли решение?

ЗАМЕТКА:

Мы используем несколько IAmStartedByMessages, но когда ConfirmMessage находится перед CreateMessage, это сообщение добавляется в очередь до тех пор, пока не будет обработано CreateMessage.


person EagleBP    schedule 05.11.2014    source источник


Ответы (1)


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

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

Вывод: не проблема, а просто лишняя строчка в лог-файле.

person EagleBP    schedule 05.11.2014
comment
Верно. Пока у вас есть более одного рабочего потока, существует вероятность того, что два или более потока попытаются работать над одной и той же сагой одновременно. Только один преуспевает, а остальные повторяются. Подобные периодические сбои являются одной из основных причин встроенной поддержки повторных попыток в NServicebus. - person janovesk; 06.11.2014