/// <inheritdoc/> public virtual async Task <IOperationResult <string> > HandleAsync(V1GetWorkflowInstanceLogsQuery query, CancellationToken cancellationToken = default) { var instance = await this.Repository.FindAsync(query.Id, cancellationToken); if (instance == null) { throw DomainException.NullReference(typeof(V1WorkflowInstance), query.Id); } if (instance.Sessions == null) { return(this.Ok(string.Empty)); } var processes = new List <Integration.Models.V1WorkflowProcess>(instance.Sessions.Count); foreach (var processId in instance.Sessions.Select(s => s.ProcessId)) { var process = await this.Processes.FindAsync(processId, cancellationToken); if (process == null) { throw DomainException.NullReference(typeof(V1WorkflowProcess), processId); } processes.Add(process); } return(this.Ok(processes.Select(p => p.Logs).Aggregate((l1, l2) => l1 += l2) !)); }
/// <inheritdoc/> public virtual async Task <IOperationResult <Integration.Models.V1WorkflowInstance> > HandleAsync(V1CorrelateWorkflowInstanceCommand command, CancellationToken cancellationToken = default) { var workflowInstance = await this.WorkflowInstances.FindAsync(command.Id, cancellationToken); if (workflowInstance == null) { throw DomainException.NullReference(typeof(V1WorkflowInstance), command.Id); } workflowInstance.SetCorrelationContext(command.CorrelationContext); workflowInstance = await this.WorkflowInstances.UpdateAsync(workflowInstance, cancellationToken); await this.WorkflowInstances.SaveChangesAsync(cancellationToken); switch (workflowInstance.Status) { case V1WorkflowInstanceStatus.Suspended: await this.Mediator.ExecuteAndUnwrapAsync(new V1StartWorkflowInstanceCommand(workflowInstance.Id), cancellationToken); break; case V1WorkflowInstanceStatus.Running: var runtimeProxy = this.RuntimeProxyManager.GetProxy(workflowInstance.Id); await runtimeProxy.CorrelateAsync(command.CorrelationContext, cancellationToken); break; default: throw DomainException.UnexpectedState(typeof(V1WorkflowInstance), workflowInstance.Id, workflowInstance.Status); } return(this.Ok(this.Mapper.Map <Integration.Models.V1WorkflowInstance>(workflowInstance))); }
/// <inheritdoc/> public virtual async Task <IOperationResult> HandleAsync(V1DeleteWorkflowCommand command, CancellationToken cancellationToken = default) { var components = command.WorkflowId.Split(":"); if (components.Length == 2) { var workflow = await this.WorkflowWriteModels.FindAsync(command.WorkflowId, cancellationToken); if (workflow == null) { throw DomainException.NullReference(typeof(V1Workflow), command.WorkflowId); } foreach (var instanceId in this.WorkflowInstances.AsQueryable() .Where(i => i.WorkflowId == workflow.Id) .Select(i => i.Id) .ToList()) { await this.Mediator.ExecuteAndUnwrapAsync(new V1DeleteWorkflowInstanceCommand(instanceId)); } workflow.Delete(); await this.WorkflowWriteModels.UpdateAsync(workflow, cancellationToken); await this.WorkflowWriteModels.RemoveAsync(workflow, cancellationToken); await this.WorkflowWriteModels.SaveChangesAsync(cancellationToken); } else { var workflowIds = this.WorkflowReadModels.AsQueryable() .Where(w => w.Definition.Id !.Equals(command.WorkflowId, StringComparison.OrdinalIgnoreCase)) .Select(w => w.Id) .ToList(); if (!workflowIds.Any()) { throw DomainException.NullReference(typeof(V1Workflow), command.WorkflowId); } foreach (var workflowId in workflowIds) { var workflow = await this.WorkflowWriteModels.FindAsync(workflowId, cancellationToken); if (workflow == null) { throw DomainException.NullReference(typeof(V1Workflow), workflowId); } workflow.Delete(); foreach (var instanceId in this.WorkflowInstances.AsQueryable() .Where(i => i.WorkflowId == workflow.Id) .Select(i => i.Id) .ToList()) { await this.Mediator.ExecuteAndUnwrapAsync(new V1DeleteWorkflowInstanceCommand(instanceId)); } await this.WorkflowWriteModels.UpdateAsync(workflow, cancellationToken); await this.WorkflowWriteModels.RemoveAsync(workflow, cancellationToken); } await this.WorkflowWriteModels.SaveChangesAsync(cancellationToken); } return(this.Ok()); }
/// <inheritdoc/> public virtual async Task <IOperationResult <Integration.Models.V1WorkflowActivity> > HandleAsync(V1CreateWorkflowActivityCommand command, CancellationToken cancellationToken = default) { var workflowInstance = await this.WorkflowInstances.FindAsync(command.WorkflowInstanceId, cancellationToken); if (workflowInstance == null) { throw DomainException.NullReference(typeof(V1WorkflowInstance), command.WorkflowInstanceId); } var parent = null as V1WorkflowActivity; if (!string.IsNullOrWhiteSpace(command.ParentId)) { parent = await this.WorkflowActivities.FindAsync(command.ParentId, cancellationToken); if (parent == null) { throw DomainException.NullReference(typeof(V1WorkflowActivity), command.ParentId); } } var activity = await this.WorkflowActivities.AddAsync(new(workflowInstance, command.Type, command.Input, command.Metadata, parent), cancellationToken); await this.WorkflowActivities.SaveChangesAsync(cancellationToken); return(this.Ok(this.Mapper.Map <Integration.Models.V1WorkflowActivity>(activity))); }
/// <inheritdoc/> public virtual async Task <IOperationResult <Integration.Models.V1Event?> > HandleAsync(V1ConsumeOrBeginCorrelateEventCommand command, CancellationToken cancellationToken = default) { var workflowInstance = await this.WorkflowInstances.FindAsync(command.WorkflowInstanceId, cancellationToken); if (workflowInstance == null) { throw DomainException.NullReference(typeof(V1WorkflowInstance), command.WorkflowInstanceId); } var e = workflowInstance.CorrelationContext.PendingEvents .FirstOrDefault(e => e.Matches(command.EventDefinition)); if (e == null) { var conditions = new List <V1CorrelationCondition>() { V1CorrelationCondition.Match(command.EventDefinition) }; var outcome = new V1CorrelationOutcome(V1CorrelationOutcomeType.Correlate, command.WorkflowInstanceId); await this.Mediator.ExecuteAndUnwrapAsync(new V1CreateCorrelationCommand(V1CorrelationLifetime.Singleton, V1CorrelationConditionType.AnyOf, conditions, outcome, workflowInstance.CorrelationContext), cancellationToken); } else { workflowInstance.CorrelationContext.RemoveEvent(e); await this.WorkflowInstances.UpdateAsync(workflowInstance, cancellationToken); await this.WorkflowInstances.SaveChangesAsync(cancellationToken); } return(this.Ok(e == null ? null : this.Mapper.Map <Integration.Models.V1Event>(e))); }
/// <inheritdoc/> public virtual async Task <IOperationResult <Integration.Models.V1WorkflowInstance> > HandleAsync(V1CancelWorkflowInstanceCommand command, CancellationToken cancellationToken = default) { var workflowInstance = await this.WorkflowInstances.FindAsync(command.WorkflowInstanceId, cancellationToken); if (workflowInstance == null) { throw DomainException.NullReference(typeof(V1WorkflowInstance), command.WorkflowInstanceId); } if (this.RuntimeHostManager.TryGetProxy(command.WorkflowInstanceId, out var proxy)) { workflowInstance.Cancel(); workflowInstance = await this.WorkflowInstances.UpdateAsync(workflowInstance, cancellationToken); await this.WorkflowInstances.SaveChangesAsync(cancellationToken); await proxy.CancelAsync(cancellationToken); } else { workflowInstance.Cancel(); workflowInstance.MarkAsCancelled(); workflowInstance = await this.WorkflowInstances.UpdateAsync(workflowInstance, cancellationToken); await this.WorkflowInstances.SaveChangesAsync(cancellationToken); } return(this.Ok(this.Mapper.Map <Integration.Models.V1WorkflowInstance>(workflowInstance))); }
/// <inheritdoc/> public virtual async Task <IOperationResult <bool> > HandleAsync(V1TryCorrelateWorkflowInstanceCommand command, CancellationToken cancellationToken = default) { var workflowInstance = await this.WorkflowInstances.FindAsync(command.WorkflowInstanceId, cancellationToken); if (workflowInstance == null) { throw DomainException.NullReference(typeof(V1WorkflowInstance), command.WorkflowInstanceId); } var e = workflowInstance.CorrelationContext.PendingEvents.FirstOrDefault(e => e.Id == command.Event.Id); if (e == null) { if (!workflowInstance.CorrelationContext.CorrelatesTo(command.Event)) { return(this.Ok(false)); } workflowInstance.CorrelationContext.Correlate(command.Event, command.MappingKeys); } else { workflowInstance.CorrelationContext.RemoveEvent(command.Event); } await this.WorkflowInstances.UpdateAsync(workflowInstance, cancellationToken); await this.WorkflowInstances.SaveChangesAsync(cancellationToken); return(this.Ok(true)); }
/// <inheritdoc/> public virtual async Task <IOperationResult <Stream> > HandleAsync(V1ArchiveWorkflowInstanceCommand command, CancellationToken cancellationToken = default) { var workflowInstance = await this.WorkflowInstances.FindAsync(command.Id, cancellationToken); if (workflowInstance == null) { throw DomainException.NullReference(typeof(V1WorkflowInstance), command.Id); } var workflow = await this.Workflows.FindAsync(workflowInstance.WorkflowId, cancellationToken); if (workflow == null) { throw DomainException.NullReference(typeof(V1Workflow), workflowInstance.WorkflowId); } var directory = new DirectoryInfo(Path.Combine(Path.GetTempPath(), workflowInstance.Id)); if (directory.Exists) { directory.Delete(true); } directory.Create(); var buffer = await this.Serializer.SerializeAsync(workflow.Definition, cancellationToken); await File.WriteAllBytesAsync(Path.Combine(directory.FullName, $"definition.{this.Options.Archiving.FileExtension}"), buffer, cancellationToken); buffer = await this.Serializer.SerializeAsync(this.Mapper.Map <Integration.Models.V1WorkflowInstance>(workflowInstance), cancellationToken); await File.WriteAllBytesAsync(Path.Combine(directory.FullName, $"instance.{this.Options.Archiving.FileExtension}"), buffer, cancellationToken); var processesDirectory = new DirectoryInfo(Path.Combine(directory.FullName, "processes")); if (!processesDirectory.Exists) { processesDirectory.Create(); } foreach (var processId in workflowInstance.Sessions.Select(s => s.ProcessId)) { var process = await this.WorkflowProcesses.FindAsync(processId, cancellationToken); if (process == null) { throw DomainException.NullReference(typeof(V1WorkflowProcess), processId); } buffer = await this.Serializer.SerializeAsync(this.Mapper.Map <Integration.Models.V1WorkflowProcess>(process), cancellationToken); await File.WriteAllBytesAsync(Path.Combine(processesDirectory.FullName, $"{processId}.{this.Options.Archiving.FileExtension}"), buffer, cancellationToken); } var archiveFilePath = Path.Combine(Path.GetTempPath(), $"{workflowInstance.Id}.zip"); ZipFile.CreateFromDirectory(directory.FullName, archiveFilePath, CompressionLevel.Fastest, true); using var fileStream = File.OpenRead(archiveFilePath); var stream = new MemoryStream(); await fileStream.CopyToAsync(stream); await stream.FlushAsync(cancellationToken); stream.Position = 0; return(this.Ok(stream)); }
/// <inheritdoc/> public virtual async Task <IOperationResult <TEntity> > HandleAsync(V1FindByIdQuery <TEntity, TKey> query, CancellationToken cancellationToken = default) { var entity = await this.Repository.FindAsync(query.Id, cancellationToken); if (entity == null) { throw DomainException.NullReference(typeof(TEntity), query.Id, nameof(query.Id)); } return(this.Ok(entity)); }
/// <inheritdoc/> public virtual async Task <IOperationResult <Integration.Models.V1WorkflowInstance> > HandleAsync(V1MarkWorkflowInstanceAsCancelledCommand command, CancellationToken cancellationToken = default) { var instance = await this.WorkflowInstances.FindAsync(command.Id, cancellationToken); if (instance == null) { throw DomainException.NullReference(typeof(V1WorkflowInstance), command.Id); } instance.MarkAsCancelled(); instance = await this.WorkflowInstances.UpdateAsync(instance, cancellationToken); await this.WorkflowInstances.SaveChangesAsync(cancellationToken); return(this.Ok(this.Mapper.Map <Integration.Models.V1WorkflowInstance>(instance))); }
/// <inheritdoc/> public virtual async Task <IOperationResult <Integration.Models.V1WorkflowInstance> > HandleAsync(V1SetWorkflowInstanceCorrelationMappingCommand command, CancellationToken cancellationToken = default) { var workflowInstance = await this.WorkflowInstances.FindAsync(command.Id, cancellationToken); if (workflowInstance == null) { throw DomainException.NullReference(typeof(V1WorkflowInstance), command.Id); } workflowInstance.SetCorrelationMapping(command.Key, command.Value); workflowInstance = await this.WorkflowInstances.UpdateAsync(workflowInstance, cancellationToken); await this.WorkflowInstances.SaveChangesAsync(cancellationToken); return(this.Ok(this.Mapper.Map <Integration.Models.V1WorkflowInstance>(workflowInstance))); }
/// <inheritdoc/> public virtual async Task <IOperationResult <Integration.Models.V1WorkflowActivity> > HandleAsync(V1CancelWorkflowActivityCommand command, CancellationToken cancellationToken = default) { var activity = await this.Activities.FindAsync(command.Id, cancellationToken); if (activity == null) { throw DomainException.NullReference(typeof(V1WorkflowActivity), command.Id); } activity.Cancel(); activity = await this.Activities.UpdateAsync(activity, cancellationToken); await this.Activities.SaveChangesAsync(cancellationToken); return(this.Ok(this.Mapper.Map <Integration.Models.V1WorkflowActivity>(activity))); }
/// <inheritdoc/> public virtual async Task <IOperationResult> HandleAsync(V1DeleteCorrelationCommand command, CancellationToken cancellationToken = default) { var correlation = await this.Correlations.FindAsync(command.Id, cancellationToken); if (correlation == null) { throw DomainException.NullReference(typeof(V1Correlation), command.Id); } correlation.Delete(); await this.Correlations.UpdateAsync(correlation, cancellationToken); await this.Correlations.RemoveAsync(correlation, cancellationToken); await this.Correlations.SaveChangesAsync(cancellationToken); return(this.Ok()); }
/// <inheritdoc/> public virtual async Task <IOperationResult <Integration.Models.V1WorkflowInstance> > HandleAsync(V1ResumeWorkflowInstanceCommand command, CancellationToken cancellationToken = default) { var workflowInstance = await this.WorkflowInstances.FindAsync(command.WorkflowInstanceId, cancellationToken); if (workflowInstance == null) { throw DomainException.NullReference(typeof(V1WorkflowInstance), command.WorkflowInstanceId); } var process = await this.ProcessManager.StartProcessAsync(workflowInstance, cancellationToken); workflowInstance.Resume(process.Id); workflowInstance = await this.WorkflowInstances.UpdateAsync(workflowInstance, cancellationToken); await this.WorkflowInstances.SaveChangesAsync(cancellationToken); return(this.Ok(this.Mapper.Map <Integration.Models.V1WorkflowInstance>(workflowInstance))); }
/// <inheritdoc/> public virtual async Task <IOperationResult <Dynamic> > HandleAsync(V1GetActivityParentStateDataQuery query, CancellationToken cancellationToken = default) { var activity = await this.Repository.FindAsync(query.ActivityId, cancellationToken); if (activity == null) { throw DomainException.NullReference(typeof(V1WorkflowActivity), query.ActivityId); } while (activity != null) { if (activity.Type == V1WorkflowActivityType.State) { return(this.Ok(activity.Input)); } activity = await this.Repository.FindAsync(activity.ParentId, cancellationToken); } return(this.Ok()); }
/// <inheritdoc/> public virtual async Task <IOperationResult> HandleAsync(V1ScheduleWorkflowCommand command, CancellationToken cancellationToken = default) { var workflow = await this.Workflows.FindAsync(command.WorkflowId, cancellationToken); if (workflow == null) { throw DomainException.NullReference(typeof(V1Workflow), command.WorkflowId); } var rawCronExpression = workflow.Definition.Start !.Schedule !.CronExpression; if (workflow.Definition.Start.Schedule.Cron == null) { throw new DomainException($"The schedule's '{nameof(ScheduleDefinition.CronExpression)}' or '{nameof(ScheduleDefinition.Cron)}' property of the specified workflow must be set in order to be scheduled"); } if (string.IsNullOrWhiteSpace(rawCronExpression)) { rawCronExpression = workflow.Definition.Start !.Schedule !.Cron.Expression; } var cronExpression = CronExpression.Parse(rawCronExpression); var timeZone = TimeZoneInfo.Local; if (!string.IsNullOrWhiteSpace(workflow.Definition.Start.Schedule.Timezone)) { timeZone = TimeZoneInfo.FindSystemTimeZoneById(workflow.Definition.Start.Schedule.Timezone); } Func <IServiceProvider, Task> job = async provider => { var mediator = provider.GetRequiredService <IMediator>(); await mediator.ExecuteAndUnwrapAsync(new V1CreateWorkflowInstanceCommand(workflow.Id, V1WorkflowInstanceActivationType.Cron, new(), null, true, null)); }; if (command.CatchUpMissedOccurences && workflow.LastInstanciated.HasValue) { foreach (var occurence in cronExpression.GetOccurrences(workflow.LastInstanciated.Value.DateTime, DateTime.Now, timeZone)) { await this.Mediator.ExecuteAndUnwrapAsync(new V1CreateWorkflowInstanceCommand(workflow.Id, V1WorkflowInstanceActivationType.Cron, new(), null, true, null), cancellationToken); } } await this.CronJobScheduler.ScheduleJobAsync(workflow.Definition.Id !, cronExpression, timeZone, job, workflow.Definition.Start.Schedule.Cron?.ValidUntil, cancellationToken); return(this.Ok()); }
/// <inheritdoc/> public virtual async Task <IOperationResult> HandleAsync(V1DeleteCommand <TAggregate, TKey> command, CancellationToken cancellationToken = default) { if (!await this.Repository.ContainsAsync(command.Id, cancellationToken)) { throw DomainException.NullReference(typeof(TAggregate), command.Id); } var aggregate = await this.Repository.FindAsync(command.Id, cancellationToken); if (aggregate == null) { throw DomainException.NullReference(typeof(TAggregate), command.Id); } aggregate.Delete(); await this.Repository.UpdateAsync(aggregate, cancellationToken); await this.Repository.RemoveAsync(aggregate, cancellationToken); await this.Repository.SaveChangesAsync(cancellationToken); return(this.Ok()); }
/// <inheritdoc/> public virtual async Task <IOperationResult <Integration.Models.V1Workflow> > HandleAsync(V1GetWorkflowByIdQuery query, CancellationToken cancellationToken = default) { Integration.Models.V1Workflow?workflow; if (string.IsNullOrWhiteSpace(query.Version) || query.Version == "latest") { workflow = this.Repository.AsQueryable() .Where(wf => wf.Definition.Id !.Equals(query.Id, StringComparison.OrdinalIgnoreCase)) .OrderByDescending(wf => wf.Definition.Version) .FirstOrDefault() !; } else { workflow = await this.Repository.FindAsync($"{query.Id}:{query.Version}", cancellationToken); } if (workflow == null) { throw DomainException.NullReference(typeof(V1Workflow), query.Id); } return(this.Ok(workflow)); }
/// <inheritdoc/> public virtual async Task <IOperationResult> HandleAsync(V1DeleteWorkflowInstanceCommand command, CancellationToken cancellationToken = default) { var workflowInstance = await this.WorkflowInstances.FindAsync(command.WorkflowInstanceId, cancellationToken); if (workflowInstance == null) { throw DomainException.NullReference(typeof(V1WorkflowInstance), command.WorkflowInstanceId); } if (this.RuntimeProxyManager.TryGetProxy(command.WorkflowInstanceId, out var proxy)) { await proxy.CancelAsync(cancellationToken); this.RuntimeProxyManager.Unregister(proxy); } workflowInstance.Delete(); await this.WorkflowInstances.UpdateAsync(workflowInstance, cancellationToken); await this.WorkflowInstances.RemoveAsync(workflowInstance, cancellationToken); await this.WorkflowInstances.SaveChangesAsync(cancellationToken); return(this.Ok()); }
/// <inheritdoc/> public virtual async Task <IOperationResult <Integration.Models.V1Workflow> > HandleAsync(V1CreateWorkflowCommand command, CancellationToken cancellationToken = default) { var validationResult = await this.WorkflowValidator.ValidateAsync(command.Definition, true, true, cancellationToken); if (!validationResult.IsValid) { return(this.Invalid(validationResult.AsErrors().ToArray())); } foreach (var subflowRef in command.Definition.GetSubflowReferences()) { var reference = subflowRef.WorkflowId; if (!string.IsNullOrWhiteSpace(subflowRef.Version)) { reference += $":{subflowRef.Version}"; } var subflow = await this.Mediator.ExecuteAndUnwrapAsync(new V1GetWorkflowByIdQuery(subflowRef.WorkflowId, subflowRef.Version), cancellationToken); if (subflow == null) { throw DomainException.NullReference(typeof(V1Workflow), $"Failed to find the referenced workflow '{reference}'"); } } if (command.IfNotExists && await this.Workflows.ContainsAsync(command.Definition.GetUniqueIdentifier(), cancellationToken)) { return(this.NotModified()); } else { while (await this.Workflows.ContainsAsync(command.Definition.GetUniqueIdentifier(), cancellationToken)) { var version = Version.Parse(command.Definition.Version); version = new Version(version.Major, version.Minor, version.Build == -1 ? 1 : version.Build + 1); command.Definition.Version = version.ToString(3); } } var workflow = await this.Workflows.AddAsync(new(command.Definition), cancellationToken); await this.Workflows.SaveChangesAsync(cancellationToken); var startState = workflow.Definition.GetStartState(); if (startState is EventStateDefinition eventState) { var lifetime = V1CorrelationLifetime.Transient; var conditionType = eventState.Exclusive ? V1CorrelationConditionType.AnyOf : V1CorrelationConditionType.AllOf; var conditions = new List <V1CorrelationCondition>(); foreach (var trigger in eventState.Triggers) { var filters = new List <V1EventFilter>(trigger.Events.Count); foreach (var eventRef in trigger.Events) { if (!workflow.Definition.TryGetEvent(eventRef, out var e)) { throw DomainException.NullReference(typeof(EventDefinition), eventRef, nameof(EventDefinition.Name)); } filters.Add(V1EventFilter.Match(e)); } conditions.Add(new(filters.ToArray())); } var outcome = new V1CorrelationOutcome(V1CorrelationOutcomeType.Start, workflow.Id); await this.Mediator.ExecuteAndUnwrapAsync(new V1CreateCorrelationCommand(lifetime, conditionType, conditions, outcome, null)); } else if (!string.IsNullOrWhiteSpace(workflow.Definition.Start?.Schedule?.Cron?.Expression)) { await this.Mediator.ExecuteAndUnwrapAsync(new V1ScheduleWorkflowCommand(workflow.Id, false), cancellationToken); } return(this.Ok(this.Mapper.Map <Integration.Models.V1Workflow>(workflow))); }
/// <inheritdoc/> public virtual async Task <IOperationResult <Integration.Models.V1WorkflowInstance> > HandleAsync(V1CreateWorkflowInstanceCommand command, CancellationToken cancellationToken = default) { var workflow = await this.Workflows.FindAsync(command.WorkflowId, cancellationToken); if (workflow == null) { throw DomainException.NullReference(typeof(V1Workflow), command.WorkflowId); } var parent = null as V1WorkflowInstance; if (!string.IsNullOrWhiteSpace(command.ParentId)) { parent = await this.WorkflowInstances.FindAsync(command.ParentId, cancellationToken); if (parent == null) { throw DomainException.NullReference(typeof(V1WorkflowInstance), command.ParentId); } } string?key = null; var dataInputSchema = workflow.Definition.DataInputSchema?.Schema; if (dataInputSchema == null && workflow.Definition.DataInputSchemaUri != null) { using var httpClient = this.HttpClientFactory.CreateClient(); var json = await httpClient.GetStringAsync(workflow.Definition.DataInputSchemaUri, cancellationToken); dataInputSchema = JSchema.Parse(json); } if (dataInputSchema != null) { var input = command.InputData; JObject?jobj; if (input == null) { jobj = new JObject(); } else { jobj = JObject.FromObject(input); } if (!jobj.IsValid(dataInputSchema, out IList <string> errors)) { throw new DomainArgumentException($"Invalid workflow input data:{Environment.NewLine}{string.Join(Environment.NewLine, errors)}", nameof(command.InputData)); } } if (!string.IsNullOrWhiteSpace(workflow.Definition.Key) && command.InputData != null) { try { key = this.ExpressionEvaluatorProvider.GetEvaluator(workflow.Definition.ExpressionLanguage) !.Evaluate(workflow.Definition.Key, command.InputData)?.ToString(); } catch { } } if (string.IsNullOrWhiteSpace(key)) { key = Guid.NewGuid().ToBase64(); } while (await this.WorkflowInstances.ContainsAsync(V1WorkflowInstance.BuildUniqueIdentifier(key, workflow), cancellationToken)) { key = Guid.NewGuid().ToBase64(); } var workflowInstance = await this.WorkflowInstances.AddAsync(new(key.ToLowerInvariant(), workflow, command.ActivationType, command.InputData, command.CorrelationContext, parent), cancellationToken); await this.WorkflowInstances.SaveChangesAsync(cancellationToken); workflow.Instanciate(); await this.Workflows.UpdateAsync(workflow, cancellationToken); await this.Workflows.SaveChangesAsync(cancellationToken); if (command.AutoStart) { await this.Mediator.ExecuteAndUnwrapAsync(new V1StartWorkflowInstanceCommand(workflowInstance.Id), cancellationToken); } return(this.Ok(this.Mapper.Map <Integration.Models.V1WorkflowInstance>(workflowInstance))); }