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()); }
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)); }
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(); }
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);
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);
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);
internal Task OnPreActorMethodAsyncInternal(ActorMethodContext actorMethodContext) { return(this.OnPreActorMethodAsync(actorMethodContext)); }
/// <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); }
internal async Task OnPostActorMethodAsyncInternal(ActorMethodContext actorMethodContext) { await this.OnPostActorMethodAsync(actorMethodContext); await this.SaveStateAsync(); }