【发布时间】:2017-12-03 10:37:56
【问题描述】:
我有以下 Actor 我正在尝试重新启动并将失败的消息重新发送回 Actor:
public class BuildActor : ReceivePersistentActor
{
public override string PersistenceId => "asdad3333";
private readonly IActorRef _nextActorRef;
public BuildActor(IActorRef nextActorRef)
{
_nextActorRef = nextActorRef;
Command<Workload>(x => Build(x));
RecoverAny(workload =>
{
Console.WriteLine("Recovering");
});
}
public void Build(Workload Workload)
{
var context = Context;
var self = Self;
Persist(Workload, async x =>
{
//after this line executes
//application goes into break mode
//does not execute PreStart or Recover
var workload = await BuildTask(Workload);
_nextActorRef.Tell(workload);
context.Stop(self);
});
}
private Task<Workload> BuildTask(Workload Workload)
{
//works as expected if method made synchronous
return Task.Run(() =>
{
//simulate exception
if (Workload.ShowException)
{
throw new Exception();
}
return Workload;
});
}
protected override void PreRestart(Exception reason, object message)
{
if (message is Workload workload)
{
Console.WriteLine("Prestart");
workload.ShowException = false;
Self.Tell(message);
}
}
}
在Persist 的成功处理程序中,我试图模拟抛出的异常,但在出现异常时,应用程序会进入中断模式,并且不会调用PreRestart 挂钩。但是,如果我通过删除 Task.Run 使 BuildTask 方法同步,那么在异常时会调用 PreRestart 和 Recover<T> 方法。
如果有人能指出我应该推荐什么模式以及我哪里出错了,我将不胜感激。
【问题讨论】:
-
你确定这和持久性有关吗?我似乎记得异步方法中的一个异常导致我的整个演员系统终止并且我没有使用持久性。我最终进行了编码,以便异步调用捕获所有异常并使用一些错误消息执行 Tell。 (不适合“让它失败”的理念,但这是一种权宜之计。)