Passing Contextual Information

强颜欢笑 提交于 2021-01-28 14:41:36

问题


We are in the process of adding akka.net actors to part of a legacy system.

The basic idea is that a message comes in from an external system, it is handed off to a logic that is managed by akka.net actors which then talk to legacy components that do things like save data to the database.

The legacy code relies on the fact that a userId is set in the CallContext, which it can then retrieve before doing database writes (to store things like "CreatedBy" and "LastModifiedBy"). It seems clear that the CallContext will not be available once the message is passed through the actor system.

This seems like it would be a common problem/requirement, but I've been unable to find this question via google or looking through the akka/akka.net discussion groups.

Is there a concept of a contextual wrapper/envelope in akka.net, or is my only option to make the passing of contextual information an explicit part of the message?


回答1:


Since your message may be possibly passed across actor system boundaries, the best option here seems to be wrapping CallContext and message to be passed, and load it on message arrival to one of the actor's fields. Here is the example code using AroundReceive method:

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))
}

This way, call context will be loaded already, when the message hits the receive method of an actor. Remember that for this, CallContext must be serializable and immutable, otherwise it won't be safe and work properly.




回答2:


Akka.NET is currently not very ExecutionContext friendly. The ThreadPoolDispatcher is using ThreadPool.UnsafeQueueUserWorkItem if the AppDomain is in full trust, so the CallContext will not flow across actors.

However, if you consume the ActorSystem with Ask, the ExecutionContext will be captured by the TPL and restored in the Task's continuation.



来源:https://stackoverflow.com/questions/35510695/passing-contextual-information

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!