我有一个图书馆提供的IObservable
,该图书馆会监听来自外部服务的事件:
let startObservable () : IObservable<'a> = failwith "Given"
对于每个收到的事件,我要执行一个返回Async
的操作:
let action (item: 'a) : Async<unit> = failwith "Given"
我正试图以以下方式实现处理器
let processor () : Async<unit> =
startObservable()
|> Observable.mapAsync action
|> Async.AwaitObservable
我已经组成mapAsync
和AwaitObservable
:理想情况下,它们将由某个库提供,到目前为止我找不到。
额外要求:
动作应按顺序执行,以便在处理上一个事件时缓冲后续事件。
如果某个动作引发错误,我希望处理器完成。否则,它将永远无法完成。
通过Async.Start
传递的取消令牌。
关于我应该使用的库的任何提示吗?
答案 0 :(得分:5)
由于您要将基于推的模型(IObservable<>
)转换为基于拉的模型(Async<>
),因此需要排队以缓冲来自可观察的数据。如果队列是受大小限制的,则为-tbh。应该是为了确保整个管道安全,以免使内存不溢出-然后还需要一种用于缓冲区溢出的策略。
MailboxProcessor<>
和自定义可观察的对象,该方法会将数据发布到其中。由于MP是F#actor的本机实现,因此它能够使用队列进行有序处理,以缓冲峰值。另一种选择是使用FSharp.Control.AsyncSeq
(特别是AsyncSeq.ofObservableBuffered函数),它将可观察到的基于拉的异步枚举-从第一点开始,它使用邮箱处理器:
startObservable()
|> AsyncSeq.ofObservableBuffered
|> AsyncSeq.iterAsync action
答案 1 :(得分:1)
Hopac可以轻松与IObservables
互操作
您可以使用Jobs
Async
转换为Job.toAsync
open System
open Hopac
let startObservable () : IObservable<'a> = failwith "Given"
let action (item: 'a) : Job<unit> = failwith "Given"
let processor () : Job<unit> =
startObservable()
|> Stream.ofObservable
|> Stream.mapJob action
|> Stream.iter