如何重试热观察?

时间:2014-04-28 20:13:35

标签: system.reactive

Rx具有很棒的功能Observable.Buffer。但在现实生活中存在问题。

场景:应用程序将事件流发送到数据库。逐个插入事件是昂贵的,因此我们需要批量处理它。我想为此使用Observable.Buffer。但是插入数据库的失败概率很小(死锁,超时,停机等)。

我可以在批处理函数本身中添加一些重试逻辑,但它会违反Rx的可编程性思想。 Observable.Retry不会削减它,因为它将重新订阅" hot"来源,这意味着失败的批次将丢失。

是否有功能,我可以编写以达到预期效果,或者我是否需要实现自己的扩展?我想要这样的东西:

_inputBuffer = new BufferBlock<int>();
_inputBuffer.AsObservable().
    Buffer(TimeSpan.FromSeconds(10), 1000).
    Do(batch => SqlSaveBatch(batch)).
    {Retry???}.
    Subscribe()

为了使其完美,我希望能够在调用OnComplete时控制情况,而重试缓冲区具有不完整的批次,并且能够执行某些操作(发送错误电子邮件,将数据保存到本地文件系统,等)

1 个答案:

答案 0 :(得分:3)

当保存到数据库失败并且需要重试时,它实际上不是流或错误的事件,而是对事件采取的操作。

我会更像这样构建你的代码:

IDisposable subscription =
    _inputBuffer.AsObservable().
    Buffer(TimeSpan.FromSeconds(10), 1000).
    Subscribe(
        batch => SqlSaveBatchWithRetryLogic(batch),
        () => YourOnCompleteAction);
  • 您可以在SqlSaveBatchWithRetryLogic()
  • 中提供重试逻辑
  • 处理YourOnCompleteAction()
  • 中的事件的OnComplete
  • 如果您未能保存批次,您可以选择从SqlSaveBatchWithRetryLogic()内部署订阅。
  • 这也会消除Do副作用。

我会谨慎对待这种方法 - 您需要观察重试逻辑。你没有背压(放慢输入的方法)。因此,如果您有任何类型的退避/重试,您将面临备份和填充内存的风险。如果您开始一直看到批次数量,您可能遇到麻烦了!您可能希望实施一个计数器来监控未完成的项目。