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时控制情况,而重试缓冲区具有不完整的批次,并且能够执行某些操作(发送错误电子邮件,将数据保存到本地文件系统,等)
答案 0 :(得分:3)
当保存到数据库失败并且需要重试时,它实际上不是流或错误的事件,而是对事件采取的操作。
我会更像这样构建你的代码:
IDisposable subscription =
_inputBuffer.AsObservable().
Buffer(TimeSpan.FromSeconds(10), 1000).
Subscribe(
batch => SqlSaveBatchWithRetryLogic(batch),
() => YourOnCompleteAction);
SqlSaveBatchWithRetryLogic()
YourOnCompleteAction()
SqlSaveBatchWithRetryLogic()
内部署订阅。Do
副作用。我会谨慎对待这种方法 - 您需要观察重试逻辑。你没有背压(放慢输入的方法)。因此,如果您有任何类型的退避/重试,您将面临备份和填充内存的风险。如果您开始一直看到批次数量,您可能遇到麻烦了!您可能希望实施一个计数器来监控未完成的项目。