我们正在将akka.net演员添加到遗留系统的一部分。
基本思想是来自外部系统的消息,它被传递给由akka.net actor管理的逻辑,然后与遗留组件进行通信,这些组件执行将数据保存到数据库等事情。
遗留代码依赖于在CallContext中设置userId的事实,然后它可以在进行数据库写入之前检索(存储诸如" CreatedBy"" LastModifiedBy" )。很明显,一旦消息通过actor系统传递,CallContext将不可用。
这似乎是一个常见的问题/要求,但我一直无法通过谷歌或通过akka / akka.net讨论组找到这个问题。
在akka.net中是否存在上下文包装器/信封的概念,或者是我唯一的选择,使上下文信息的传递成为消息的明确部分?
答案 0 :(得分:4)
由于您的消息可能跨越actor系统边界,因此这里的最佳选择似乎是将CallContext和消息包装起来,并在消息到达时加载到actor的某个字段。以下是使用AroundReceive
方法的示例代码:
public struct Wrapper {
public readonly CallContext CallContext;
public readonly object Message;
...
}
public abstract class ContextualActor : ReceiveActor {
protected CallContext CallContext;
protected override bool AroundReceive(Receive receive, object message) {
if (message is Wrapper) {
var wrapped = (Wrapper)message;
CallContext = wrapped.CallContext;
return base.AroundReceive(receive, wrapped.Message);
}
else return base.AroundReceive(receive, message);
}
public void Send(IActorRef aref, object message) =>
aref.Tell(new Wrapper(CallContext, message))
}
这样,当消息命中actor的receive方法时,将加载调用上下文。请记住,为此,CallContext
必须是可序列化且不可变的,否则它将不安全且无法正常工作。
答案 1 :(得分:1)
Akka.NET目前不是很ExecutionContext
友好。如果AppDomain完全信任,则ThreadPoolDispatcher正在使用ThreadPool.UnsafeQueueUserWorkItem,因此CallContext不会在actor之间流动。
但是,如果您使用Ask使用ActorSystem,则执行文本将由TPL捕获并在任务的继续中恢复。