NServiceBus — ставить саги в очередь с одним и тем же ключом

Сценарий: я построил сагу с 10 шагами. Он обновляет различные системы, и вся сага может занять несколько минут.

Сага начинается с данных из другой системы, где пользователи вводят информацию о клиенте.

Я не могу видеть, когда пользователь заканчивает вводить данные в своей системе, но я читаю данные с изменениями из системы каждые x минут.

Моя проблема в том, что всякий раз, когда я начинаю сагу с данными о клиенте, мне нужно убедиться, что предыдущая сага о том же клиенте завершена. Если пользователь тратит 10 минут на ввод данных, система может запустить 5 потоков для одного и того же клиента, и потоки могут превзойти предыдущие потоки и исказить данные.

Кто-нибудь знает, как я могу это решить?

Заранее спасибо.

Оле


person Ole Gade    schedule 04.01.2016    source источник
comment
Не могли бы вы сделать свой уникальный атрибут идентификатором клиента? Если это так, вы можете позволить сообщению, которое запускает сагу, также сопоставляться и обрабатываться сагой. Таким образом, если сага с идентификатором клиента 1 запускается и поступает новое сообщение (обновление, полученное для клиента 1), это приводит к обработке той же саги. Если это не сработает, не могли бы вы предоставить короткие фрагменты кода о ваших сопоставлениях саги + сообщение инициализации   -  person janpieter_z    schedule 04.01.2016


Ответы (2)


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

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

Назовем это сообщение:

public class ClientTypedSomethingAboutCustomer 
{
    int CustomerId {get;set;}
    ...
}

Ваша сага будет настроена примерно так:

public class CustomerSaga : Saga<CustomerSagaData>, IAmStartedByMessages<ClientTypedSomethingAboutCustomer>
{
    public override void ConfigureHowToFindSaga()
    {
        ConfigureMapping<ClientTypedSomethingAboutCustomer>
            (message => message.CustomerId).ToSaga(saga => saga.CustomerId);
        ...
    }
    ...
}

Это приводит к инициализации саги и установке значения идентификатора клиента в реализации IContainSagaData для каждого отдельного полученного клиентского сообщения.

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

Что-то типа:

public class ClientTypedSomethingElseAboutCustomer 
{
    int CustomerId {get;set;}
    ...
}

Тогда ваша сага будет выглядеть так:

public class CustomerSaga : Saga<CustomerSagaData>, IAmStartedByMessages<ClientTypedSomethingAboutCustomer>
    ,IHandleMessages<ClientTypedSomethingElseAboutCustomer>
{
    public override void ConfigureHowToFindSaga()
    {
        ConfigureMapping<ClientTypedSomethingAboutCustomer>
            (message => message.CustomerId).ToSaga(saga => saga.CustomerId);

        ConfigureMapping<ClientTypedSomethingElseAboutCustomer>
            (message => message.CustomerId).ToSaga(saga => saga.CustomerId);
    }
    ...
}

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

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

person tom redfern    schedule 04.01.2016
comment
Вы также можете реализовать сложную логику поиска саги - person Dennis van der Stelt; 05.01.2016
comment
Как описано в документах: По сути, семантика IAmStartedByMessages такова: создать новый экземпляр, если существующий не может быть найден. docs.particular.net/nservicebus/sagas/#starting-a-saga< /а> - person Udi Dahan; 05.01.2016

И @janpieter_z, и @tom-redfern верны: убедитесь, что вы можете сопоставить сагу с каким-либо идентификатором клиента.

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

Кроме того, несколько сообщений могут быть установлены как «IAmStartedByMessages», если они не приходят в правильном порядке.

Наконец, кто отправляет сообщения вашей саге? Разве сага не должна отвечать за отправку запросов на сбор данных? Возможно, каждые 10 секунд через тайм-ауты или что-то в этом роде, пока ничего не будет получено в течение нескольких минут, или обработчик не ответит другим сообщением?

person Dennis van der Stelt    schedule 05.01.2016