Exemple #1
0
 private void EnsureRoutineHubKey(RoutineName routineName)
 {
     if (!this.RoutineHub.ContainsKey(routineName))
     {
         this.RoutineHub.Add(routineName, new Queue <IRoutineItem>());
     }
 }
Exemple #2
0
        private T Run <T>(RoutineName routineName, IRoutineItem r, Feedback feedback, object[] args)
        {
            r.BroadCastMessage = feedback.Success.Value; // Set the broadcast message. Other values are set during registration.

            var request  = Request.Create(r.CommandName, r.BroadCastMessage, args);
            var response = new Response(request, request.Message + "[Routine: " + routineName + "]", ResponseTypes.Success);


            var result = (T)r.Action.DynamicInvoke(args);

            response.Entity    = result;
            response.Type      = result.GetType();
            response.EventName = r.EventName;
            response.Message   = request.Message ?? String.Format(ResponseMessage, "N/A", r.Action.Method.Name, response.Type.Name);

            this.CommandStream.Enqueue(new CommandStreamItem()
            {
                Command = r.CommandName, Response = response
            });

            // Broadcase the response to all listeners.
            this.Broadcast(response);

            return(result);
        }
Exemple #3
0
        internal override bool MatchesInvoke(Invoke request, IQuery query)
        {
            if (request == null)
            {
                return(false);
            }

            bool ignoreCase = true;

            if (query != null)
            {
                ignoreCase = query.IgnoreIdentifiersCase();
            }

            if (!RoutineName.Equals(request.RoutineName, ignoreCase))
            {
                return(false);
            }

            // TODO: add a better resolution to obtain the final type of the argument
            //       and compare it to the parameter type definition
            bool unboundedSeen = false;

            for (int i = 0; i < request.Arguments.Length; i++)
            {
                var argType = request.Arguments[i].ReturnType(query, null);

                if (i + 1 > Parameters.Length)
                {
                    if (!unboundedSeen)
                    {
                        return(false);
                    }

                    // TODO: verify the type of the argument (how to evaluate?)
                }
                else
                {
                    var param = Parameters[i];
                    unboundedSeen = param.IsUnbounded;

                    var paramType = param.Type;

                    if (!paramType.IsComparable(argType))
                    {
                        return(false);
                    }
                }
            }

            if (!unboundedSeen &&
                request.Arguments.Length != Parameters.Length)
            {
                return(false);
            }

            return(true);
        }
Exemple #4
0
        public T RollBack <T>(RoutineName routineName, Feedback feedback, object[] args)
        {
            if (!this.RoutineHub.ContainsKey(routineName))
            {
                throw new ArgumentException("There is no routine by this name registered.");
            }

            if (this.RoutineHub[routineName].FirstOrDefault(x => x.Rollback == null) != null)
            {
                throw new InvalidDataException("There is a method in this routine without a RollBack function assigned. This routine is not eligable for RollBack.");
            }

            var result = default(T);

            var reverse = this.RoutineHub[routineName].Reverse().ToList();

            for (var i = (reverse.Count - 1); i >= 0; i--)
            {
                var request = Request.Create(reverse[i].CommandName, reverse[i].BroadCastMessage + "[Rolling Back Routine: " + routineName + "][" + (i - 1) + "/" + reverse.Count() + "]", args);

                var response = new Response(
                    request,
                    request.Message + "[Routine: " + routineName + "] [Executing Rollback Method: "
                    + reverse[i].Rollback.Method.Name + "]",
                    ResponseTypes.Success)
                {
                    EventName = reverse[i].EventName
                };

                try
                {
                    result          = (T)reverse[i].Rollback.DynamicInvoke(args);
                    response.Entity = result;

                    // Broadcase the response to all listeners.
                    this.Broadcast(response);
                }
                catch (TargetInvocationException rollbackException)
                {
                    this.BroadCast(rollbackException, request);

                    response.Message      = "[All is lost. RollBack method failed]" + response.Message;
                    response.ResponseType = ResponseTypes.Error;

                    this.CommandStream.Enqueue(new CommandStreamItem()
                    {
                        Command = reverse[i].CommandName, Response = response
                    });

                    // Broadcase the response to all listeners.
                    this.Broadcast(response);

                    break;
                }
            }
            return(result);
        }
Exemple #5
0
        public T Run <T>(RoutineName routineName, Feedback feedback, object[] args)
        {
            var result  = default(T);
            var routine = this.RoutineHub[routineName].ToList();

            for (var i = 0; i < routine.Count - 1; i++)
            {
                try
                {
                    result = this.Run <T>(routineName, routine[i], new Feedback()
                    {
                        Success = new Resource()
                        {
                            Value = "(Routine: " + routineName + ")(" + (i + 1) + "/" + routine.Count + ")"
                        }
                    }, args);

                    //Replace whatever T was that was passed in.
                    int index = Array.FindIndex(args, x => x.GetType() == typeof(T) || x.GetType().IsSubclassOf(typeof(T)));
                    args[index] = result;
                }
                catch (Exception ex)
                {
                    var request    = Request.Create(routine[i].CommandName, routine[i].BroadCastMessage, args);
                    var exResponse = this.BroadCast(ex, request);

                    try
                    {
                        // If we have a fail over action then try it.
                        if (routine[i].FailOver != null)
                        {
                            try
                            {
                                result = this.FailOver <T>(routineName, request, exResponse.ResponseId, routine[i], args);
                            }
                            catch (Exception failOverException)
                            {
                                this.BroadCast(failOverException, request);
                                throw;
                            }
                        }
                        else
                        {
                            throw;
                        }
                    }
                    catch (Exception deepEx)
                    {
                        this.BroadCast(deepEx, request);
                        throw;
                    }
                }
            }

            return(result);
        }
Exemple #6
0
        internal override bool MatchesInvoke(Invoke invoke, IRequest request)
        {
            if (invoke == null)
            {
                return(false);
            }

            if (!RoutineName.Equals(invoke.RoutineName))
            {
                return(false);
            }

            // TODO: add a better resolution to obtain the final type of the argument
            //       and compare it to the parameter type definition
            bool unboundedSeen = false;

            for (int i = 0; i < invoke.Arguments.Length; i++)
            {
                var argType = invoke.Arguments[i].Value.ReturnType(request, null);

                if (i + 1 > Parameters.Length)
                {
                    if (!unboundedSeen)
                    {
                        return(false);
                    }

                    // TODO: verify the type of the argument (how to evaluate?)
                }
                else
                {
                    var param = Parameters[i];
                    unboundedSeen = param.IsUnbounded;

                    var paramType = param.Type;

                    if (!paramType.IsComparable(argType))
                    {
                        return(false);
                    }
                }
            }

            if (!unboundedSeen &&
                invoke.Arguments.Length != Parameters.Length)
            {
                return(false);
            }

            return(true);
        }
Exemple #7
0
        internal override bool MatchesInvoke(Invoke invoke, IQuery query)
        {
            if (invoke == null)
            {
                return(false);
            }

            bool ignoreCase = true;

            if (query != null)
            {
                ignoreCase = query.IgnoreIdentifiersCase();
            }

            if (!RoutineName.Equals(invoke.RoutineName, ignoreCase))
            {
                return(false);
            }


            var inputParams = Parameters.Where(parameter => parameter.IsInput).ToList();

            if (invoke.Arguments.Length != inputParams.Count)
            {
                return(false);
            }

            for (int i = 0; i < invoke.Arguments.Length; i++)
            {
                // TODO: support variable evaluation here? or evaluate parameters before reaching here?
                if (!invoke.Arguments[i].IsConstant())
                {
                    return(false);
                }

                var argType   = invoke.Arguments[i].ReturnType(query, null);
                var paramType = Parameters[i].Type;

                // TODO: verify if this is assignable (castable) ...
                if (!paramType.IsComparable(argType))
                {
                    return(false);
                }
            }

            return(true);
        }
Exemple #8
0
        /// <summary>
        /// Register with the routine hub, which is used to chain command actions and provide failover and rollback options
        /// </summary>
        /// <typeparam name="T">The type of the parameter which will be passed between actions.</typeparam>
        /// <param name="routineName">Name of the routine to associate this command name, event name, and action.</param>
        /// <param name="commandName">Name of the command to register</param>
        /// <param name="eventName">Broadcast channel</param>
        /// <param name="action">Called as the primary/preferred target</param>
        /// <param name="failOver">Optional. Will be called on error of the 'action'</param>
        /// <param name="rollBack">Optional. In the advent of an error that can't be solved by action or failover. Once this level is reached the command queue will stop processing.</param>
        public void Register <T>(RoutineName routineName, CommandName commandName, EventName eventName, Func <T, Feedback, T> action, Func <T, Feedback, T> failOver = null, Func <T, Feedback, T> rollBack = null)
        {
            try
            {
                this.EnsureRoutineHubKey(routineName);

                this.RoutineHub[routineName].Enqueue(new RoutineItem {
                    CommandName = commandName, EventName = eventName, Action = action, FailOver = failOver, Rollback = rollBack
                });                                                                                                                                                                    // wireup the action associated with this command, and the event channel to broadcast to when this command is processed.
            }
            catch (Exception ex)
            {
                var msg = string.Format(ResponseMessage, "Registration failed with msg: " + ex.Message, action.Method.Name, typeof(T).Name);
                this.Broadcast(new Response {
                    Entity = ex, Type = ex.GetType(), EventName = EventName.OnException, Message = msg
                });
            }
        }
        internal override bool MatchesInvoke(Invoke invoke, IRequest request)
        {
            if (invoke == null)
            {
                return(false);
            }

            if (!RoutineName.Equals(invoke.RoutineName))
            {
                return(false);
            }


            var inputParams = Parameters.Where(parameter => parameter.IsInput).ToList();

            if (invoke.Arguments.Length != inputParams.Count)
            {
                return(false);
            }

            for (int i = 0; i < invoke.Arguments.Length; i++)
            {
                if (!invoke.Arguments[i].Value.IsConstant())
                {
                    return(false);
                }

                var argType   = invoke.Arguments[i].Value.ReturnType(request, null);
                var paramType = Parameters[i].Type;

                // TODO: verify if this is assignable (castable) ...
                if (!paramType.IsComparable(argType))
                {
                    return(false);
                }
            }

            return(true);
        }
Exemple #10
0
        private T FailOver <T>(RoutineName routineName, Request request, Guid exResponseId, IRoutineItem r, object[] args)
        {
            request.Message = request.Message;
            var response = new Response(request, "", ResponseTypes.Success);

            var result = (T)r.FailOver.DynamicInvoke(args);

            response.Entity    = result;
            response.Type      = result.GetType();
            response.EventName = r.EventName;
            response.Message   = "[Executing Failover Method: " + r.FailOver.Method.Name + "]" + String.Format(ResponseMessage, "N/A", r.Action.Method.Name, response.Type.Name);

            this.CommandStream.Enqueue(new CommandStreamItem()
            {
                Command  = r.CommandName,
                Response = response
            });

            // Broadcase the response to all listeners.
            this.Broadcast(response);

            return(result);
        }