Ejemplo n.º 1
0
 internal void StartChain(string flowName, StepExecutionContext context)
 {
     var definitions = from definition in _Definitions
                       where definition.FlowCode.Equals(flowName, StringComparison.InvariantCultureIgnoreCase)
                       select definition;
     foreach (var definition in definitions)
     {
         definition.Steps.ForEach((step) => ProceedStep(step, context));
     }
 }
Ejemplo n.º 2
0
 private void ProceedStep(MachineWorkStep step, StepExecutionContext context)
 {
     IInvocation invocation = context.Invocation;
     step.Context = context;
     if (step.RequiresAttributeType == null)
     {
         step.ExecuteStep(invocation, null);
         _logger.DebugFormat("'{0}' has executed. No Aspect is required.", step.StepName);
         return;
     }
     IEnumerable<object> attribute = AttributesHelper.GetAttributes(invocation, step.RequiresAttributeType);
     if (attribute == null || attribute.Count() == 0)
     {
         _logger.DebugFormat("'{0}' can not be executed. No aspect was applied.", step.StepName);
         return;
     }
     step.ExecuteStep(invocation, attribute.Cast<AspectAttributeBase>());
     _logger.DebugFormat("'{0}' has executed. Aspects are applied.", step.StepName);
 }
Ejemplo n.º 3
0
        public async Task <WorkflowExecutorResult> Execute(WorkflowInstance workflow, WorkflowOptions options)
        {
            var wfResult = new WorkflowExecutorResult();

            var exePointers = new List <ExecutionPointer>(workflow.ExecutionPointers.Where(x => x.Active && (!x.SleepUntil.HasValue || x.SleepUntil < _datetimeProvider.Now.ToUniversalTime())));
            var def         = _registry.GetDefinition(workflow.WorkflowDefinitionId, workflow.Version);

            if (def == null)
            {
                _logger.LogError("Workflow {0} version {1} is not registered", workflow.WorkflowDefinitionId, workflow.Version);
                return(wfResult);
            }

            foreach (var pointer in exePointers)
            {
                var step = def.Steps.First(x => x.Id == pointer.StepId);
                if (step != null)
                {
                    try
                    {
                        switch (step.InitForExecution(wfResult, def, workflow, pointer))
                        {
                        case ExecutionPipelineDirective.Defer:
                            continue;

                        case ExecutionPipelineDirective.EndWorkflow:
                            workflow.Status       = WorkflowStatus.Complete;
                            workflow.CompleteTime = _datetimeProvider.Now.ToUniversalTime();
                            continue;
                        }

                        if (!pointer.StartTime.HasValue)
                        {
                            pointer.StartTime = _datetimeProvider.Now.ToUniversalTime();
                        }

                        _logger.LogDebug("Starting step {0} on workflow {1}", step.Name, workflow.Id);

                        IStepBody body = step.ConstructBody(_serviceProvider);

                        if (body == null)
                        {
                            _logger.LogError("Unable to construct step body {0}", step.BodyType.ToString());
                            pointer.SleepUntil = _datetimeProvider.Now.ToUniversalTime().Add(options.ErrorRetryInterval);
                            wfResult.Errors.Add(new ExecutionError()
                            {
                                WorkflowId         = workflow.Id,
                                ExecutionPointerId = pointer.Id,
                                ErrorTime          = _datetimeProvider.Now.ToUniversalTime(),
                                Message            = String.Format("Unable to construct step body {0}", step.BodyType.ToString())
                            });
                            continue;
                        }

                        IStepExecutionContext context = new StepExecutionContext()
                        {
                            Workflow         = workflow,
                            Step             = step,
                            PersistenceData  = pointer.PersistenceData,
                            ExecutionPointer = pointer,
                            Item             = pointer.ContextItem
                        };

                        ProcessInputs(workflow, step, body, context);

                        switch (step.BeforeExecute(wfResult, context, pointer, body))
                        {
                        case ExecutionPipelineDirective.Defer:
                            continue;

                        case ExecutionPipelineDirective.EndWorkflow:
                            workflow.Status       = WorkflowStatus.Complete;
                            workflow.CompleteTime = _datetimeProvider.Now.ToUniversalTime();
                            continue;
                        }

                        var result = await body.RunAsync(context);

                        if (result.Proceed)
                        {
                            ProcessOutputs(workflow, step, body);
                        }

                        ProcessExecutionResult(workflow, def, pointer, step, result, wfResult);
                        step.AfterExecute(wfResult, context, result, pointer);
                    }
                    catch (Exception ex)
                    {
                        pointer.RetryCount++;
                        _logger.LogError("Workflow {0} raised error on step {1} Message: {2}", workflow.Id, pointer.StepId, ex.Message);
                        wfResult.Errors.Add(new ExecutionError()
                        {
                            WorkflowId         = workflow.Id,
                            ExecutionPointerId = pointer.Id,
                            ErrorTime          = _datetimeProvider.Now.ToUniversalTime(),
                            Message            = ex.Message
                        });

                        switch (step.ErrorBehavior ?? def.DefaultErrorBehavior)
                        {
                        case WorkflowErrorHandling.Retry:
                            pointer.SleepUntil = _datetimeProvider.Now.ToUniversalTime().Add(step.RetryInterval ?? def.DefaultErrorRetryInterval ?? options.ErrorRetryInterval);
                            break;

                        case WorkflowErrorHandling.Suspend:
                            workflow.Status = WorkflowStatus.Suspended;
                            break;

                        case WorkflowErrorHandling.Terminate:
                            workflow.Status = WorkflowStatus.Terminated;
                            break;
                        }

                        Host.ReportStepError(workflow, step, ex);
                    }
                }
                else
                {
                    _logger.LogError("Unable to find step {0} in workflow definition", pointer.StepId);
                    pointer.SleepUntil = _datetimeProvider.Now.ToUniversalTime().Add(options.ErrorRetryInterval);
                    wfResult.Errors.Add(new ExecutionError()
                    {
                        WorkflowId         = workflow.Id,
                        ExecutionPointerId = pointer.Id,
                        ErrorTime          = _datetimeProvider.Now.ToUniversalTime(),
                        Message            = String.Format("Unable to find step {0} in workflow definition", pointer.StepId)
                    });
                }
            }
            ProcessAfterExecutionIteration(workflow, def, wfResult);
            DetermineNextExecutionTime(workflow);

            return(wfResult);
        }
Ejemplo n.º 4
0
        private async Task ExecuteStep(WorkflowInstance workflow, WorkflowStep step, ExecutionPointer pointer, WorkflowExecutorResult wfResult, WorkflowDefinition def)
        {
            using (var scope = _scopeProvider.CreateScope())
            {
                _logger.LogDebug("Starting step {0} on workflow {1}", step.Name, workflow.Id);

                IStepBody body = step.ConstructBody(scope.ServiceProvider);

                if (body == null)
                {
                    _logger.LogError("Unable to construct step body {0}", step.BodyType.ToString());
                    pointer.SleepUntil = _datetimeProvider.Now.ToUniversalTime().Add(_options.ErrorRetryInterval);
                    wfResult.Errors.Add(new ExecutionError()
                    {
                        WorkflowId         = workflow.Id,
                        ExecutionPointerId = pointer.Id,
                        ErrorTime          = _datetimeProvider.Now.ToUniversalTime(),
                        Message            = $"Unable to construct step body {step.BodyType.ToString()}"
                    });
                    return;
                }

                IStepExecutionContext context = new StepExecutionContext()
                {
                    Workflow         = workflow,
                    Step             = step,
                    PersistenceData  = pointer.PersistenceData,
                    ExecutionPointer = pointer,
                    Item             = pointer.ContextItem
                };

                foreach (var input in step.Inputs)
                {
                    input.AssignInput(workflow.Data, body, context);
                }

                switch (step.BeforeExecute(wfResult, context, pointer, body))
                {
                case ExecutionPipelineDirective.Defer:
                    return;

                case ExecutionPipelineDirective.EndWorkflow:
                    workflow.Status       = WorkflowStatus.Complete;
                    workflow.CompleteTime = _datetimeProvider.Now.ToUniversalTime();
                    return;
                }

                var result = await body.RunAsync(context);

                if (result.Proceed)
                {
                    foreach (var output in step.Outputs)
                    {
                        output.AssignOutput(workflow.Data, body, context);
                    }
                }

                _executionResultProcessor.ProcessExecutionResult(workflow, def, pointer, step, result, wfResult);
                step.AfterExecute(wfResult, context, result, pointer);
            }
        }
Ejemplo n.º 5
0
        public async Task <WorkflowExecutorResult> Execute(WorkflowInstance workflow)
        {
            var wfResult = new WorkflowExecutorResult();

            var exePointers = new List <ExecutionPointer>(workflow.ExecutionPointers.Where(x => x.Active && (!x.SleepUntil.HasValue || x.SleepUntil < _datetimeProvider.Now.ToUniversalTime())));
            var def         = _registry.GetDefinition(workflow.WorkflowDefinitionId, workflow.Version);

            if (def == null)
            {
                _logger.LogError("Workflow {0} version {1} is not registered", workflow.WorkflowDefinitionId, workflow.Version);
                return(wfResult);
            }

            foreach (var pointer in exePointers)
            {
                if (pointer.Status == PointerStatus.Cancelled)
                {
                    continue;
                }

                var step = def.Steps.FindById(pointer.StepId);
                if (step == null)
                {
                    _logger.LogError("Unable to find step {0} in workflow definition", pointer.StepId);
                    pointer.SleepUntil = _datetimeProvider.Now.ToUniversalTime().Add(_options.ErrorRetryInterval);
                    wfResult.Errors.Add(new ExecutionError()
                    {
                        WorkflowId         = workflow.Id,
                        ExecutionPointerId = pointer.Id,
                        ErrorTime          = _datetimeProvider.Now.ToUniversalTime(),
                        Message            = String.Format("Unable to find step {0} in workflow definition", pointer.StepId)
                    });
                    continue;
                }

                try
                {
                    switch (step.InitForExecution(wfResult, def, workflow, pointer))
                    {
                    case ExecutionPipelineDirective.Defer:
                        continue;

                    case ExecutionPipelineDirective.EndWorkflow:
                        workflow.Status       = WorkflowStatus.Complete;
                        workflow.CompleteTime = _datetimeProvider.Now.ToUniversalTime();
                        continue;
                    }

                    if (pointer.Status != PointerStatus.Running)
                    {
                        pointer.Status = PointerStatus.Running;
                        _publisher.PublishNotification(new StepStarted()
                        {
                            EventTimeUtc         = _datetimeProvider.Now,
                            Reference            = workflow.Reference,
                            ExecutionPointerId   = pointer.Id,
                            StepId               = step.Id,
                            WorkflowInstanceId   = workflow.Id,
                            WorkflowDefinitionId = workflow.WorkflowDefinitionId,
                            Version              = workflow.Version
                        });
                    }

                    if (!pointer.StartTime.HasValue)
                    {
                        pointer.StartTime = _datetimeProvider.Now.ToUniversalTime();
                    }

                    using (var scope = _scopeProvider.CreateScope())
                    {
                        _logger.LogDebug("Starting step {0} on workflow {1}", step.Name, workflow.Id);

                        IStepBody body = step.ConstructBody(scope.ServiceProvider);

                        if (body == null)
                        {
                            _logger.LogError("Unable to construct step body {0}", step.BodyType.ToString());
                            pointer.SleepUntil = _datetimeProvider.Now.ToUniversalTime().Add(_options.ErrorRetryInterval);
                            wfResult.Errors.Add(new ExecutionError()
                            {
                                WorkflowId         = workflow.Id,
                                ExecutionPointerId = pointer.Id,
                                ErrorTime          = _datetimeProvider.Now.ToUniversalTime(),
                                Message            = String.Format("Unable to construct step body {0}", step.BodyType.ToString())
                            });
                            continue;
                        }

                        IStepExecutionContext context = new StepExecutionContext()
                        {
                            Workflow         = workflow,
                            Step             = step,
                            PersistenceData  = pointer.PersistenceData,
                            ExecutionPointer = pointer,
                            Item             = pointer.ContextItem
                        };

                        foreach (var input in step.Inputs)
                        {
                            input.AssignInput(workflow.Data, body, context);
                        }


                        switch (step.BeforeExecute(wfResult, context, pointer, body))
                        {
                        case ExecutionPipelineDirective.Defer:
                            continue;

                        case ExecutionPipelineDirective.EndWorkflow:
                            workflow.Status       = WorkflowStatus.Complete;
                            workflow.CompleteTime = _datetimeProvider.Now.ToUniversalTime();
                            continue;
                        }

                        var result = await body.RunAsync(context);

                        if (result.Proceed)
                        {
                            foreach (var output in step.Outputs)
                            {
                                output.AssignOutput(workflow.Data, body, context);
                            }
                        }

                        _executionResultProcessor.ProcessExecutionResult(workflow, def, pointer, step, result, wfResult);
                        step.AfterExecute(wfResult, context, result, pointer);
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError("Workflow {0} raised error on step {1} Message: {2}", workflow.Id, pointer.StepId, ex.Message);
                    wfResult.Errors.Add(new ExecutionError()
                    {
                        WorkflowId         = workflow.Id,
                        ExecutionPointerId = pointer.Id,
                        ErrorTime          = _datetimeProvider.Now.ToUniversalTime(),
                        Message            = ex.Message
                    });

                    _executionResultProcessor.HandleStepException(workflow, def, pointer, step, ex);
                    Host.ReportStepError(workflow, step, ex);
                }
                _cancellationProcessor.ProcessCancellations(workflow, def, wfResult);
            }
            ProcessAfterExecutionIteration(workflow, def, wfResult);
            DetermineNextExecutionTime(workflow);

            return(wfResult);
        }
Ejemplo n.º 6
0
 internal void StartChain(string flowName, IInvocation invocation)
 {
     StepExecutionContext context = new StepExecutionContext { Invocation = invocation };
     StartChain(flowName, context);
 }
Ejemplo n.º 7
0
 public Task PersistWorkflowInstanceAsync(WorkflowInstance wfi, StepExecutionContext context, ExecutionResult executionResult,
                                          long elapsedMilliseconds, CancellationToken stoppingToken)
 {
     _logger.LogInformation($"{wfi.WorkflowId} 执行结果:{executionResult.Proceed}");
     return(Task.CompletedTask);
 }
        public async Task Execute(WorkflowInstance workflow, IPersistenceProvider persistenceStore, WorkflowOptions options)
        {
            //TODO: split this method up
            List <ExecutionPointer> exePointers = new List <ExecutionPointer>(workflow.ExecutionPointers.Where(x => x.Active && (!x.SleepUntil.HasValue || x.SleepUntil < DateTime.Now.ToUniversalTime())));
            var def = _registry.GetDefinition(workflow.WorkflowDefinitionId, workflow.Version);

            if (def == null)
            {
                _logger.LogError("Workflow {0} version {1} is not registered", workflow.WorkflowDefinitionId, workflow.Version);
                return;
            }

            foreach (var pointer in exePointers)
            {
                var step = def.Steps.First(x => x.Id == pointer.StepId);
                if (step != null)
                {
                    try
                    {
                        if (step.InitForExecution(_host, persistenceStore, def, workflow, pointer) == ExecutionPipelineDirective.Defer)
                        {
                            continue;
                        }

                        if (!pointer.StartTime.HasValue)
                        {
                            pointer.StartTime = DateTime.Now;
                        }

                        _logger.LogDebug("Starting step {0} on workflow {1}", step.Name, workflow.Id);

                        IStepBody body;

                        if (step is WorkflowStepInline)
                        {
                            body = new InlineStepBody((step as WorkflowStepInline).Body);
                        }
                        else
                        {
                            body = (_serviceProvider.GetService(step.BodyType) as IStepBody);
                            if (body == null)
                            {
                                var stepCtor = step.BodyType.GetConstructor(new Type[] { });
                                if (stepCtor != null)
                                {
                                    body = (stepCtor.Invoke(null) as IStepBody);
                                }
                            }

                            if (body == null)
                            {
                                _logger.LogError("Unable to construct step body {0}", step.BodyType.ToString());
                                pointer.SleepUntil = DateTime.Now.ToUniversalTime().Add(options.ErrorRetryInterval);
                                pointer.Errors.Add(new ExecutionError()
                                {
                                    Id        = Guid.NewGuid().ToString(),
                                    ErrorTime = DateTime.Now.ToUniversalTime(),
                                    Message   = String.Format("Unable to construct step body {0}", step.BodyType.ToString())
                                });
                                continue;
                            }
                        }

                        foreach (var input in step.Inputs)
                        {
                            var member        = (input.Target.Body as MemberExpression);
                            var resolvedValue = input.Source.Compile().DynamicInvoke(workflow.Data);
                            step.BodyType.GetProperty(member.Member.Name).SetValue(body, resolvedValue);
                        }

                        IStepExecutionContext context = new StepExecutionContext()
                        {
                            Workflow        = workflow,
                            Step            = step,
                            PersistenceData = pointer.PersistenceData
                        };

                        if (step.BeforeExecute(_host, persistenceStore, context, pointer, body) == ExecutionPipelineDirective.Defer)
                        {
                            continue;
                        }

                        var result = body.Run(context);

                        foreach (var output in step.Outputs)
                        {
                            var member        = (output.Target.Body as MemberExpression);
                            var resolvedValue = output.Source.Compile().DynamicInvoke(body);
                            var data          = workflow.Data;
                            data.GetType().GetProperty(member.Member.Name).SetValue(data, resolvedValue);
                        }

                        if (result.Proceed)
                        {
                            pointer.Active  = false;
                            pointer.EndTime = DateTime.Now;
                            int  forkCounter = 1;
                            bool noOutcomes  = true;
                            foreach (var outcome in step.Outcomes.Where(x => object.Equals(x.Value, result.OutcomeValue)))
                            {
                                workflow.ExecutionPointers.Add(new ExecutionPointer()
                                {
                                    Id             = Guid.NewGuid().ToString(),
                                    StepId         = outcome.NextStep,
                                    Active         = true,
                                    ConcurrentFork = (forkCounter * pointer.ConcurrentFork),
                                    StepName       = def.Steps.First(x => x.Id == outcome.NextStep).Name
                                });
                                noOutcomes = false;
                                forkCounter++;
                            }
                            pointer.PathTerminator = noOutcomes;
                        }
                        else
                        {
                            pointer.PersistenceData = result.PersistenceData;
                            if (result.SleepFor.HasValue)
                            {
                                pointer.SleepUntil = DateTime.Now.ToUniversalTime().Add(result.SleepFor.Value);
                            }
                        }

                        step.AfterExecute(_host, persistenceStore, context, result, pointer);
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError("Workflow {0} raised error on step {1} Message: {2}", workflow.Id, pointer.StepId, ex.Message);
                        pointer.Errors.Add(new ExecutionError()
                        {
                            Id        = Guid.NewGuid().ToString(),
                            ErrorTime = DateTime.Now.ToUniversalTime(),
                            Message   = ex.Message
                        });

                        switch (step.ErrorBehavior ?? def.DefaultErrorBehavior)
                        {
                        case WorkflowErrorHandling.Retry:
                            pointer.SleepUntil = DateTime.Now.ToUniversalTime().Add(step.RetryInterval ?? def.DefaultErrorRetryInterval ?? options.ErrorRetryInterval);
                            break;

                        case WorkflowErrorHandling.Suspend:
                            workflow.Status = WorkflowStatus.Suspended;
                            break;

                        case WorkflowErrorHandling.Terminate:
                            workflow.Status = WorkflowStatus.Terminated;
                            break;
                        }

                        _host.ReportStepError(workflow, step, ex);
                    }

                    await persistenceStore.PersistWorkflow(workflow);
                }
                else
                {
                    _logger.LogError("Unable to find step {0} in workflow definition", pointer.StepId);
                    pointer.SleepUntil = DateTime.Now.ToUniversalTime().Add(options.ErrorRetryInterval);
                    pointer.Errors.Add(new ExecutionError()
                    {
                        ErrorTime = DateTime.Now.ToUniversalTime(),
                        Message   = String.Format("Unable to find step {0} in workflow definition", pointer.StepId)
                    });
                }
            }
            DetermineNextExecutionTime(workflow);
            await persistenceStore.PersistWorkflow(workflow);
        }
Ejemplo n.º 9
0
        public async Task Execute(WorkflowInstance workflow, IPersistenceProvider persistenceStore, WorkflowOptions options)
        {
            List <ExecutionPointer> exePointers = new List <ExecutionPointer>(workflow.ExecutionPointers.Where(x => x.Active && (!x.SleepUntil.HasValue || x.SleepUntil < DateTime.Now.ToUniversalTime())));
            var def = _registry.GetDefinition(workflow.WorkflowDefinitionId, workflow.Version);

            if (def == null)
            {
                _logger.LogError("Workflow {0} version {1} is not registered", workflow.WorkflowDefinitionId, workflow.Version);
                return;
            }

            foreach (var pointer in exePointers)
            {
                var step = def.Steps.First(x => x.Id == pointer.StepId);
                if (step != null)
                {
                    try
                    {
                        if ((step is ISubscriptionStep) && (!pointer.EventPublished))
                        {
                            pointer.EventKey  = (step as ISubscriptionStep).EventKey;
                            pointer.EventName = (step as ISubscriptionStep).EventName;
                            pointer.Active    = false;
                            await persistenceStore.PersistWorkflow(workflow);

                            await _host.SubscribeEvent(workflow.Id, pointer.StepId, pointer.EventName, pointer.EventKey);

                            continue;
                        }

                        if (!pointer.StartTime.HasValue)
                        {
                            pointer.StartTime = DateTime.Now;
                        }

                        _logger.LogDebug("Starting step {0} on workflow {1}", step.Name, workflow.Id);

                        IStepBody body;

                        if (step is WorkflowStepInline)
                        {
                            body = new InlineStepBody((step as WorkflowStepInline).Body);
                        }
                        else
                        {
                            body = (_serviceProvider.GetService(step.BodyType) as IStepBody);
                            if (body == null)
                            {
                                var stepCtor = step.BodyType.GetConstructor(new Type[] { });
                                if (stepCtor != null)
                                {
                                    body = (stepCtor.Invoke(null) as IStepBody);
                                }
                            }

                            if (body == null)
                            {
                                _logger.LogError("Unable to construct step body {0}", step.BodyType.ToString());
                                pointer.SleepUntil = DateTime.Now.ToUniversalTime().Add(options.ErrorRetryInterval);
                                pointer.Errors.Add(new ExecutionError()
                                {
                                    ErrorTime = DateTime.Now.ToUniversalTime(),
                                    Message   = String.Format("Unable to construct step body {0}", step.BodyType.ToString())
                                });
                                continue;
                            }
                        }

                        foreach (var input in step.Inputs)
                        {
                            var member        = (input.Target.Body as MemberExpression);
                            var resolvedValue = input.Source.Compile().DynamicInvoke(workflow.Data);
                            step.BodyType.GetProperty(member.Member.Name).SetValue(body, resolvedValue);
                        }

                        if ((body is ISubscriptionBody) && (pointer.EventPublished))
                        {
                            (body as ISubscriptionBody).EventData = pointer.EventData;
                        }

                        IStepExecutionContext context = new StepExecutionContext()
                        {
                            Workflow        = workflow,
                            Step            = step,
                            PersistenceData = pointer.PersistenceData
                        };

                        var result = body.Run(context);

                        foreach (var output in step.Outputs)
                        {
                            var member        = (output.Target.Body as MemberExpression);
                            var resolvedValue = output.Source.Compile().DynamicInvoke(body);
                            var data          = workflow.Data;
                            data.GetType().GetProperty(member.Member.Name).SetValue(data, resolvedValue);
                        }

                        if (result.Proceed)
                        {
                            pointer.Active  = false;
                            pointer.EndTime = DateTime.Now;

                            foreach (var outcome in step.Outcomes.Where(x => object.Equals(x.Value, result.OutcomeValue)))
                            {
                                workflow.ExecutionPointers.Add(new ExecutionPointer()
                                {
                                    StepId = outcome.NextStep,
                                    Active = true
                                });
                            }
                        }
                        else
                        {
                            pointer.PersistenceData = result.PersistenceData;
                            if (result.SleepFor.HasValue)
                            {
                                pointer.SleepUntil = DateTime.Now.ToUniversalTime().Add(result.SleepFor.Value);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError("Workflow {0} raised error on step {1} Message: {2}", workflow.Id, pointer.StepId, ex.Message);
                        pointer.SleepUntil = DateTime.Now.ToUniversalTime().Add(options.ErrorRetryInterval);
                        pointer.Errors.Add(new ExecutionError()
                        {
                            ErrorTime = DateTime.Now.ToUniversalTime(),
                            Message   = ex.Message
                        });
                    }

                    await persistenceStore.PersistWorkflow(workflow);
                }
                else
                {
                    _logger.LogError("Unable to find step {0} in workflow definition", pointer.StepId);
                    pointer.SleepUntil = DateTime.Now.ToUniversalTime().Add(options.ErrorRetryInterval);
                    pointer.Errors.Add(new ExecutionError()
                    {
                        ErrorTime = DateTime.Now.ToUniversalTime(),
                        Message   = String.Format("Unable to find step {0} in workflow definition", pointer.StepId)
                    });
                }
            }
            DetermineNextExecutionTime(workflow);
            await persistenceStore.PersistWorkflow(workflow);
        }
Ejemplo n.º 10
0
        private async Task ExecuteAsync(WorkflowInstance wfi, CancellationToken stoppingToken)
        {
            using var scope = _serviceProvider.CreateScope();
            var context = new StepExecutionContext()
            {
                StoppingToken   = stoppingToken,
                ServiceProvider = _serviceProvider,
                Logger          = _logger,
                ContextData     = wfi.Data
            };
            var executionResult = new ExecutionResult();
            var sw = new Stopwatch();

            try
            {
                _options?.Start?.Invoke(scope.ServiceProvider, wfi);
                var steps = scope.ServiceProvider.GetServices <IStepBodyAsync>().ToList();
                _logger.LogInformation($"{wfi.Id} Begin");
                sw.Start();
                if (!steps.Any())
                {
                    throw new WorkflowStepNotRegisteredException(wfi.WorkflowId, wfi.Version);
                }
                foreach (var workFlowStep in wfi.Steps)
                {
                    var retryCnt = 0;
                    context.CurrentStep = workFlowStep;
                    var stepBody = steps.FirstOrDefault(m => m.GetType() == workFlowStep.StepType);
                    if (stepBody == null)
                    {
                        throw new NullReferenceException(workFlowStep?.StepType?.FullName);
                    }
                    _logger.LogInformation($"{workFlowStep.Id}, Begin");
                    var inComeData = context.ContextData;
                    // retry step when fail
                    while (retryCnt++ <= Math.Abs(context.CurrentStep.FailedRetryCount))
                    {
                        executionResult = await stepBody.RunAsync(context, stoppingToken);

                        if (executionResult.Proceed)
                        {
                            break;
                        }
                    }

                    var outComeData = context.ContextData;
                    // persistent current step data & status
                    await _persistenceProvider.PersistWorkflowStepAsync(wfi.Id, wfi.WorkflowId, workFlowStep, inComeData, outComeData, executionResult, stoppingToken);

                    if (!executionResult.Proceed)
                    {
                        _logger.LogError(
                            $"{workFlowStep.Id}, retryCount: {retryCnt - 1}, error:{executionResult.InnerException.Message}");
                        break;
                    }

                    _logger.LogInformation($"{workFlowStep.Id}, End");
                    _logger.LogInformation(
                        $"{workFlowStep.Id}, {executionResult.ConsumeElapsedMilliseconds} ms");
                }

                sw.Stop();
                if (!executionResult.Proceed)
                {
                    _logger.LogError($"{wfi.Id}, End With Exception: {executionResult.InnerException}");
                }
                _logger.LogInformation($"{wfi.Id}, End and Execute: {sw.ElapsedMilliseconds} ms");
            }
            catch (System.Exception e)
            {
                _logger.LogError(e.Message, e);
                executionResult.Proceed        = false;
                executionResult.InnerException = e;
            }
            finally
            {
                await _persistenceProvider.PersistWorkflowInstanceAsync(wfi, context, executionResult, sw.ElapsedMilliseconds, stoppingToken);

                _options?.End?.Invoke(scope.ServiceProvider, wfi, context, executionResult);
            }
        }