RX реагирует на отдельные триггеры, но затем обрабатывает действие синхронно

1

Я пишу службу, которая в основном синхронизирует 2 источника данных. Требования состоят в том, что он периодически синхронизируется, но также возможно, чтобы администратор вручную запускал его для синхронизации в ответ на определенные случаи.

Мы используем сообщения MassTransit для IPC, поэтому веб-интерфейс отправит (скажем) TriggerSyncMessage через MassTransit, и служба увидит их.

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

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

Вот так:

var syncMessageObserver = Bus.Instance.AsObservable<TriggerSyncMessage>();

var subject = new Subject<string>();

syncMessageObserver.Subscribe(msg =>
{
    subject.OnNext("from message");
});

var timerSyncer = Observable.Timer(TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(60000)).Timestamp();

 timerSyncer.Subscribe(x =>
{
    subject.OnNext("from timer");
});

subject.AsObservable().Subscribe(msg =>
{
    // actual syncing stuff
});

У меня есть 2 вопроса по этому подходу: 1. Является ли это... правильным способом справиться с этим делом? Я не уверен, что вы хотите использовать предмет, чтобы связать наблюдаемые вместе, или если есть лучший способ.

  1. В качестве расширения этой проблемы я предпочел бы, чтобы следующий запуск метода синхронизации не запускался до тех пор, пока текущий не завершится. Также несколько вызовов для запуска синхронизации рассматриваются только один раз, когда пришло время для синхронизации. Поэтому, если у нас есть синхронизация, работающая с таймером, а нетерпеливый администратор нажимает кнопку "sync" 5 раз, когда операция таймера завершается, мы запускаем только один раз после этого.
    Любые предложения о том, как подойти к этому?
Теги:
masstransit
reactive-programming
system.reactive

1 ответ

3
Лучший ответ

Первая часть выглядит достаточно разрешимой. Просто игнорируйте значения и проецируйте свое сообщение. Здесь мы используем шаблон именования игнорируемого параметра '_' (который является допустимым именем переменной С#).

//TODO: Rename syncMessageObserver. It is not an Observer, it is an Observable.
Observable.Merge(
    syncMessageObserver.Select(_ => "from message"),
    Observable.Timer(TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(60000)).Timestamp().Select( _=> "from timer")
)
.Subscribe(msg =>
{
    // actual syncing stuff
});

Следующая проблема немного, но сложнее, но является общей. Часто требования предъявляются по разным причинам, но здесь вы все равно можете использовать одно и то же решение, и это будет оператор ObserveLatestOn. Это вышло из банков, где нам нужно показывать только самую последнюю цену. Если в то время, когда потребовалось сделать цену, многие другие цены были получены, мы должны показать только последнюю.

Вы можете увидеть, как это обсуждалось на форумах MSDN Rx, в блоге JamesWorld и видео на YouTube, в котором обсуждалось, как это происходило.

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

//TODO: Rename syncMessageObserver. It is not an Observer, it is an Observable.
Observable.Merge(
    syncMessageObserver.Select(_=>"from message"),
    Observable.Timer(TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(60000)).Timestamp().Select(_=>"from timer")
)
.ObserveLatestOn(Scheduler.CurrentThread)
.Subscribe(msg =>
{
    // actual syncing stuff
});

Для получения дополнительной информации о том, что такое Планировщик и как выбрать подходящий для вас сценарий, см. Здесь. Если тестирование важно для вас, то вам также нужно будет найти здесь контент о том, как быстро и детерминировать модульное тестирование запланированного/параллельного кода.

  • 0
    Работает отлично, спасибо. И спасибо также за introtorx.com Ли - я много на него ссылаюсь :)
  • 0
    Жаль, что я не мог бы поднять это больше, этот определенно входит в Evernote для справки. Кроме того, спасибо за книгу - интересно читать и как Spiffeah, много ссылок :-)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню