传递上下文信息
问题描述:
我们在加入akka.net演员遗留系统的一部分的过程。传递上下文信息
其基本思想是,一条消息从外部系统进入,它被交给一个由akka.net演员管理的逻辑,然后与传统组件进行对话,这些组件将数据保存到数据库中。
传统代码依赖于在CallContext中设置userId,然后在数据库写入之前可以检索(存储诸如“CreatedBy”和“LastModifiedBy”之类的东西)的事实。看起来很清楚,一旦消息传递给actor系统,CallContext就不可用。
这似乎将是一个常见的问题/需求,但我一直无法找到通过谷歌或者这个问题通过阿卡/ akka.net讨论组期待。
是否有akka.net上下文包装/信封的概念,或者是我做的上下文信息传递的唯一选项消息的明确的一部分吗?
答
Akka.NET目前不是很ExecutionContext
友好。如果AppDomain完全信任,ThreadPoolDispatcher正在使用ThreadPool.UnsafeQueueUserWorkItem,因此CallContext不会流过actor。
但是,如果你消耗与询问ActorSystem,在执行上下文将由TPL捕获并在任务的持续恢复。
答
由于您的消息可跨演员系统边界可能通过,最好选择在这里似乎被包裹CallContext中和消息传递,并加载在消息到达演员的领域之一。下面是使用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))
}
这样,呼叫内容将被加载,当消息到达一个演员的接收方法。请记住,为此,CallContext
必须是可序列化和不可变的,否则它将不安全并正常工作。