Exemplo n.º 1
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);
            }
        }