Beispiel #1
0
        internal static CommandState PrepareInternal(Type commandType, IJellyfishContext context, string commandGroup, string commandName, CommandPropertiesBuilder propertiesBuilder = null, IClock clock = null, CommandMetrics metrics = null, ICircuitBreaker circuitBreaker = null)
        {
            var state = new CommandState();

            state.CommandName  = commandName ?? commandType.FullName;
            state.CommandGroup = commandGroup ?? state.CommandName;

            clock = clock ?? Clock.GetInstance();
            var properties = propertiesBuilder?.Build(state.CommandName) ?? new CommandProperties(state.CommandName);

            metrics        = metrics ?? CommandMetricsFactory.GetInstance(state.CommandName, state.CommandGroup, properties, clock);
            circuitBreaker = circuitBreaker ?? (properties.CircuitBreakerEnabled.Value ? CircuitBreakerFactory.GetOrCreateInstance(state.CommandName, properties, metrics, clock) : new NoOpCircuitBreaker());
            context.MetricsPublisher.CreateOrRetrievePublisherForCommand(state.CommandGroup, metrics, circuitBreaker);

            ServiceCommandOptions flags = ServiceCommandOptions.None;

            if (IsMethodImplemented(commandType, "GetFallback"))
            {
                flags |= ServiceCommandOptions.HasFallBack;
            }
            if (IsMethodImplemented(commandType, "GetCacheKey"))
            {
                flags |= ServiceCommandOptions.HasCacheKey;
            }
            state.Flags = flags;
            return(state);
        }
 public TestServiceCommand(IJellyfishContext ctx, string name, CommandPropertiesBuilder builder, IClock clock = null, TestCircuitBreaker circuitBreaker = null, CommandExecutionHook executionHook = null)
     : base(ctx ?? new JellyfishContext(), clock, name, name, null, builder, circuitBreaker, circuitBreaker?.Metrics, executionHook: executionHook)
 {
     SetFlag(ServiceCommandOptions.HasFallBack, false);
     SetFlag(ServiceCommandOptions.HasCacheKey, false);
     Id = cx++;
 }
        private static void InitializeServices(IJellyfishContext ctx, Assembly asm)
        {
            foreach(var t in asm.GetTypes())
            {
                if(!typeof( IServiceCommandInfo ).IsAssignableFrom( t ))
                    continue;

                var attr = t.GetCustomAttributes<CommandAttribute>( true ).FirstOrDefault();                
                ServiceCommandHelper.PrepareInternal( t, ctx, attr?.CommandGroup, attr?.CommandName );
            }
        }
Beispiel #4
0
        private static void InitializeServices(IJellyfishContext ctx, Assembly asm)
        {
            foreach (var t in asm.GetTypes())
            {
                if (!typeof(IServiceCommandInfo).IsAssignableFrom(t))
                {
                    continue;
                }

                var attr = t.GetCustomAttributes <CommandAttribute>(true).FirstOrDefault();
                ServiceCommandHelper.PrepareInternal(t, ctx, attr?.CommandGroup, attr?.CommandName);
            }
        }
        internal ServiceCommand(IJellyfishContext context, IClock clock, string commandGroup = null, string commandName = null, string threadPoolKey = null, CommandPropertiesBuilder properties = null, ICircuitBreaker circuitBreaker = null, CommandMetrics metrics = null, CommandExecutionHook executionHook = null)
        {
            Contract.Requires(context != null);
            CommandState state = _states.GetOrAdd(this.GetType().FullName, (n) => ServiceCommandHelper.PrepareInternal(this.GetType(), context, commandGroup, commandName, properties, clock, metrics, circuitBreaker));

            if (String.IsNullOrEmpty(state.CommandGroup))
            {
                throw new ArgumentException("commandGroup can not be null or empty.");
            }

            Logger = context.GetService <ILoggerFactory>()?.CreateLogger(this.GetType().FullName) ?? EmptyLogger.Instance;

            CommandGroup    = state.CommandGroup;
            CommandName     = state.CommandName;
            _clock          = clock ?? Clock.GetInstance(); // for test
            Properties      = properties?.Build(CommandName) ?? new CommandProperties(CommandName);
            Metrics         = metrics ?? CommandMetricsFactory.GetInstance(CommandName, CommandGroup, Properties, _clock);
            _circuitBreaker = circuitBreaker ?? (Properties.CircuitBreakerEnabled.Value ? CircuitBreakerFactory.GetOrCreateInstance(CommandName, Properties, Metrics, _clock) : new NoOpCircuitBreaker());
            context.MetricsPublisher.CreateOrRetrievePublisherForCommand(CommandGroup, Metrics, _circuitBreaker);

            this._flags = state.Flags;

            _threadPoolKey   = threadPoolKey ?? CommandGroup;
            _executionResult = new ExecutionResult();
            _executionHook   = executionHook ?? context.CommandExecutionHook;

            var executionPolicy = Properties.ExecutionIsolationStrategy.Value;

            if (executionPolicy == ExecutionIsolationStrategy.Semaphore)
            {
                _flags |= ServiceCommandOptions.SemaphoreExecutionStrategy;
            }
            if (executionPolicy == ExecutionIsolationStrategy.Thread)
            {
                _flags |= ServiceCommandOptions.ThreadExecutionStrategy;
            }

            if (Properties.RequestLogEnabled.Value)
            {
                _currentRequestLog = context.GetRequestLog();
            }

            if ((_flags & ServiceCommandOptions.HasCacheKey) == ServiceCommandOptions.HasCacheKey && Properties.RequestCacheEnabled.Value)
            {
                _requestCache = context.GetCache <CacheItem>(CommandName);
            }
        }
        internal static CommandState PrepareInternal(Type commandType, IJellyfishContext context, string commandGroup, string commandName, CommandPropertiesBuilder propertiesBuilder=null, IClock clock = null, CommandMetrics metrics = null, ICircuitBreaker circuitBreaker = null)
        {
            var state = new CommandState();

            state.CommandName = commandName ?? commandType.FullName;
            state.CommandGroup = commandGroup ?? state.CommandName;

            clock = clock ?? Clock.GetInstance();
            var properties = propertiesBuilder?.Build( state.CommandName ) ?? new CommandProperties( state.CommandName );
            metrics = metrics ?? CommandMetricsFactory.GetInstance( state.CommandName, state.CommandGroup, properties, clock );
            circuitBreaker = circuitBreaker ?? ( properties.CircuitBreakerEnabled.Value ? CircuitBreakerFactory.GetOrCreateInstance( state.CommandName, properties, metrics, clock ) : new NoOpCircuitBreaker() );
            context.MetricsPublisher.CreateOrRetrievePublisherForCommand( state.CommandGroup, metrics, circuitBreaker );

            ServiceCommandOptions flags = ServiceCommandOptions.None;
            if(IsMethodImplemented( commandType, "GetFallback" ))
                flags |= ServiceCommandOptions.HasFallBack;
            if(IsMethodImplemented( commandType, "GetCacheKey" ))
                flags |= ServiceCommandOptions.HasCacheKey;
            state.Flags = flags;
            return state;
        }
        // ignoring since this never ends ... useful for testing https://github.com/Netflix//issues/236

        //  [Fact]
        //public void testSuccessClosesCircuitWhenBusy()
        //    {
        //        Plugins.getInstance().registerCommandExecutionHook(new MyCommandExecutionHook());
        //    try {
        //            performLoad(200, 0, 40);
        //            performLoad(250, 100, 40);
        //            performLoad(600, 0, 40);
        //        } finally {
        //        .reset();
        //        }

        //    }

        async Task performLoad(IJellyfishContext ctx, int totalNumCalls, int errPerc, int waitMillis)
        {
            Random rnd = new Random();

            for (int i = 0; i < totalNumCalls; i++)
            {
                //System.out.println(i);

                try
                {
                    var err = rnd.NextDouble() * 100 < errPerc;

                    TestCommand cmd = new TestCommand(ctx, err);
                    await cmd.ExecuteAsync();
                }
                catch (Exception)
                {
                    //System.err.println(e.getMessage());
                }

                Thread.Sleep(waitMillis);
            }
        }
 internal MetricsPublisherFactory(IJellyfishContext context)
 {
     _context = context;
 }
 public MyCommand(IJellyfishContext ctx, string id)
     : base(ctx)
 {
     _id = id;
 }
        public static TestServiceCommand Get(IJellyfishContext ctx, ITestOutputHelper output, string commandName, ExecutionIsolationStrategy strategy,
                                             ExecutionResult executionResult          = ExecutionResult.NONE, FallbackResult fallbackResult = FallbackResult.UNIMPLEMENTED,
                                             Action <CommandPropertiesBuilder> setter = null, TestCircuitBreaker circuitBreaker             = null, IClock clock = null)
        {
            var builder = CommandPropertiesTest.GetUnitTestPropertiesSetter();

            builder.WithExecutionIsolationStrategy(strategy);
            if (setter != null)
            {
                setter(builder);
            }
            if (clock == null)
            {
                clock = new MockedClock();
            }

            var cmd = new TestServiceCommand(ctx, commandName, builder, clock, circuitBreaker ?? new TestCircuitBreaker(clock), new TestExecutionHook(output));

            cmd.Log = msg => output.WriteLine("({0}) - {1}", cmd.Id, msg);

            if (executionResult == ExecutionResult.SUCCESS)
            {
                cmd.Action = () =>
                {
                    cmd.Log("Execution success"); return(Task.FromResult(TestCommandFactory.EXECUTE_VALUE));
                };
            }
            else if (executionResult == ExecutionResult.FAILURE)
            {
                cmd.Action = () => { cmd.Log("Execution failure");; throw new Exception("Execution Failure for TestCommand"); };
            }
            else if (executionResult == ExecutionResult.HYSTRIX_FAILURE)
            {
                cmd.Action = () =>
                {
                    cmd.Log("Execution failure");
                    throw new Exception("Execution  Failure for TestCommand", new Exception("Fallback Failure for TestCommand"));
                };
            }
            else if (executionResult == ExecutionResult.RECOVERABLE_ERROR)
            {
                cmd.Action = () =>
                {
                    cmd.Log("Execution recoverable error");
                    throw new Exception("Execution ERROR for TestCommand");
                };
            }
            else if (executionResult == ExecutionResult.UNRECOVERABLE_ERROR)
            {
                cmd.Action = () =>
                {
                    cmd.Log("Execution unrecoverable error");
                    throw new StackOverflowException("Unrecoverable Error for TestCommand");
                };
            }
            else if (executionResult == ExecutionResult.BAD_REQUEST)
            {
                cmd.Action = () =>
                {
                    cmd.Log("Execution bad request");
                    throw new BadRequestException("Execution BadRequestException for TestCommand");
                };
            }

            if (fallbackResult == FallbackResult.SUCCESS)
            {
                cmd.Fallback = () =>
                {
                    cmd.Log("Execution fallback success");
                    return(Task.FromResult(TestCommandFactory.FALLBACK_VALUE));
                };
            }
            else if (fallbackResult == FallbackResult.FAILURE)
            {
                cmd.Fallback = () => { cmd.Log("Execution fallback error"); throw new Exception("Fallback Failure for TestCommand"); };
            }
            else if (fallbackResult == FallbackResult.UNIMPLEMENTED)
            {
                cmd.Fallback = () =>
                {
                    cmd.Log("Execution fallback unimplemented");
                    throw new NotImplementedException();
                };
            }

            return(cmd);
        }
 public SuccessfulCacheableCommand(IJellyfishContext ctx, TestCircuitBreaker circuitBreaker, bool cacheEnabled, T value)
     : base(ctx, circuitBreaker.Clock, "SuccessfulCacheableCommand", null, metrics: circuitBreaker.Metrics, circuitBreaker: circuitBreaker, properties: CommandPropertiesTest.GetUnitTestPropertiesSetter().WithRequestCacheEnabled(true))
 {
     this.value        = value;
     this.cacheEnabled = cacheEnabled;
 }
 internal MetricsPublisherFactory(IJellyfishContext context)
 {
     _context = context;
 }
 public TestController(IJellyfishContext ctx)
 {
     _context = ctx;
 }
 public TestController(IJellyfishContext ctx)
 {
     _context = ctx;
 }
 /// <summary>
 /// Construct a <see cref="ServiceCommand{T}"/>.
 /// <p>
 /// The CommandName will be derived from the implementing class name.
 /// Construct a <see cref="ServiceCommand{T}"/> with defined <see cref="CommandPropertiesBuilder"/> that allows injecting property
 ///  and strategy overrides and other optional arguments.
 /// <p>
 /// NOTE: The CommandName is used to associate a <see cref="ServiceCommand{T}"/>
 ///  with <see cref="ICircuitBreaker"/>, <see cref="CommandMetrics"/> and other objects.
 /// <p>
 /// Do not create multiple <see cref="ServiceCommand{T}"/> implementations with the same CommandName
 /// but different injected default properties as the first instantiated will win.
 /// <p>
 /// Properties passed in via <see cref="CommandPropertiesBuilder">Properties</see> are cached for the given CommandName for the life of the Process
 /// or until <see cref="IJellyfishContext.Reset"/> is called. Dynamic properties allow runtime changes. Read more on the <a href="https://github.com/Zenasoft/Jellyfish.Configuration"> Wiki</a>.
 /// </summary>
 /// <param name="context">Current jellyfish context</param>
 /// <param name="commandGroup">
 /// used to group together multiple <see cref="ServiceCommand{T}"/> objects. <p/>
 /// The CommandGroup is used to represent a common relationship between commands.
 /// For example, a library or team name, the system all related commands interact with, common business purpose etc.
 /// </param>
 /// <param name="properties"></param>
 /// <param name="threadPoolKey">
 /// used to identify the thread pool in which a <see cref="ServiceCommand{T}"/> executes.
 /// </param>
 internal protected ServiceCommand(IJellyfishContext context, string commandGroup = null, string commandName = null, CommandPropertiesBuilder properties = null, string threadPoolKey = null, CommandExecutionHook executionHook = null)
     : this(context, null, commandGroup, commandName, threadPoolKey, properties)
 {
 }
Beispiel #16
0
 public LatentCommand(IJellyfishContext ctx, int duration)
     : base(ctx, "Latent", null, new CommandPropertiesBuilder().WithExecutionTimeoutInMilliseconds(1000), null)
 {
     this.duration = duration;
 }
 public TestCommand(IJellyfishContext ctx, bool error) : base(ctx ?? new JellyfishContext(), "group")
 {
     this.error = error;
 }