/// <summary>
        /// Triggered externally by the operation upon completion
        /// </summary>
        /// <param name="operation"></param>
        /// <param name="result"></param>
        private void OnOperationComplete(BaseOperation operation, Result result)
        {
            // long operationTime = StopwatchService.Stop(OperationStopwatchKey + operation.operationID);
            // this.LogAssertion($"{operation.GetOperationName()}: Time ms: {operationTime}\n{result}", result.Success);

            // Check if should wait for parallel operations before proceeding to next step
            _result += result;
            _parallelOperationsCounter--;
            if (_parallelOperationsCounter > 0)
            {
                return;
            }

            _lastOperationResult = result;

            // Continue to next operation if exists or complete operation queue
            if (_result.Success && _operations.Count > 0)
            {
                ExecuteNextOperation();
            }
            else
            {
                OnOperationQueueCompleted();
            }
        }
        /// <summary>
        /// Start executing the next operation in queue & any
        /// subsequent operations that should run in parallel
        /// </summary>
        private void ExecuteNextOperation()
        {
            _parallelOperationsCounter++;
            _totalExecutedOperations++;

            // Dequeue next operation & execute it
            BaseOperation operation = _operations[0];

            _operations.RemoveAt(0);

            try
            {
                this.Log(operation.GetOperationName());
                // StopwatchService.Start(OperationStopwatchKey + operation.operationID);
                operation.ExecuteOperation(_totalExecutedOperations, _lastOperationResult, OnOperationComplete);
            }
            catch (Exception exception)
            {
                this.LogException(exception);
                Result result = new Result();
                result.SetFailure("Exception while executing operation:\n" + exception.Message);
                OnOperationComplete(operation, result);
                return;
            }

            // Run next operation if it should run in parallel
            if (_operations.Count > 0 && _operations[0].RunInParallel)
            {
                ExecuteNextOperation();
            }
        }