正确处理Akka异步延续中的异常

时间:2020-07-04 13:34:33

标签: akka.net

为了将minimumNumberOfTouches方法与async / task actor系统集成,我编写了以下方法

akkling

它基于有关如何将参与者与异步工作流集成的建议(此处为示例https://github.com/Horusiath/Akkling/blob/0b5b0ffa4cd516407706ed230f81915452cdb183/tests/Akkling.Tests/Actors.fs#L124

但是,如果异步方法抛出异常,那么该问题将由父主管不处理

我希望这段代码可以工作,但不能

    let actorOfTask (t: 'a -> Task<'b>) =
        (fun (ctx: Actor<_>) ->
        let rec loop() =
            actor {
                let! data = ctx.Receive()
                task {
                    try
                        let! t' = data |> t
                        return t'
                    with e ->
                        // TODO : Raise exception in order to supervisor can catch it
                        printf "Exception %O" e
                        return raise e
                }
                |> Async.AwaitTask
                |!> ctx.Sender()
                
            }
        loop())

尽管如果常规角色流中发生异常(未与async集成),则该主管会处理该异常。

任何建议如何解决?

谢谢

1 个答案:

答案 0 :(得分:1)

来自Akka.Net文档

https://getakka.net/articles/actors/receive-actor-api.html

WARNING
To complete the Task with an exception you need send a Failure message to the sender. This is not done automatically when an actor throws an exception while processing a message.

try
{
    var result = operation();
    Sender.Tell(result, Self);
}
catch (Exception e)
{
    Sender.Tell(new Failure { Exception = e }, Self);
}

所以演员应该这样实现

    let actorOfTask (sendTo: IActorRef<_>) (t: 'a -> Task<_>) =
        (fun (ctx: Actor<_>) ->
        let rec loop() =
            actor {
                let! data = ctx.Receive()
                task {
                    try
                        let! t' = data |> t
                        return t' :> obj
                    with e ->
                        return Akka.Actor.Failure(Exception = e) :> obj
                }
                |> Async.AwaitTask
                |!> (retype sendTo)
            }
        loop())