Ejemplo n.º 1
0
        /// <summary>
        /// Chain the next request using (MessagePack) binary serialized data.
        /// TPayload is the type that the received actor will try to deserialize payload to.
        /// </summary>
        /// <typeparam name="TPayload"></typeparam>
        /// <param name="requestContext"></param>
        /// <param name="payload"></param>
        /// <param name="actionName"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        protected virtual async Task ChainRequestAsync <TPayload>(ActorRequestContext requestContext, byte[] payload, string actionName = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            var isRequestValid = ValidateRequestAsync(requestContext, cancellationToken);

            if (isRequestValid.Result)
            {
                try
                {
                    //serialize back to object
                    var deserializedPayload = DeserializePayload <TPayload>(payload);

#pragma warning disable 618
                    await ChainRequestAsync(requestContext, deserializedPayload, actionName, cancellationToken);

#pragma warning restore 618
                }
                catch (Exception ex)
                {
                    Logger.LogError(ex, $"[{CurrentActor}-ChainRequestAsync]Failed to deserialize of type {typeof(TPayload)}: " + ex.Message);
                    throw;
                }
            }
            else
            {
                var exception = new ActorRequestInvalidException(
                    $"Actor Request {requestContext.RequestId} with action name {requestContext.ActionName} from {requestContext.ManagerId} is failed to validate and will not be processed by actor {Id} of the service {ActorService.ActorTypeInformation.ServiceName}. The exception will be propagated to the caller and possibly result in a retry.");
                Logger.LogError(exception, exception.Message);
                throw exception;
            }
        }
        public virtual async Task SaveRequest(string actionName, ActorRequestContext actorRequestContext, Type typeOfPayload, byte[] entity, CancellationToken cancellationToken)
        {
            try
            {
                await StateManager.AddStateAsync(NameCompositionResolver.GenerateRequestContextStateName(actionName, actorRequestContext.RequestId), actorRequestContext, cancellationToken);

                await StateManager.AddStateAsync(NameCompositionResolver.GenerateRequestPayloadStateName(actionName, actorRequestContext.RequestId), entity, cancellationToken);

                await StateManager.AddStateAsync(NameCompositionResolver.GenerateRequestPayloadTypeStateName(actionName, actorRequestContext.RequestId), typeOfPayload.AssemblyQualifiedName, cancellationToken);

                //As cancellation token cant be serialized & replicated to other node and cant be used to invoke cancellation
                //await StateManager.AddStateAsync(NameCompositionResolver.GenerateRequestCanncellationTokenStateName(actionName, actorRequestContext.RequestId), cancellationToken, cancellationToken);

                //UnComment if wantting to deal with status of the requests

                /*
                 * await StateManager.AddStateAsync(
                 *  NameCompositionResolver.GenerateRequestStateStateName(actionName,
                 *      actorRequestContext.RequestId), false, cancellationToken);
                 * //add current latest reminder name for any current info. due to the single thread behaviour of actors, this is valid
                 * await StateManager.AddOrUpdateStateAsync(ACTOR_REMINDER_LATEST_STATE_NAME, NameCompositionResolver.GenerateReminderName(actionName, actorRequestContext.RequestId),
                 *  (s, reminderName) => reminderName, cancellationToken);
                 */
            }
            catch (InvalidOperationException ex)
            {
                //add an already existed state
                //throw;
            }
        }
Ejemplo n.º 3
0
        public async Task ChainNextActorAsync(ActorRequestContext nextActorRequestContext, object payload, Type typeOfPayload, ActorIdentity actorIdentity, CancellationToken cancellationToken)
        {
            if (actorIdentity?.ActorId == null || actorIdentity?.ActorServiceUri == null)
            {
                throw new ArgumentNullException($"MessagingActorClient failed at ChainNextActorAsync due to null of {nameof(actorIdentity)}. The client could not chain to next actor which is null.");
            }
            //put more logic on to the orchestration collection later. Now it is just get the single one
            var proxy = ActorProxy.Create <IBaseMessagingActor>(
                new ActorId(actorIdentity.ActorId),
                new Uri(actorIdentity.ActorServiceUri));

            var serializedPayload = _binaryMessageSerializer.SerializePayload(payload, typeOfPayload);

            try
            {
                await proxy.ChainProcessMessageAsync(nextActorRequestContext, serializedPayload, cancellationToken);
            }
            catch (System.Fabric.FabricServiceNotFoundException)
            {
                if (actorIdentity.ActorServiceUri.Equals(Constants.DetourConstants.DEFAULT_GENERIC_DETOUR_ACTOR,
                                                         StringComparison.OrdinalIgnoreCase))
                {
                    if ((dynamic)payload is DetourPayload detourPayload)
                    {
                        serializedPayload = _binaryMessageSerializer.SerializePayload(detourPayload.NextActorPayload);
                        proxy             = ActorProxy.Create <IBaseMessagingActor>(
                            new ActorId(detourPayload.NextActorId),
                            new Uri(detourPayload.DefaultNextActorUri));
                        await proxy.ChainProcessMessageAsync(nextActorRequestContext, serializedPayload, cancellationToken);
                    }
                }
                throw;
            }
        }
        /// <summary>
        /// Wrapper for orchestration-order to be converted to executable order
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="nextActorRequestContext"></param>
        /// <param name="payload"></param>
        /// <param name="order"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        protected virtual async Task ChainNextActorsAsync(ActorRequestContext nextActorRequestContext, object payload, Type typeOfPayload, OrchestrationOrder order, CancellationToken cancellationToken)
        {
            //put more logic on to the orchestration collection later. Now it is just get the single one
            var anotherOrderInMyActorLifeTime =
                order.ToExecutableOrder();

            await ChainNextActorsAsync(nextActorRequestContext, payload, typeOfPayload, anotherOrderInMyActorLifeTime, cancellationToken);

            //just do nothing because no order
        }
        protected virtual async Task ChainNextActorsAsync(ActorRequestContext nextActorRequestContext, object payload, Type typeOfPayload, CancellationToken cancellationToken)
        {
            // if having any request-order
            if (!Orders.IsEmpty)
            {
                //put more logic on to the orchestration collection later. Now it is just get the single one
                var anotherOrderInMyActorLifeTime =
                    Orders.GetFirstExecutableOrder();

                await ChainNextActorsAsync(nextActorRequestContext, payload, typeOfPayload, anotherOrderInMyActorLifeTime, cancellationToken);
            }
            //just do nothing because no order
        }
        public async Task ChainNextActorAsync(ActorRequestContext nextActorRequestContext, object payload, Type typeOfPayload, ActorIdentity actorIdentity, CancellationToken cancellationToken)
        {
            if (actorIdentity?.ActorId == null || actorIdentity?.ActorServiceUri == null)
            {
                throw new ArgumentNullException($"MessagingActorClient failed at ChainNextActorAsync due to null of {nameof(actorIdentity)}. The client could not chain to next actor which is null.");
            }
            //put more logic on to the orchestration collection later. Now it is just get the single one
            var proxy = ActorProxy.Create <IBaseMessagingActor>(
                new ActorId(actorIdentity.ActorId),
                new Uri(actorIdentity.ActorServiceUri));

            var serializedPayload = _binaryMessageSerializer.SerializePayload(payload, typeOfPayload);
            await proxy.ChainProcessMessageAsync(nextActorRequestContext, serializedPayload, cancellationToken);
        }
        /// <summary>
        /// Main method to chain an order take in an executable order
        /// Allow actors to directly make call to next actor via an executable order object
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="nextActorRequestContext"></param>
        /// <param name="payload"></param>
        /// <param name="excutableOrder"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        protected virtual async Task ChainNextActorsAsync(ActorRequestContext nextActorRequestContext, object payload, Type typeOfPayload, ExecutableOrchestrationOrder excutableOrder, CancellationToken cancellationToken)
        {
            //try to complete the step
            await CompleteStepAsync(payload);

            try
            {
                await ActorClient.ChainNextActorAsync(nextActorRequestContext, payload, typeOfPayload, new ActorIdentity(excutableOrder.ActorId, excutableOrder.ActorServiceUri), cancellationToken);
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, $"{CurrentActor} failed to chain next actor {excutableOrder?.ActorServiceUri} with actor id {excutableOrder?.ActorId}. Message: {ex.Message}");
            }
        }
Ejemplo n.º 8
0
        public async Task <string> SaveMessageAsync(ActorRequestContext actorRequestContext, string key, byte[] payload, CancellationToken cancellationToken)
        {
            try
            {
                // save message => schedule to delete after TTL
                await RegisterReminderAsync(TTL_REMINDER_NAME, null, TimeSpan.FromDays(MAX_TTL_IN_MINUTE), TimeSpan.FromMilliseconds(-1));

                await StateManager.AddOrUpdateStateAsync(key, payload, (k, v) => payload, cancellationToken);

                return(key);
            }
            catch (System.Exception ex)
            {
                Logger.LogError(ex, $"Failed to store the variable with key {key}.");
                return(SAVED_ERROR);
            }
        }
        protected async Task ChainNextActorAsync(ActorRequestContext nextActorRequestContext, string startedPayload, object nextPayload, Type typeOfPayload, ExecutableOrchestrationOrder order, CancellationToken cancellationToken)
        {
            var flowInstanceId = nextActorRequestContext.FlowInstanceId;

            // var startedFlowInstanceId = new FlowInstanceId(Activity.Current.Id, (this.GetType().Name));
            var applicationName = Context.CodePackageActivationContext.ApplicationName;

            await TryCreateFlow(applicationName, flowInstanceId, startedPayload);

            var uri = new Uri(order.ActorServiceUri);

            //var startedFlowInstanceId = new FlowInstanceId(Activity.Current.Id, (this.GetType().Name));
            var proxy = ActorProxy.Create <IBaseMessagingActor>(order.ActorId == null ? ActorId.CreateRandom() : new ActorId(order.ActorId), uri);

            var payload = BinaryMessageSerializer.SerializePayload(nextPayload);
            await proxy.ChainProcessMessageAsync(nextActorRequestContext, payload, cancellationToken);
        }
Ejemplo n.º 10
0
        public async Task <byte[]> RetrieveMessageAsync(ActorRequestContext actorRequestContext, string key, bool isOptional, CancellationToken cancellationToken)
        {
            try
            {
                //anytime a request to retrieve data, re-schedule reminder to new one
                await RegisterReminderAsync(TTL_REMINDER_NAME, null, TimeSpan.FromDays(MAX_TTL_IN_MINUTE), TimeSpan.FromMilliseconds(-1));

                return(await StateManager.GetStateAsync <byte[]>(key));
            }
            catch (System.Exception ex)
            {
                if (isOptional)
                {
                    return(null);
                }
                Logger.LogError(ex, $"Failed to retrieve the variable with key {key} from {actorRequestContext?.ManagerId}.");
                throw;
            }
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Non generic version of ChainRequestAsync
        /// </summary>
        /// <param name="requestContext"></param>
        /// <param name="payload"></param>
        /// <param name="typeOfPayload"></param>
        /// <param name="actionName"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        protected virtual async Task ChainRequestAsyncNonGeneric(ActorRequestContext requestContext, byte[] payload, Type typeOfPayload,
                                                                 string actionName = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            try
            {
                //any specify reminder name? if not, use default
                var currentActionName   = actionName ?? requestContext.ActionName;
                var currentReminderName = NameCompositionResolver.GenerateReminderName(currentActionName, requestContext.RequestId);

                //persist request to state
                await ActorRequestPersistence.SaveRequest(currentActionName, requestContext, typeOfPayload, payload, cancellationToken);

                // register reminder to process the request later
                await RegisterReminderAsync(currentReminderName, null,
                                            _dueTime, _periodTimeInfinite);
            }
            catch (Exception e)
            {
                Logger.LogError(e, $"[{CurrentActor}-ChainRequestAsync] Failed to chain request of type {typeOfPayload.Name}: " + e.Message);
                throw;
            }
        }
Ejemplo n.º 12
0
        /// <summary>
        /// This method will allow supports for Flow&Step involed in the implementation without a strong type expression of the interface
        /// This method also help when we have methodName resolved by a serialized Step
        /// </summary>
        /// <param name="methodName"></param>
        /// <param name="actorRequestContext"></param>
        /// <param name="arguments"></param>
        /// <returns></returns>
        private static async Task Invoke(string methodName, ActorRequestContext actorRequestContext, params object[] arguments)
        {
            if (actorRequestContext?.TargetActor == null)
            {
                throw new ArgumentNullException(INVALID_TARGET_ACTOR_ERROR_MESSAGE);
            }

            var serializableMethodInfo = new SerializableMethodInfo();

            serializableMethodInfo.MethodName = methodName;
            actorRequestContext.MethodName    = methodName;

            foreach (var arg in arguments)
            {
                serializableMethodInfo.Arguments.Add(new SerializableMethodArgument()
                {
                    ArgumentAssemblyType = arg.GetType().AssemblyQualifiedName,
                    Value = _binaryMessageSerializer.SerializePayload(arg)
                });
            }
            actorRequestContext.ActionName = actorRequestContext.ActionName;
            await _actorClient.ChainNextActorAsync <SerializableMethodInfo>(actorRequestContext, serializableMethodInfo, actorRequestContext.TargetActor, CancellationToken.None);
        }
Ejemplo n.º 13
0
 public virtual async Task ChainProcessMessageAsync(ActorRequestContext actorRequestContext, byte[] payload,
                                                    CancellationToken cancellationToken)
 {
     //Every action only work with SerializableMethodInfo class
     await ChainRequestAsync <SerializableMethodInfo>(actorRequestContext, payload, actorRequestContext.ActionName, cancellationToken);
 }
Ejemplo n.º 14
0
 public ActorHttpAsyncHandler(ActorRequestContext context, TInput inputModel, Channel <TInput> input)
 {
     _context    = context;
     _input      = input;
     _inputModel = inputModel;
 }
Ejemplo n.º 15
0
 protected abstract Task <bool> FlowInitialize(ActorRequestContext actorRequestContext, FlowInstanceId flowInstanceId, CancellationToken cancellationToken);
Ejemplo n.º 16
0
 public static Task Invoke <TIActionInterface>(Expression <Func <TIActionInterface, object> > expression, ActorRequestContext actorRequestContext, ExecutableOrchestrationOrder executableOrchestrationOrder, CancellationToken cancellationToken) where TIActionInterface : IRemotableAction
 => ActionInvoker <TIActionInterface> .Invoke(expression, actorRequestContext, executableOrchestrationOrder, cancellationToken);
 /// <summary>
 /// Validate request to see if the action name is already implemented on the actor or some failure with manager id
 /// Override when there is the need of that kind validation. Possible exception that could be thrown is ActorMessageValidationException and all of its deriveds
 /// </summary>
 /// <param name="requestContext"></param>
 /// <param name="cancellationToken"></param>
 /// <exception cref="ActorMessageValidationException"></exception>
 /// <exception cref="ActorRequestActionNameNotSupportedException"></exception>
 /// <returns></returns>
 protected virtual Task <bool> ValidateRequestAsync(ActorRequestContext requestContext,
                                                    CancellationToken cancellationToken)
 {
     return(Task.FromResult(true));
 }
        public override async Task ChainProcessMessageAsync(ActorRequestContext actorRequestContext, byte[] payload, CancellationToken cancellationToken)
        {
            var serviceBusOption = Deserialize <ServiceBusOption>(payload);

            await ChainCreateEventBusListenersAsync(serviceBusOption);
        }
Ejemplo n.º 19
0
 public Task ChainRequestAsync(ActorRequestContext actorRequestContext, byte[] payload, Type typeOfPayload, string actionName, CancellationToken cancellationToken) => Actor.ChainRequestAsync(actorRequestContext, payload, typeOfPayload, actionName, cancellationToken);
Ejemplo n.º 20
0
 public Task ChainNextActorAsync <T>(ActorRequestContext nextActorRequestContext, T payload, ActorIdentity actorIdentity, CancellationToken cancellationToken)
 {
     return(ChainNextActorAsync(nextActorRequestContext, payload, typeof(T), actorIdentity, cancellationToken));
 }
Ejemplo n.º 21
0
 public Task ChainNextActorsAsync <TIActionInterface>(Expression <Func <TIActionInterface, object> > expression, ActorRequestContext actorRequestContext, ExecutableOrchestrationOrder executableOrchestrationOrder, CancellationToken cancellationToken) where TIActionInterface : IRemotableAction => Actor.ChainNextActorsAsync(expression, actorRequestContext, executableOrchestrationOrder, cancellationToken);
Ejemplo n.º 22
0
 public static Task Invoke(string methodName, ActorRequestContext actorRequestContext, ExecutableOrchestrationOrder executableOrchestrationOrder, params object[] arguments)
 {
     actorRequestContext.TargetActor = new ActorIdentity(executableOrchestrationOrder.ActorId, executableOrchestrationOrder.ActorServiceUri);
     return(Invoke(methodName, actorRequestContext, arguments));
 }
Ejemplo n.º 23
0
 public Task ChainNextActorsAsync(ActorRequestContext actorRequestContext, object payload, Type typeOfPayload, ExecutableOrchestrationOrder executableOrchestrationOrder, CancellationToken cancellationToken) => Actor.ChainNextActorsAsync(actorRequestContext, payload, typeOfPayload, executableOrchestrationOrder, cancellationToken);
Ejemplo n.º 24
0
 public virtual Task <bool> InitFlowAsync(ActorRequestContext actorRequestContext, FlowInstanceId flowInstanceId, CancellationToken cancellationToken)
 {
     FlowInstanceId = flowInstanceId;
     FlowServiceUri = actorRequestContext.ManagerService;
     return(FlowInitialize(actorRequestContext, flowInstanceId, cancellationToken));
 }
 public abstract Task ChainProcessMessageAsync(ActorRequestContext actorRequestContext, byte[] payload,
                                               CancellationToken cancellationToken);
Ejemplo n.º 26
0
 public override Task ChainProcessMessageAsync(ActorRequestContext actorRequestContext, byte[] payload, CancellationToken cancellationToken)
 {
     return(Task.CompletedTask);
 }
 /// <summary>
 /// Main method to chain an order take in an executable order
 /// Allow actors to directly make call to next actor via an executable order object
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="nextActorRequestContext"></param>
 /// <param name="payload"></param>
 /// <param name="excutableOrder"></param>
 /// <param name="cancellationToken"></param>
 /// <returns></returns>
 protected virtual async Task ChainNextActorsAsync <T>(ActorRequestContext nextActorRequestContext, T payload, ExecutableOrchestrationOrder excutableOrder, CancellationToken cancellationToken)
 {
     await ChainNextActorsAsync(nextActorRequestContext, payload, typeof(T), excutableOrder, cancellationToken);
 }