Exemplo n.º 1
0
        /// <summary>
        /// Executes Plugin's ExecutePlugin method safely taking care maintaining the right execution context
        /// </summary>
        /// <param name="actualParams">Key-Value pairs representing Typed variable and their names</param>
        /// <returns>PluginOutput object</returns>
        private async Task <PluginData <T> > ExecuteSafely <T>(PluginInputs actualParams)
            where T : Schema, new()
        {
            var            pluginSucceeded = false;
            PluginData <T> pluginData      = null;

            try
            {
                EnsurePluginIsInitialized();
                _executionContext.StartPluginExecution(PluginContext);
                if (AlreadyExecuted())
                {
                    pluginSucceeded = true;
                    pluginData      = _executionContext.GetPluginOutputFromId <T>(PluginContext.PluginOutputId);
                }
                else if (RequiredInputsNotNull(actualParams, ExecInfo.ParameterInfo))
                {
                    if (!IsCompatiblePlugin())
                    {
                        throw new VersionMismatchException(PluginContext.PluginName);
                    }

                    _executionContext.UpdateInputConsumers(PluginContext);
                    if (AllDependenciesFulFilled())
                    {
                        if (ValidateParams(actualParams, ExecInfo.ParameterInfo, out object[] validatedParams))
Exemplo n.º 2
0
        /// <summary>
        /// Uses reflection to safely execute a Typed "ExecutePlugin" method that is defined in a Task/Workflow
        /// </summary>
        /// <param name="actualParams">Key-Value pairs representing Typed variable and their names</param>
        public virtual async Task <PluginData <T> > Execute <T>(PluginInputs actualParams)
            where T : Schema, new()
        {
            if (actualParams == null)
            {
                throw new WorkflowEngineException("ContainerInputs passed to a plugin cannot be null");
            }

            PluginContext.PluginInputIds = actualParams.ToDictionary(kv => kv.Key, kv => kv.Value?.Id);
            return(await ExecuteSafely <T>(actualParams).ConfigureAwait(false));
        }
Exemplo n.º 3
0
        /// <summary>
        /// Ensures that all non-null plugin parameters have been instantiated properly
        /// TODO: Replace this with a Compile Time Check using FxCop
        /// </summary>
        private void EnsureParamsContextIsSet(PluginInputs actualParams)
        {
            if (actualParams == null)
            {
                throw new WorkflowEngineException(nameof(actualParams));
            }

            if (actualParams.Values.Any(param => param != null && param.ExecutionContext == null))
            {
                throw new WorkflowEngineException("Workflow ExecutionContext not set for this plugin data objects. Make sure to use PluginServices to GetFromId all Plugin String");
            }
        }
Exemplo n.º 4
0
        /// <summary>
        /// Returns true only if:
        /// 1. All single requird inputs are not null
        /// 2. All list required inputs are not null
        /// 3. Every item in non-null list inputs are not null
        /// </summary>
        private static bool RequiredInputsNotNull(PluginInputs actualParams, ParameterInfo[] expectedParams)
        {
            foreach (var ap in actualParams)
            {
                var pi = expectedParams.FirstOrDefault(ep => ep.Name == ap.Key);
                if (pi != null && pi.CustomAttributes.All(a => a.AttributeType != typeof(OptionalAttribute)) && ap.Value == null)
                {
                    return(false);
                }
            }

            return(!actualParams.Values.Any(param => param != null && param.IsList() && param.GetDataList().Any(item => item == null)));
        }
        public WorkflowContainerContext(IState persistentState)
        {
            var state = persistentState as WorkflowContextState;

            if (state == null)
            {
                throw new WorkflowEngineException("WorkflowContainerContext must be loaded with an object of type WorkflowContextState");
            }
            ExecutionContext  = new ExecutionContext(state.ExecutionContext);
            ContainerInputs   = new PluginInputs(state.ContainerInputs, ExecutionContext);
            RootPluginContext = new PluginContext(state.RootPluginContext);

            // Sync Root Plugin Context with Execution Context (Pointer Swizzling)
            RootPluginContext = ExecutionContext.GetPluginContextFromId(RootPluginContext.PluginId);
            Executed          = state.Executed;
            Variants          = state.Variants;
        }
Exemplo n.º 6
0
        private static void UpdatePluginInputs(PluginInputs oldInputs, PluginInputs newInputs)
        {
            if (newInputs == null)
            {
                return;
            }

            foreach (var kv in newInputs)
            {
                var oldInput = oldInputs[kv.Key];
                var newInput = kv.Value;
                if (!Equals(oldInput.Id, newInput.Id))
                {
                    throw new WorkflowEngineException("Attempting updating an input with a different one. Use GetWorkflowInput()");
                }

                oldInputs[kv.Key] = kv.Value;
            }
        }
Exemplo n.º 7
0
        public async Task <WorkflowContainerExecutionResult> ReExecute(PluginInputs newInputs = null)
        {
            EnsureContainerIsInitialized();
            if (!_containerContext.Executed)
            {
                throw new WorkflowEngineException("Cannot re-execute workfor container before executing it.");
            }
            var rootWorkflow = _pluginServices.LoadPlugin <TWorkflow>(_containerContext.RootPluginContext);

            UpdatePluginInputs(_containerContext.ContainerInputs, newInputs);
            try
            {
                _rootWorkflowOutput = await rootWorkflow.Execute <TOutput>(_containerContext.ContainerInputs).ConfigureAwait(false);
            }
            catch (VersionMismatchException)
            {
                return(WorkflowContainerExecutionResult.NotExecuted);
            }
            return(_rootWorkflowOutput == null ? WorkflowContainerExecutionResult.PartiallyCompleted : WorkflowContainerExecutionResult.Completed);
        }
Exemplo n.º 8
0
        async Task <WorkflowContainerExecutionResult> IWorkflowContainer <TWorkflow, TOutput> .Execute(PluginInputs workflowInputs)
        {
            EnsureContainerIsInitialized();
            if (_containerContext.Executed)
            {
                throw new WorkflowEngineException("Cannot execute workflow container more than once.");
            }

            var rootWorkflow = _pluginServices.LoadPlugin <TWorkflow>(_containerContext.RootPluginContext);

            _containerContext.Executed          = true;
            _containerContext.ContainerInputs   = workflowInputs ?? throw new WorkflowEngineException("Cannot execute container with null inputs");
            _containerContext.RootPluginContext = rootWorkflow.GetContext();
            _containerContext.ExecutionContext  = _pluginServices.GetExecutionContext();

            _rootWorkflowOutput = await rootWorkflow.Execute <TOutput>(workflowInputs).ConfigureAwait(false);

            return(_rootWorkflowOutput == null ? WorkflowContainerExecutionResult.PartiallyCompleted : WorkflowContainerExecutionResult.Completed);
        }