public async Task <string> StartWorkflow <TData>(string workflowId, int version, TData data) { if (_shutdown) { throw new Exception("Host is not running"); } var def = _registry.GetDefinition(workflowId, version); if (def == null) { throw new Exception(String.Format("Workflow {0} version {1} is not registered", workflowId, version)); } var wf = new WorkflowInstance(); wf.WorkflowDefinitionId = workflowId; wf.Version = version; wf.Data = data; wf.Description = def.Description; wf.NextExecution = 0; wf.Status = WorkflowStatus.Runnable; wf.ExecutionPointers.Add(new ExecutionPointer() { StepId = def.InitialStep, Active = true }); string id = await _persistenceStore.CreateNewWorkflow(wf); await _queueProvider.QueueForProcessing(id); return(id); }
public async Task <string> StartWorkflow <TData>(string workflowId, int?version, TData data = null) where TData : class { var def = _registry.GetDefinition(workflowId, version); if (def == null) { throw new WorkflowNotRegisteredException(workflowId, version); } var wf = new WorkflowInstance { WorkflowDefinitionId = workflowId, Version = def.Version, Data = data, Description = def.Description, NextExecution = 0, CreateTime = DateTime.Now.ToUniversalTime(), Status = WorkflowStatus.Runnable }; if ((def.DataType != null) && (data == null)) { wf.Data = TypeExtensions.GetConstructor(def.DataType, new Type[] { }).Invoke(null); } wf.ExecutionPointers.Add(_pointerFactory.BuildGenesisPointer(def)); string id = await _persistenceStore.CreateNewWorkflow(wf); await _queueProvider.QueueWork(id, QueueType.Workflow); return(id); }
public async Task <string> StartWorkflow <TData>(string workflowId, int?version, TData data = null, string reference = null) where TData : class, new() { var def = _registry.GetDefinition(workflowId, version); if (def == null) { throw new WorkflowNotRegisteredException(workflowId, version); } var wf = new WorkflowInstance { WorkflowDefinitionId = workflowId, Version = def.Version, Data = data, Description = def.Description, NextExecution = 0, CreateTime = _dateTimeProvider.UtcNow, Status = WorkflowStatus.Runnable, Reference = reference }; if ((def.DataType != null) && (data == null)) { if (typeof(TData) == def.DataType) { wf.Data = new TData(); } else { wf.Data = def.DataType.GetConstructor(new Type[0]).Invoke(new object[0]); } } wf.ExecutionPointers.Add(_pointerFactory.BuildGenesisPointer(def)); using (var scope = _serviceProvider.CreateScope()) { var middlewareRunner = scope.ServiceProvider.GetRequiredService <IWorkflowMiddlewareRunner>(); await middlewareRunner.RunPreMiddleware(wf, def); } string id = await _persistenceStore.CreateNewWorkflow(wf); await _queueProvider.QueueWork(id, QueueType.Workflow); await _queueProvider.QueueWork(id, QueueType.Index); await _eventHub.PublishNotification(new WorkflowStarted { EventTimeUtc = _dateTimeProvider.UtcNow, Reference = reference, WorkflowInstanceId = id, WorkflowDefinitionId = def.Id, Version = def.Version }); return(id); }
public async Task <IActionResult> Post(string workflowName, int?version, string document) { var def = _registry.GetDefinition(workflowName, version); if (def == null) { return(BadRequest($"Workflow definition {workflowName} for version {version} not found")); } var workflowId = await _workflowService.StartWorkflow( workflowName, version, data : new UntypedDocumentWorkflowData { Document = document }); return(Ok(workflowId)); }
public async Task <string> StartWorkflow <TData>(string workflowId, int?version, TData data = null, string reference = null) where TData : class, new() { var def = _registry.GetDefinition(workflowId, version); if (def == null) { throw new WorkflowNotRegisteredException(workflowId, version); } var wf = new WorkflowInstance { WorkflowDefinitionId = workflowId, Version = def.Version, Data = data, Description = def.Description, NextExecution = 0, CreateTime = DateTime.Now.ToUniversalTime(), Status = WorkflowStatus.Runnable, Reference = reference }; if ((def.DataType != null) && (data == null)) { wf.Data = new TData(); } wf.ExecutionPointers.Add(_pointerFactory.BuildGenesisPointer(def)); string id = await _persistenceStore.CreateNewWorkflow(wf); await _queueProvider.QueueWork(id, QueueType.Workflow); await _eventHub.PublishNotification(new WorkflowStarted() { EventTimeUtc = DateTime.UtcNow, Reference = reference, WorkflowInstanceId = id, WorkflowDefinitionId = def.Id, Version = def.Version }); return(id); }
public async Task <string> StartWorkflow <TData>(string workflowId, int?version, TData data = null) where TData : class { var def = _registry.GetDefinition(workflowId, version); if (def == null) { throw new WorkflowNotRegisteredException(workflowId, version); } var wf = new WorkflowInstance { WorkflowDefinitionId = workflowId, Version = def.Version, Data = data, Description = def.Description, NextExecution = 0, CreateTime = DateTime.Now.ToUniversalTime(), Status = WorkflowStatus.Runnable }; if ((def.DataType != null) && (data == null)) { wf.Data = TypeExtensions.GetConstructor(def.DataType, new Type[] { }).Invoke(null); } wf.ExecutionPointers.Add(new ExecutionPointer { Id = Guid.NewGuid().ToString(), StepId = 0, Active = true, StepName = Enumerable.First <WorkflowStep>(def.Steps, x => x.Id == 0).Name }); string id = await _persistenceStore.CreateNewWorkflow(wf); await _queueProvider.QueueWork(id, QueueType.Workflow); return(id); }
public async Task <IActionResult> Post(string id, int?version, [FromBody] JObject data) { string workflowId = null; var def = _registry.GetDefinition(id, version); if (def == null) { return(BadRequest(String.Format("Workflow defintion {0} for version {1} not found", id, version))); } if ((data != null) && (def.DataType != null)) { var dataStr = JsonConvert.SerializeObject(data); var dataObj = JsonConvert.DeserializeObject(dataStr, def.DataType); workflowId = await _workflowHost.StartWorkflow(id, version, dataObj); } else { workflowId = await _workflowHost.StartWorkflow(id, version, null); } return(Ok(workflowId)); }
public async Task <WorkflowInstance> RunWorkflowSync <TData>(string workflowId, int version, TData data, string reference, CancellationToken token, bool persistSate = true) where TData : new() { var def = _registry.GetDefinition(workflowId, version); if (def == null) { throw new WorkflowNotRegisteredException(workflowId, version); } var wf = new WorkflowInstance { WorkflowDefinitionId = workflowId, Version = def.Version, Data = data, Description = def.Description, NextExecution = 0, CreateTime = _dateTimeProvider.UtcNow, Status = WorkflowStatus.Suspended, Reference = reference }; if ((def.DataType != null) && (data == null)) { if (typeof(TData) == def.DataType) { wf.Data = new TData(); } else { wf.Data = def.DataType.GetConstructor(new Type[0]).Invoke(new object[0]); } } wf.ExecutionPointers.Add(_pointerFactory.BuildGenesisPointer(def)); var id = Guid.NewGuid().ToString(); if (persistSate) { id = await _persistenceStore.CreateNewWorkflow(wf, token); } else { wf.Id = id; } wf.Status = WorkflowStatus.Runnable; if (!await _lockService.AcquireLock(id, CancellationToken.None)) { throw new InvalidOperationException(); } try { while ((wf.Status == WorkflowStatus.Runnable) && !token.IsCancellationRequested) { await _executor.Execute(wf, token); if (persistSate) { await _persistenceStore.PersistWorkflow(wf, token); } } } finally { await _lockService.ReleaseLock(id); } if (persistSate) { await _queueService.QueueWork(id, QueueType.Index); } return(wf); }
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); }
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); } _cancellationProcessor.ProcessCancellations(workflow, def, wfResult); foreach (var pointer in exePointers) { if (!pointer.Active) { 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 = $"Unable to find step {pointer.StepId} in workflow definition" }); continue; } try { if (!InitializeStep(workflow, step, wfResult, def, pointer)) { continue; } await ExecuteStep(workflow, step, pointer, wfResult, def); } 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); }
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); }
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); }
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); }
public virtual WorkflowDefinition GetDefinition(string workflowId, int?version = null) { return(_registry.GetDefinition(workflowId, version)); }