AddEvent() public method

public AddEvent ( EventType evt ) : void
evt EventType
return void
        public async Task <T> ExecuteAsync()
        {
            /* this is a stateful object so can only be used once */
            if (Interlocked.CompareExchange(ref _started, 1, 0) == 1)
            {
                throw new IllegalStateException("This instance can only be executed once. Please instantiate a new instance.");
            }

            CacheItem cacheItem;

            // get from cache
            if (_requestCache != null)
            {
                var key = GetCacheKey();
                if (key != null && _requestCache.TryGetValue(key, out cacheItem))
                {
                    Metrics.MarkResponseFromCache();
                    _executionResult     = cacheItem.ExecutionResult;
                    _isExecutionComplete = true;
                    RecordExecutedCommand();
                    try
                    {
                        _executionHook.OnCacheHit(this);
                    }
                    catch (Exception hookEx)
                    {
                        Logger.LogWarning("Error calling CommandExecutionHook.onCacheHit", hookEx);
                    }
                    return(cacheItem.Value);
                }
            }

            T    result;
            long ms;
            var  start = _clock.EllapsedTimeInMs;

            try
            {
                RecordExecutedCommand();
                Metrics.IncrementConcurrentExecutionCount();

                // mark that we're starting execution on the ExecutionHook
                // if this hook throws an exception, then a fast-fail occurs with no fallback.  No state is left inconsistent
                _executionHook.OnStart(this);

                if (_circuitBreaker.AllowRequest)        // short circuit closed = OK
                {
                    if (ExecutionSemaphore.TryAcquire()) // semaphore
                    {
                        try
                        {
                            // if bulkhead by thread
                            var token = Properties.ExecutionTimeoutEnabled.Value
                                ? new CancellationTokenSource(Properties.ExecutionIsolationThreadTimeoutInMilliseconds.Value)
                                : new CancellationTokenSource();
                            try
                            {
                                if ((_flags & ServiceCommandOptions.SemaphoreExecutionStrategy) != ServiceCommandOptions.SemaphoreExecutionStrategy)
                                {
                                    _isExecutedInThread = true;

                                    ///
                                    /// If any of these hooks throw an exception, then it appears as if the actual execution threw an error
                                    ///
                                    _executionHook.OnThreadStart(this);
                                    _executionHook.OnExecutionStart(this);

                                    // Run with bulkhead and timeout
                                    var t = await Task.Factory.StartNew(
                                        () => Run(token.Token),
                                        token.Token,
                                        TaskCreationOptions.DenyChildAttach | TaskCreationOptions.HideScheduler,
                                        TaskScheduler
                                        )
                                            .ConfigureAwait(false);

                                    result = await t.ConfigureAwait(false);

                                    if (token.IsCancellationRequested)
                                    {
                                        throw new OperationCanceledException();
                                    }
                                    _executionHook.OnThreadComplete(this);
                                }
                                else
                                {
                                    // Simple semaphore
                                    _executionHook.OnExecutionStart(this);
                                    result = await Run(token.Token).ConfigureAwait(false);
                                }

                                try
                                {
                                    _executionHook.OnExecutionSuccess(this);
                                }
                                catch (Exception hookEx)
                                {
                                    Logger.LogWarning("Error calling CommandExecutionHook.onExecutionSuccess", hookEx);
                                }
                            }
                            catch (AggregateException ae)
                            {
                                ms = _clock.EllapsedTimeInMs - start;
                                var e = ((AggregateException)ae).InnerException;
                                return(await OnExecutionError(ms, e));
                            }
                            catch (TaskSchedulerException tex)
                            {
                                start = 0; // We don't want register execution time.
                                Metrics.MarkThreadPoolRejection();
                                return(await GetFallbackOrThrowException(EventType.THREAD_POOL_REJECTED, FailureType.REJECTED_THREAD_EXECUTION, "Thread pool is full", tex.InnerException));
                            }
                            catch (OperationCanceledException)
                            {
                                // timeout
                                ms = _clock.EllapsedTimeInMs - start;
                                Metrics.MarkTimeout(ms);
                                return(await GetFallbackOrThrowException(EventType.TIMEOUT, FailureType.TIMEOUT, "timed-out", ServiceCommand <T> .TimeoutException));
                            }
                            catch (Exception e)
                            {
                                ms = _clock.EllapsedTimeInMs - start;
                                e  = _executionHook.OnExecutionError(this, e);

                                return(await OnExecutionError(ms, e));
                            }

                            ms = _clock.EllapsedTimeInMs - start;
                            Metrics.AddCommandExecutionTime(ms);
                            Metrics.MarkSuccess(ms);
                            _circuitBreaker.MarkSuccess();
                            _executionResult.AddEvent(EventType.SUCCESS);

                            try
                            {
                                _executionHook.OnSuccess(this);
                            }
                            catch (Exception hookEx)
                            {
                                Logger.LogWarning("Error calling CommandExecutionHook.onSuccess", hookEx);
                            }

                            if (_requestCache != null)
                            {
                                var key = GetCacheKey();

                                cacheItem = new CacheItem {
                                    ExecutionResult = new ExecutionResult(_executionResult), Value = result
                                };
                                cacheItem.ExecutionResult.AddEvent(EventType.RESPONSE_FROM_CACHE);
                                cacheItem.ExecutionResult.ExecutionTime = -1;

                                if (key != null && !_requestCache.TryAdd(key, cacheItem))
                                {
                                    _requestCache.TryGetValue(key, out cacheItem);
                                    _executionResult = cacheItem.ExecutionResult;
                                    result           = cacheItem.Value;
                                    start            = 0;
                                }
                            }
                            return(result);
                        }
                        finally
                        {
                            ExecutionSemaphore.Release();
                        }
                    }
                    else
                    {
                        Metrics.MarkSemaphoreRejection();
                        return(await GetFallbackOrThrowException(EventType.SEMAPHORE_REJECTED, FailureType.REJECTED_SEMAPHORE_EXECUTION,
                                                                 "could not acquire a semaphore for execution", new Exception("could not acquire a semaphore for execution")));
                    }
                }
                else
                {
                    start = 0;
                    Metrics.MarkShortCircuited();
                    return(await GetFallbackOrThrowException(EventType.SHORT_CIRCUITED, FailureType.SHORTCIRCUIT,
                                                             "short-circuited", new Exception(" circuit short-circuited and is OPEN")));
                }
            }
            finally
            {
                if (start > 0)
                {
                    RecordTotalExecutionTime(start);
                }
                Metrics.DecrementConcurrentExecutionCount();
                _isExecutionComplete = true;
            }
        }