传递上下文信息

本文关键字:信息 上下文 | 更新日期: 2023-09-27 18:35:28

我们正在将 akka.net 参与者添加到遗留系统的一部分。

基本思想是,消息来自外部系统,它被传递给由 akka.net 参与者管理的逻辑,然后这些参与者与执行诸如将数据保存到数据库之类的操作的遗留组件进行通信。

遗留代码依赖于在 CallContext 中设置用户 ID 的事实,然后它可以在执行数据库写入之前检索该 userId(以存储"CreatedBy"和"LastModifiedBy"之类的内容)。 很明显,一旦消息通过参与者系统传递,CallContext 将不可用。

这似乎是一个常见的问题/要求,但我无法通过谷歌或查看 akka/akka.net 讨论组找到这个问题。

akka.net 中是否有上下文包装器/信封的概念,或者我的唯一选择是使上下文信息的传递成为消息的明确部分?

传递上下文信息

由于您的消息可能跨越参与者系统边界传递,因此这里最好的选择似乎是包装 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必须是可序列化且不可变的,否则它将不安全且无法正常工作。

Akka.NET 目前不是很ExecutionContext友好。如果 AppDomain 处于完全信任状态,则 ThreadPoolDispatcher 正在使用 ThreadPool.UnsafeQueueUserWorkItem,因此 CallContext 不会跨参与者流动。

但是,如果您将ActorSystem与Ask一起使用,则TPL将捕获ExecutionContext,并在任务的延续中恢复。