예제 #1
0
        internal ActorManager(
            ActorRegistration registration,
            ActorActivator activator,
            JsonSerializerOptions jsonSerializerOptions,
            ILoggerFactory loggerFactory,
            IActorProxyFactory proxyFactory,
            IDaprInteractor daprInteractor)
        {
            this.registration          = registration;
            this.activator             = activator;
            this.jsonSerializerOptions = jsonSerializerOptions;
            this.loggerFactory         = loggerFactory;
            this.proxyFactory          = proxyFactory;
            this.daprInteractor        = daprInteractor;

            this.timerManager = new DefaultActorTimerManager(this.daprInteractor);

            // map for remoting calls.
            this.methodDispatcherMap = new ActorMethodDispatcherMap(this.registration.Type.InterfaceTypes);

            // map for non-remoting calls.
            this.actorMethodInfoMap    = new ActorMethodInfoMap(this.registration.Type.InterfaceTypes);
            this.activeActors          = new ConcurrentDictionary <ActorId, ActorActivatorState>();
            this.reminderMethodContext = ActorMethodContext.CreateForReminder(ReceiveReminderMethodName);
            this.timerMethodContext    = ActorMethodContext.CreateForTimer(TimerMethodName);
            this.serializersManager    = IntializeSerializationManager(null);
            this.messageBodyFactory    = new WrappedRequestMessageFactory();

            this.logger = loggerFactory.CreateLogger(this.GetType());
        }
예제 #2
0
        internal async Task <Tuple <string, byte[]> > DispatchWithRemotingAsync(ActorId actorId, string actorMethodName, string daprActorheader, Stream data, CancellationToken cancellationToken)
        {
            var actorMethodContext = ActorMethodContext.CreateForActor(actorMethodName);

            // Get the serialized header
            var actorMessageHeader = this.serializersManager.GetHeaderSerializer()
                                     .DeserializeRequestHeaders(new MemoryStream(Encoding.ASCII.GetBytes(daprActorheader)));

            var interfaceId = actorMessageHeader.InterfaceId;

            // Get the deserialized Body.
            var msgBodySerializer = this.serializersManager.GetRequestMessageBodySerializer(actorMessageHeader.InterfaceId);

            IActorRequestMessageBody actorMessageBody;

            using (var stream = new MemoryStream())
            {
                await data.CopyToAsync(stream);

                actorMessageBody = msgBodySerializer.Deserialize(stream);
            }

            // Call the method on the method dispatcher using the Func below.
            var methodDispatcher = this.methodDispatcherMap.GetDispatcher(actorMessageHeader.InterfaceId, actorMessageHeader.MethodId);

            // Create a Func to be invoked by common method.
            async Task <Tuple <string, byte[]> > RequestFunc(Actor actor, CancellationToken ct)
            {
                IActorResponseMessageBody responseMsgBody = null;

                try
                {
                    responseMsgBody = (IActorResponseMessageBody)await methodDispatcher.DispatchAsync(
                        actor,
                        actorMessageHeader.MethodId,
                        actorMessageBody,
                        this.messageBodyFactory,
                        ct);

                    return(this.CreateResponseMessage(responseMsgBody, interfaceId));
                }
                catch (Exception exception)
                {
                    // return exception response message
                    return(this.CreateExceptionResponseMessage(exception));
                }
            }

            return(await this.DispatchInternalAsync(actorId, actorMethodContext, RequestFunc, cancellationToken));
        }
예제 #3
0
        internal ActorManager(ActorService actorService)
        {
            this.actorService = actorService;

            // map for remoting calls.
            this.methodDispatcherMap = new ActorMethodDispatcherMap(this.actorService.ActorTypeInfo.InterfaceTypes);

            // map for non-remoting calls.
            this.actorMethodInfoMap    = new ActorMethodInfoMap(this.actorService.ActorTypeInfo.InterfaceTypes);
            this.activeActors          = new ConcurrentDictionary <ActorId, Actor>();
            this.reminderMethodContext = ActorMethodContext.CreateForReminder(ReceiveReminderMethodName);
            this.timerMethodContext    = ActorMethodContext.CreateForReminder(TimerMethodName);
            this.serializersManager    = IntializeSerializationManager(null);
            this.messageBodyFactory    = new WrappedRequestMessageFactory();
        }
예제 #4
0
        internal async Task DispatchWithoutRemotingAsync(ActorId actorId, string actorMethodName, Stream requestBodyStream, Stream responseBodyStream, CancellationToken cancellationToken)
        {
            var actorMethodContext = ActorMethodContext.CreateForActor(actorMethodName);

            // Create a Func to be invoked by common method.
            var methodInfo = this.actorMethodInfoMap.LookupActorMethodInfo(actorMethodName);

            async Task <object> RequestFunc(Actor actor, CancellationToken ct)
            {
                var     parameters = methodInfo.GetParameters();
                dynamic awaitable;

                if (parameters.Length == 0)
                {
                    awaitable = methodInfo.Invoke(actor, null);
                }
                else
                {
                    // deserialize using stream.
                    var type             = parameters[0].ParameterType;
                    var deserializedType = default(object);
                    using (var streamReader = new StreamReader(requestBodyStream))
                    {
                        var json = await streamReader.ReadToEndAsync();

                        deserializedType = JsonConvert.DeserializeObject(json, type);
                    }

                    awaitable = methodInfo.Invoke(actor, new object[] { deserializedType });
                }

                await awaitable;

                // Write Response back if method's return type is other than Task.
                // Serialize result if it has result (return type was not just Task.)
                if (methodInfo.ReturnType.Name != typeof(Task).Name)
                {
                    // already await, Getting result will be non blocking.
                    var x = awaitable.GetAwaiter().GetResult();
                    return(x);
                }
                else
                {
                    return(default);
예제 #5
0
        internal async Task DispatchWithoutRemotingAsync(ActorId actorId, string actorMethodName, Stream requestBodyStream, Stream responseBodyStream, CancellationToken cancellationToken)
        {
            var actorMethodContext = ActorMethodContext.CreateForActor(actorMethodName);

            // Create a Func to be invoked by common method.
            var methodInfo = this.actorMethodInfoMap.LookupActorMethodInfo(actorMethodName);

            async Task <object> RequestFunc(Actor actor, CancellationToken ct)
            {
                var     parameters = methodInfo.GetParameters();
                dynamic awaitable;

                if (parameters.Length == 0)
                {
                    awaitable = methodInfo.Invoke(actor, null);
                }
                else if (parameters.Length == 1)
                {
                    // deserialize using stream.
                    var type             = parameters[0].ParameterType;
                    var deserializedType = await JsonSerializer.DeserializeAsync(requestBodyStream, type);

                    awaitable = methodInfo.Invoke(actor, new object[] { deserializedType });
                }
                else
                {
                    var errorMsg = $"Method {string.Concat(methodInfo.DeclaringType.Name, ".", methodInfo.Name)} has more than one parameter and can't be invoked through http";
                    ActorTrace.Instance.WriteError(TraceType, errorMsg);
                    throw new ArgumentException(errorMsg);
                }

                await awaitable;

                // Handle the return type of method correctly.
                if (methodInfo.ReturnType.Name != typeof(Task).Name)
                {
                    // already await, Getting result will be non blocking.
                    var x = awaitable.GetAwaiter().GetResult();
                    return(x);
                }
                else
                {
                    return(default);
예제 #6
0
        internal async Task DispatchWithoutRemotingAsync(ActorId actorId, string actorMethodName, Stream requestBodyStream, Stream responseBodyStream, CancellationToken cancellationToken)
        {
            var actorMethodContext = ActorMethodContext.CreateForActor(actorMethodName);

            // Create a Func to be invoked by common method.
            var methodInfo = this.actorMethodInfoMap.LookupActorMethodInfo(actorMethodName);

            async Task <object> RequestFunc(Actor actor, CancellationToken ct)
            {
                var     parameters = methodInfo.GetParameters();
                dynamic awaitable;

                if (parameters.Length == 0)
                {
                    awaitable = methodInfo.Invoke(actor, null);
                }
                else
                {
                    // deserialize using stream.
                    var type             = parameters[0].ParameterType;
                    var deserializedType = await JsonSerializer.DeserializeAsync(requestBodyStream, type);

                    awaitable = methodInfo.Invoke(actor, new object[] { deserializedType });
                }

                await awaitable;

                // Handle the return type of method correctly.
                if (methodInfo.ReturnType.Name != typeof(Task).Name)
                {
                    // already await, Getting result will be non blocking.
                    var x = awaitable.GetAwaiter().GetResult();
                    return(x);
                }
                else
                {
                    return(default);
예제 #7
0
 internal Task OnPreActorMethodAsyncInternal(ActorMethodContext actorMethodContext)
 {
     return(this.OnPreActorMethodAsync(actorMethodContext));
 }
예제 #8
0
 /// <summary>
 /// Override this method for performing any action after an actor method has finished execution.
 /// This method is invoked by actor runtime an actor method has finished execution.
 /// </summary>
 /// <param name="actorMethodContext">
 /// An <see cref="ActorMethodContext"/> describing the method that was invoked by actor runtime prior to this method.
 /// </param>
 /// <returns>
 /// Returns a <see cref="Task">Task</see> representing post-actor-method operation.
 /// </returns>
 /// /// <remarks>
 /// This method is invoked by actor runtime prior to:
 /// <list type="bullet">
 /// <item><description>Invoking an actor interface method when a client request comes.</description></item>
 /// <item><description>Invoking a method when a reminder fires.</description></item>
 /// <item><description>Invoking a timer callback when timer fires.</description></item>
 /// </list>
 /// </remarks>
 protected virtual Task OnPostActorMethodAsync(ActorMethodContext actorMethodContext)
 {
     return(Task.CompletedTask);
 }
예제 #9
0
        internal async Task OnPostActorMethodAsyncInternal(ActorMethodContext actorMethodContext)
        {
            await this.OnPostActorMethodAsync(actorMethodContext);

            await this.SaveStateAsync();
        }