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);
            }
        }
Esempio n. 2
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);
        }
 /// <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)
 {
 }