我有以下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
挂钩。但是,如果我通过删除BuildTask
使Task.Run
方法同步,则会在异常时调用PreRestart
和Recover<T>
方法。
我真的很感激,如果有人可以指出我应该推荐的模式以及我出错的地方。
答案 0 :(得分:2)
最有可能的是,Akka.Persistence不是解决问题的好方法。
Akka.Persistence使用eventsourcing原则来存储演员的状态。在这种情况下,很少有关键点重要:
Persist
方法仅用于存储事件 - 它们描述事实,已发生的事情:因此,他们不能被拒绝,他们不会失败(你在Persist
回调中做的事情。)Persist
来重新创建自己的状态,直到最后一个已知的时间点。因此,Recover
方法应该只关注重放actor的状态(它可以在同一事件中多次调用)并且永远不会产生副作用(副作用的例子),这一点非常重要。正在发送电子邮件)。任何抛出的异常都意味着,演员状态不可挽回地被腐蚀,演员将被杀死。如果您想将消息重新发送给您的演员,您可以: