Fix solution build
This commit is contained in:
parent
ab7fd8c366
commit
bbf0cfa8f8
|
|
@ -6,3 +6,7 @@ insert_final_newline=false
|
|||
indent_style=space
|
||||
indent_size=4
|
||||
|
||||
# ReSharper properties
|
||||
resharper_csharp_max_line_length=240
|
||||
resharper_keep_user_linebreaks=true
|
||||
|
||||
|
|
|
|||
|
|
@ -80,8 +80,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Samples.CustomActiviti
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Samples.TimesheetApproval", "src\samples\Elsa.Samples.TimesheetApproval\Elsa.Samples.TimesheetApproval.csproj", "{1678743A-9095-4683-8DCD-5763F41924E2}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Samples.WorkflowDefinition", "src\samples\Elsa.Samples.WorkflowDefinition\Elsa.Samples.WorkflowDefinition.csproj", "{7AC91435-7D10-4353-9064-598A6F8EAED6}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.DistributedLocking.Redis", "src\providers\Elsa.DistributedLocking.Redis\Elsa.DistributedLocking.Redis.csproj", "{EBD49CCA-5400-4C36-B5DF-7B28190AA323}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Samples.DistributedLock", "src\samples\Elsa.Samples.DistributedLock\Elsa.Samples.DistributedLock.csproj", "{4D162E3C-0962-43B9-B193-6E806249F81B}"
|
||||
|
|
@ -194,10 +192,6 @@ Global
|
|||
{1678743A-9095-4683-8DCD-5763F41924E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1678743A-9095-4683-8DCD-5763F41924E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1678743A-9095-4683-8DCD-5763F41924E2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7AC91435-7D10-4353-9064-598A6F8EAED6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7AC91435-7D10-4353-9064-598A6F8EAED6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7AC91435-7D10-4353-9064-598A6F8EAED6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7AC91435-7D10-4353-9064-598A6F8EAED6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EBD49CCA-5400-4C36-B5DF-7B28190AA323}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EBD49CCA-5400-4C36-B5DF-7B28190AA323}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EBD49CCA-5400-4C36-B5DF-7B28190AA323}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
|
@ -250,7 +244,6 @@ Global
|
|||
{A11D79AE-F4C9-4595-9B73-0E0AB221B90D} = {5E5E1E84-DDBC-40D6-B891-0D563A15A44A}
|
||||
{554C21D7-10BE-48E6-B0EF-9FCA43B32A0F} = {5E5E1E84-DDBC-40D6-B891-0D563A15A44A}
|
||||
{1678743A-9095-4683-8DCD-5763F41924E2} = {5E5E1E84-DDBC-40D6-B891-0D563A15A44A}
|
||||
{7AC91435-7D10-4353-9064-598A6F8EAED6} = {5E5E1E84-DDBC-40D6-B891-0D563A15A44A}
|
||||
{4D162E3C-0962-43B9-B193-6E806249F81B} = {5E5E1E84-DDBC-40D6-B891-0D563A15A44A}
|
||||
{7CD5C8D5-EC78-4A99-A514-F01CA7197AC8} = {DA71CDAA-8DD3-4D5F-9FBD-8E4B37A2D925}
|
||||
{E20238CE-5C64-4F87-8753-3B4E1EC9A740} = {7CD5C8D5-EC78-4A99-A514-F01CA7197AC8}
|
||||
|
|
|
|||
|
|
@ -1,2 +1,4 @@
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/KEEP_USER_LINEBREAKS/@EntryValue">False</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/WRAP_LINES/@EntryValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=EF/@EntryIndexedValue">EF</s:String></wpf:ResourceDictionary>
|
||||
|
|
@ -30,11 +30,11 @@ namespace Elsa.Builders
|
|||
where T : class, IActivity;
|
||||
|
||||
IActivityBuilder New<T>(
|
||||
Action<ISetupActivity<T>>? setup = default,
|
||||
Action<ISetupActivity<T>>? setup,
|
||||
Action<IActivityBuilder>? branch = default) where T : class, IActivity;
|
||||
|
||||
IActivityBuilder StartWith<T>(
|
||||
Action<ISetupActivity<T>>? setup = default,
|
||||
Action<ISetupActivity<T>>? setup,
|
||||
Action<IActivityBuilder>? branch = default) where T : class, IActivity;
|
||||
|
||||
IActivityBuilder StartWith<T>(Action<IActivityBuilder>? branch = default)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace Elsa.Services
|
|||
{
|
||||
public abstract class Activity : IActivity
|
||||
{
|
||||
public virtual string Type => GetType().Name;
|
||||
public string Type => GetType().Name;
|
||||
public string Id { get; set; } = default!;
|
||||
public string? Name { get; set; }
|
||||
public string? DisplayName { get; set; }
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace Elsa.Services
|
|||
/// <summary>
|
||||
/// The type name of this activity.
|
||||
/// </summary>
|
||||
string Type { get; set; }
|
||||
string Type { get;}
|
||||
|
||||
/// <summary>
|
||||
/// Unique identifier of this activity within the workflow.
|
||||
|
|
|
|||
|
|
@ -10,6 +10,6 @@ namespace Elsa.Services
|
|||
/// </summary>
|
||||
public interface IWorkflowProvider
|
||||
{
|
||||
Task<IEnumerable<WorkflowBlueprint>> GetWorkflowsAsync(CancellationToken cancellationToken);
|
||||
Task<IEnumerable<IWorkflowBlueprint>> GetWorkflowsAsync(CancellationToken cancellationToken);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ namespace Elsa.Services
|
|||
{
|
||||
public interface IWorkflowSchedulerQueue
|
||||
{
|
||||
void Enqueue(WorkflowBlueprint workflowBlueprint, IActivity activity, object? input, string? correlationId);
|
||||
(WorkflowBlueprint Workflow, IActivity Activity, object? Input, string? CorrelationId)? Dequeue(string workflowDefinitionId, string activityId);
|
||||
void Enqueue(IWorkflowBlueprint workflowBlueprint, IActivityBlueprint activity, object? input, string? correlationId);
|
||||
(IWorkflowBlueprint Workflow, IActivityBlueprint Activity, object? Input, string? CorrelationId)? Dequeue(string workflowDefinitionId, string activityId);
|
||||
}
|
||||
}
|
||||
|
|
@ -11,23 +11,19 @@ namespace Elsa.Services.Models
|
|||
{
|
||||
}
|
||||
|
||||
public ActivityBlueprint(
|
||||
Func<ActivityExecutionContext, CancellationToken, ValueTask<IActivity>> createActivity) =>
|
||||
CreateActivityAsync = createActivity;
|
||||
public ActivityBlueprint(Func<ActivityExecutionContext, CancellationToken, ValueTask<IActivity>> createActivity) => CreateActivityAsync = createActivity;
|
||||
|
||||
public ActivityBlueprint(
|
||||
string id,
|
||||
Func<ActivityExecutionContext, CancellationToken, ValueTask<IActivity>> createActivity)
|
||||
public ActivityBlueprint(string id, Func<ActivityExecutionContext, CancellationToken, ValueTask<IActivity>> createActivity)
|
||||
{
|
||||
Id = id;
|
||||
CreateActivityAsync = createActivity;
|
||||
}
|
||||
|
||||
public string Id { get; set; } = default!;
|
||||
public string? Name { get; set; }
|
||||
public string Type { get; set; } = default!;
|
||||
public bool PersistWorkflow { get; set; }
|
||||
public JObject Data { get; set; } = new JObject();
|
||||
|
||||
public Func<ActivityExecutionContext, CancellationToken, ValueTask<IActivity>> CreateActivityAsync { get; set; }
|
||||
= default!;
|
||||
public Func<ActivityExecutionContext, CancellationToken, ValueTask<IActivity>> CreateActivityAsync { get; set; } = default!;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,13 +4,13 @@ namespace Elsa.Services.Models
|
|||
{
|
||||
public class ExecutionLogEntry : IExecutionLogEntry
|
||||
{
|
||||
public ExecutionLogEntry(IActivity activity, Instant timestamp)
|
||||
public ExecutionLogEntry(string activityId, Instant timestamp)
|
||||
{
|
||||
Activity = activity;
|
||||
ActivityId = activityId;
|
||||
Timestamp = timestamp;
|
||||
}
|
||||
|
||||
public IActivity Activity { get; }
|
||||
public string ActivityId { get; }
|
||||
public Instant Timestamp { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -8,7 +8,9 @@ namespace Elsa.Services.Models
|
|||
public interface IActivityBlueprint
|
||||
{
|
||||
public string Id { get; }
|
||||
string? Name { get; }
|
||||
public string Type { get; }
|
||||
public bool PersistWorkflow { get; }
|
||||
public JObject Data { get; }
|
||||
Func<ActivityExecutionContext, CancellationToken, ValueTask<IActivity>> CreateActivityAsync { get; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ namespace Elsa.Services.Models
|
|||
{
|
||||
public interface IExecutionLogEntry
|
||||
{
|
||||
IActivity Activity { get; }
|
||||
string ActivityId { get; }
|
||||
Instant Timestamp { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -49,12 +49,17 @@ namespace Elsa.Services.Models
|
|||
new ScheduledActivity(scheduledActivityModel.ActivityId, scheduledActivityModel.Input);
|
||||
|
||||
public IWorkflowBlueprint WorkflowBlueprint { get; }
|
||||
|
||||
public IServiceProvider ServiceProvider { get; }
|
||||
|
||||
// public WorkflowDefinition WorkflowDefinition { get; }
|
||||
public WorkflowInstance WorkflowInstance { get; }
|
||||
public WorkflowStatus Status { get; set; }
|
||||
public Stack<IScheduledActivity> ScheduledActivities { get; }
|
||||
public HashSet<BlockingActivity> BlockingActivities { get; } = new HashSet<BlockingActivity>(new BlockingActivityEqualityComparer());
|
||||
|
||||
public HashSet<BlockingActivity> BlockingActivities { get; } =
|
||||
new HashSet<BlockingActivity>(new BlockingActivityEqualityComparer());
|
||||
|
||||
public Variables Variables { get; }
|
||||
public bool HasScheduledActivities => ScheduledActivities.Any();
|
||||
public IScheduledActivity? ScheduledActivity { get; private set; }
|
||||
|
|
@ -87,7 +92,9 @@ namespace Elsa.Services.Models
|
|||
public ICollection<IExecutionLogEntry> ExecutionLog { get; }
|
||||
public bool IsFirstPass { get; private set; }
|
||||
|
||||
public bool AddBlockingActivity(IActivity activity) => BlockingActivities.Add(new BlockingActivity(activity.Id, activity.Type));
|
||||
public bool AddBlockingActivity(IActivity activity) =>
|
||||
BlockingActivities.Add(new BlockingActivity(activity.Id, activity.Type));
|
||||
|
||||
public void SetVariable(string name, object? value) => Variables.Set(name, JToken.FromObject(value!));
|
||||
public T GetVariable<T>(string name) => (T)GetVariable(name)!;
|
||||
public object? GetVariable(string name) => Variables.Get(name);
|
||||
|
|
@ -103,10 +110,12 @@ namespace Elsa.Services.Models
|
|||
|
||||
public void Complete() => Status = WorkflowStatus.Completed;
|
||||
|
||||
public IActivityBlueprint? GetActivity(string id) => WorkflowBlueprint.Activities.FirstOrDefault(x => x.Id == id);
|
||||
public IActivityBlueprint? GetActivity(string id) =>
|
||||
WorkflowBlueprint.Activities.FirstOrDefault(x => x.Id == id);
|
||||
|
||||
public void UpdateWorkflowInstance(WorkflowInstance workflowInstance)
|
||||
public WorkflowInstance UpdateWorkflowInstance()
|
||||
{
|
||||
var workflowInstance = WorkflowInstance;
|
||||
workflowInstance.Variables = Variables;
|
||||
|
||||
workflowInstance.ScheduledActivities = new Stack<Elsa.Models.ScheduledActivity>(
|
||||
|
|
@ -121,7 +130,7 @@ namespace Elsa.Services.Models
|
|||
workflowInstance.Output = Output;
|
||||
|
||||
var executionLog = workflowInstance.ExecutionLog.Concat(
|
||||
ExecutionLog.Select(x => new Elsa.Models.ExecutionLogEntry(x.Activity.Id, x.Timestamp)));
|
||||
ExecutionLog.Select(x => new Elsa.Models.ExecutionLogEntry(x.ActivityId, x.Timestamp)));
|
||||
|
||||
workflowInstance.ExecutionLog = executionLog.ToList();
|
||||
|
||||
|
|
@ -133,6 +142,8 @@ namespace Elsa.Services.Models
|
|||
Message = WorkflowFault.Message
|
||||
};
|
||||
}
|
||||
|
||||
return workflowInstance;
|
||||
}
|
||||
|
||||
private JObject Serialize(IActivity activity) => JObject.FromObject(activity);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace Elsa.Data.Services
|
|||
_activityActivator = activityActivator;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<WorkflowBlueprint>> GetWorkflowsAsync(CancellationToken cancellationToken)
|
||||
public async Task<IEnumerable<IWorkflowBlueprint>> GetWorkflowsAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
var workflowDefinitions = await _workflowDefinitionManager.ListAsync(cancellationToken);
|
||||
return workflowDefinitions.Select(CreateWorkflow);
|
||||
|
|
@ -87,7 +87,6 @@ namespace Elsa.Data.Services
|
|||
activity.Description = activityDefinition.Description;
|
||||
activity.Id = activityDefinition.Id;
|
||||
activity.Name = activityDefinition.Name;
|
||||
activity.Type = activityDefinition.Type;
|
||||
activity.DisplayName = activityDefinition.DisplayName;
|
||||
activity.PersistWorkflow = activityDefinition.PersistWorkflow;
|
||||
|
||||
|
|
|
|||
|
|
@ -53,8 +53,10 @@ namespace Elsa.Messaging.Domain.Handlers
|
|||
{
|
||||
_logger.LogDebug(
|
||||
"Deleting completed workflow instance {WorkflowInstanceId}",
|
||||
workflowExecutionContext.WorkflowInstanceId);
|
||||
await _workflowInstanceManager.DeleteAsync(workflowExecutionContext.WorkflowInstance, cancellationToken);
|
||||
workflowExecutionContext.WorkflowInstance.WorkflowInstanceId);
|
||||
await _workflowInstanceManager.DeleteAsync(
|
||||
workflowExecutionContext.WorkflowInstance,
|
||||
cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -62,7 +64,9 @@ namespace Elsa.Messaging.Domain.Handlers
|
|||
}
|
||||
}
|
||||
|
||||
private async ValueTask SaveWorkflowAsync(WorkflowExecutionContext workflowExecutionContext, CancellationToken cancellationToken)
|
||||
private async ValueTask SaveWorkflowAsync(
|
||||
WorkflowExecutionContext workflowExecutionContext,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var workflowInstance = workflowExecutionContext.UpdateWorkflowInstance();
|
||||
await _workflowInstanceManager.SaveAsync(workflowInstance, cancellationToken);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@ namespace Elsa.Messaging.Domain.Handlers
|
|||
|
||||
public Task Handle(ActivityExecuted notification, CancellationToken cancellationToken)
|
||||
{
|
||||
notification.WorkflowExecutionContext.ExecutionLog.Add(new ExecutionLogEntry(notification.Activity, _clock.GetCurrentInstant()));
|
||||
notification.WorkflowExecutionContext.ExecutionLog.Add(
|
||||
new ExecutionLogEntry(notification.Activity.Id, _clock.GetCurrentInstant()));
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,12 +68,7 @@ namespace Elsa.Services
|
|||
correlationId,
|
||||
cancellationToken);
|
||||
|
||||
return await RunWorkflowAsync(
|
||||
workflowBlueprint,
|
||||
workflowInstance,
|
||||
activityId,
|
||||
input,
|
||||
cancellationToken);
|
||||
return await RunWorkflowAsync(workflowBlueprint, workflowInstance, activityId, input, cancellationToken);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -89,8 +84,7 @@ namespace Elsa.Services
|
|||
cancellationToken);
|
||||
|
||||
if (workflowBlueprint == null)
|
||||
throw new WorkflowException(
|
||||
$"Workflow instance {workflowInstance.Id} references workflow definition {workflowInstance.WorkflowDefinitionId} version {workflowInstance.Version}, but no such workflow definition was found.");
|
||||
throw new WorkflowException($"Workflow instance {workflowInstance.Id} references workflow definition {workflowInstance.WorkflowDefinitionId} version {workflowInstance.Version}, but no such workflow definition was found.");
|
||||
|
||||
return await RunWorkflowAsync(workflowBlueprint, workflowInstance, activityId, input, cancellationToken);
|
||||
}
|
||||
|
|
@ -147,8 +141,7 @@ namespace Elsa.Services
|
|||
if (statusEvent != null)
|
||||
await _mediator.Publish(statusEvent, cancellationToken);
|
||||
|
||||
workflowExecutionContext.UpdateWorkflowInstance(workflowInstance);
|
||||
return workflowInstance;
|
||||
return workflowExecutionContext.UpdateWorkflowInstance();
|
||||
}
|
||||
|
||||
private async Task BeginWorkflow(
|
||||
|
|
@ -204,7 +197,7 @@ namespace Elsa.Services
|
|||
activityBlueprint,
|
||||
input);
|
||||
|
||||
var activity = await activityBlueprint.CreateActivityAsync();
|
||||
var activity = await activityBlueprint.CreateActivityAsync(activityExecutionContext, cancellationToken);
|
||||
return await activity.CanExecuteAsync(activityExecutionContext, cancellationToken);
|
||||
}
|
||||
|
||||
|
|
@ -227,8 +220,7 @@ namespace Elsa.Services
|
|||
activityBlueprint,
|
||||
scheduledActivity.Input);
|
||||
|
||||
var activity = await activityBlueprint.CreateActivityAsync();
|
||||
|
||||
var activity = await activityBlueprint.CreateActivityAsync(activityExecutionContext, cancellationToken);
|
||||
var result = await activityOperation(activityExecutionContext, activity, cancellationToken);
|
||||
await _mediator.Publish(new ActivityExecuting(activityExecutionContext), cancellationToken);
|
||||
await result.ExecuteAsync(activityExecutionContext, cancellationToken);
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@ namespace Elsa.Services
|
|||
_queue = queue;
|
||||
}
|
||||
|
||||
public async Task ScheduleWorkflowAsync(string instanceId,
|
||||
public async Task ScheduleWorkflowAsync(
|
||||
string instanceId,
|
||||
string? activityId = default,
|
||||
object? input = default,
|
||||
CancellationToken cancellationToken = default) =>
|
||||
|
|
@ -57,7 +58,7 @@ namespace Elsa.Services
|
|||
VersionOptions.Published,
|
||||
cancellationToken);
|
||||
|
||||
if(workflow == null)
|
||||
if (workflow == null)
|
||||
throw new WorkflowException($"No workflow definition found by ID {definitionId}");
|
||||
|
||||
var startActivities = workflow.GetStartActivities();
|
||||
|
|
@ -103,7 +104,7 @@ namespace Elsa.Services
|
|||
where activity.Type == activityType
|
||||
select (workflow, activity);
|
||||
|
||||
var tuples = (IList<(WorkflowBlueprint Workflow, IActivity Activity)>)query.ToList();
|
||||
var tuples = (IList<(IWorkflowBlueprint Workflow, IActivityBlueprint Activity)>)query.ToList();
|
||||
|
||||
tuples = await FilterRunningSingletonsAsync(tuples).ToList();
|
||||
|
||||
|
|
@ -164,8 +165,9 @@ namespace Elsa.Services
|
|||
cancellationToken);
|
||||
}
|
||||
|
||||
private async Task ScheduleWorkflowAsync(WorkflowBlueprint workflowBlueprint,
|
||||
IActivity activity,
|
||||
private async Task ScheduleWorkflowAsync(
|
||||
IWorkflowBlueprint workflowBlueprint,
|
||||
IActivityBlueprint activity,
|
||||
object? input,
|
||||
string? correlationId,
|
||||
CancellationToken cancellationToken)
|
||||
|
|
@ -175,8 +177,7 @@ namespace Elsa.Services
|
|||
await ScheduleWorkflowAsync(workflowInstance.WorkflowInstanceId, activity.Id, input, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<(WorkflowBlueprint, IActivity)>> FilterRunningSingletonsAsync(
|
||||
IEnumerable<(WorkflowBlueprint Workflow, IActivity Activity)> tuples)
|
||||
private async Task<IEnumerable<(IWorkflowBlueprint, IActivityBlueprint)>> FilterRunningSingletonsAsync(IEnumerable<(IWorkflowBlueprint Workflow, IActivityBlueprint Activity)> tuples)
|
||||
{
|
||||
var tupleList = tuples.ToList();
|
||||
var transients = tupleList.Where(x => !x.Workflow.IsSingleton).ToList();
|
||||
|
|
@ -197,7 +198,7 @@ namespace Elsa.Services
|
|||
return result;
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<WorkflowInstance>> GetStartedWorkflowsAsync(WorkflowBlueprint workflowBlueprint)
|
||||
private async Task<IEnumerable<WorkflowInstance>> GetStartedWorkflowsAsync(IWorkflowBlueprint workflowBlueprint)
|
||||
{
|
||||
var workflowDefinitionId = workflowBlueprint.Id;
|
||||
|
||||
|
|
@ -218,8 +219,8 @@ namespace Elsa.Services
|
|||
public async Task Handle(WorkflowCompleted notification, CancellationToken cancellationToken)
|
||||
{
|
||||
var workflowExecutionContext = notification.WorkflowExecutionContext;
|
||||
var workflowDefinitionId = workflowExecutionContext.WorkflowDefinitionId;
|
||||
var startActivityId = workflowExecutionContext.ExecutionLog.Select(x => x.Activity.Id).FirstOrDefault();
|
||||
var workflowDefinitionId = workflowExecutionContext.WorkflowBlueprint.Id;
|
||||
var startActivityId = workflowExecutionContext.ExecutionLog.Select(x => x.ActivityId).FirstOrDefault();
|
||||
|
||||
if (startActivityId == null)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -5,15 +5,15 @@ namespace Elsa.Services
|
|||
{
|
||||
public class WorkflowSchedulerQueue : IWorkflowSchedulerQueue
|
||||
{
|
||||
private readonly IDictionary<(string WorkflowDefinitionId, string ActivityId), (WorkflowBlueprint Workflow, IActivity Activity, object? Input, string? CorrelationId)> _nextWorkflowInstances;
|
||||
private readonly IDictionary<(string WorkflowDefinitionId, string ActivityId), (IWorkflowBlueprint Workflow, IActivityBlueprint Activity, object? Input, string? CorrelationId)> _nextWorkflowInstances;
|
||||
|
||||
public WorkflowSchedulerQueue() =>
|
||||
_nextWorkflowInstances = new Dictionary<(string WorkflowDefinitionId, string ActivityId), (WorkflowBlueprint Workflow, IActivity Activity, object? Input, string? CorrelationId)>();
|
||||
_nextWorkflowInstances = new Dictionary<(string WorkflowDefinitionId, string ActivityId), (IWorkflowBlueprint Workflow, IActivityBlueprint Activity, object? Input, string? CorrelationId)>();
|
||||
|
||||
public void Enqueue(WorkflowBlueprint workflowBlueprint, IActivity activity, object? input, string? correlationId)
|
||||
public void Enqueue(IWorkflowBlueprint workflowBlueprint, IActivityBlueprint activity, object? input, string? correlationId)
|
||||
=> _nextWorkflowInstances[(workflowBlueprint.Id, activity.Id)] = (workflowBlueprint, activity, input, correlationId);
|
||||
|
||||
public (WorkflowBlueprint Workflow, IActivity Activity, object? Input, string? CorrelationId)? Dequeue(string workflowDefinitionId, string activityId)
|
||||
public (IWorkflowBlueprint Workflow, IActivityBlueprint Activity, object? Input, string? CorrelationId)? Dequeue(string workflowDefinitionId, string activityId)
|
||||
{
|
||||
var key = (workflowDefinitionId, activityId);
|
||||
if(!_nextWorkflowInstances.ContainsKey(key))
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ namespace Elsa.WorkflowProviders
|
|||
_workflowBuilder = workflowBuilder;
|
||||
}
|
||||
|
||||
public Task<IEnumerable<WorkflowBlueprint>> GetWorkflowsAsync(CancellationToken cancellationToken) => Task.FromResult(GetWorkflows());
|
||||
private IEnumerable<WorkflowBlueprint> GetWorkflows() => from workflow in _workflows let builder = _workflowBuilder() select builder.Build(workflow);
|
||||
public Task<IEnumerable<IWorkflowBlueprint>> GetWorkflowsAsync(CancellationToken cancellationToken) => Task.FromResult(GetWorkflows());
|
||||
private IEnumerable<IWorkflowBlueprint> GetWorkflows() => from workflow in _workflows let builder = _workflowBuilder() select builder.Build(workflow);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.8" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\activities\Elsa.Activities.Console\Elsa.Activities.Console.csproj" />
|
||||
<ProjectReference Include="..\..\core\Elsa.Abstractions\Elsa.Abstractions.csproj" />
|
||||
<ProjectReference Include="..\..\core\Elsa.Core\Elsa.Core.csproj" />
|
||||
<ProjectReference Include="..\..\core\Elsa\Elsa.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
using Elsa.Activities.Console;
|
||||
using Elsa.Models;
|
||||
using Elsa.Services;
|
||||
using Elsa.Builders;
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Elsa.Samples.WorkflowDefinition
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
private static async Task Main(string[] args)
|
||||
{
|
||||
var services = new ServiceCollection()
|
||||
.AddElsa()
|
||||
.AddLogging(log => log.AddConsole())
|
||||
.AddConsoleActivities()
|
||||
.AddSingleton(Console.In)
|
||||
.BuildServiceProvider();
|
||||
|
||||
var activityResolver = services.GetRequiredService<IActivityActivator>();
|
||||
var activity1 = activityResolver.ActivateActivity<WriteLine>()
|
||||
.WithId("activity-1")
|
||||
.WithText("Hello world!");
|
||||
|
||||
var activity2 = activityResolver.ActivateActivity<WriteLine>()
|
||||
.WithId("activity-2")
|
||||
.WithText("Goodbye cruel world...!");
|
||||
|
||||
// Create Workflow Definition.
|
||||
var workflowDefinition = new Models.WorkflowDefinition
|
||||
{
|
||||
WorkflowDefinitionVersionId = "definition-001",
|
||||
IsPublished = true,
|
||||
Activities = new List<ActivityDefinition>
|
||||
{
|
||||
ActivityDefinition.FromActivity(activity1),
|
||||
ActivityDefinition.FromActivity(activity2)
|
||||
},
|
||||
Connections = new[]
|
||||
{
|
||||
new ConnectionDefinition("activity-1", "activity-2", OutcomeNames.Done),
|
||||
}
|
||||
};
|
||||
|
||||
// Register it.
|
||||
//var workflowDefinitionStore = services.GetService<IWorkflowDefinitionStore>();
|
||||
//await workflowDefinitionStore.AddAsync(workflowDefinition);
|
||||
|
||||
// Run it.
|
||||
var invoker = services.GetService<IWorkflowHost>();
|
||||
await invoker.RunWorkflowDefinitionAsync("definition-001");
|
||||
|
||||
Console.ReadLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
|
@ -39,9 +40,9 @@ namespace Elsa.Scripting.Liquid.Handlers
|
|||
"Variables",
|
||||
x => new LiquidPropertyAccessor(name => ToFluidValue(x.WorkflowExecutionContext.Variables, name)));
|
||||
|
||||
context.MemberAccessStrategy.Register<ActivityExecutionContext, LiquidObjectAccessor<IActivity>>(
|
||||
context.MemberAccessStrategy.Register<ActivityExecutionContext, LiquidObjectAccessor<IActivityBlueprint>>(
|
||||
"Activities",
|
||||
x => new LiquidObjectAccessor<IActivity>(name => GetActivityAsync(x, name)));
|
||||
x => new LiquidObjectAccessor<IActivityBlueprint>(name => GetActivityAsync(x, name)));
|
||||
|
||||
context.MemberAccessStrategy.Register<LiquidObjectAccessor<IActivity>, object>(GetActivityOutput);
|
||||
|
||||
|
|
@ -64,10 +65,11 @@ namespace Elsa.Scripting.Liquid.Handlers
|
|||
private async Task<object?> GetActivityOutput(LiquidObjectAccessor<IActivity> accessor, string activityName)
|
||||
{
|
||||
var activity = await accessor.GetValueAsync(activityName);
|
||||
return activity?.Output;
|
||||
//return activity?.Output;
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private Task<IActivity> GetActivityAsync(ActivityExecutionContext context, string name)
|
||||
=> Task.FromResult(context.WorkflowExecutionContext.Activities.FirstOrDefault(x => x.Name == name));
|
||||
private Task<IActivityBlueprint> GetActivityAsync(ActivityExecutionContext context, string name)
|
||||
=> Task.FromResult(context.WorkflowExecutionContext.WorkflowBlueprint.Activities.FirstOrDefault(x => x.Name == name));
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,6 @@ namespace Elsa.Server.GraphQL.Extensions
|
|||
return services
|
||||
.AddScoped<IWorkflowPublisher, WorkflowPublisher>()
|
||||
.AddSingleton<VersionOptionsConverter>()
|
||||
.AddSingleton<ActivityStateResolver>()
|
||||
.AddSingleton<IActivityDescriber, ActivityDescriber>()
|
||||
.AddAutoMapperProfile<MappingProfile>(ServiceLifetime.Singleton)
|
||||
.AddGraphQL(sp => SchemaBuilder.New()
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
using AutoMapper;
|
||||
using Elsa.Models;
|
||||
using Elsa.Serialization;
|
||||
using Elsa.Server.GraphQL.Types;
|
||||
using Elsa.Services;
|
||||
|
||||
namespace Elsa.Server.GraphQL.Mapping
|
||||
{
|
||||
public class ActivityStateResolver : IValueResolver<ActivityDefinitionInput, ActivityDefinition, Variables?>
|
||||
{
|
||||
private readonly ITokenSerializer _serializer;
|
||||
private readonly IActivityActivator _activityActivator;
|
||||
|
||||
public ActivityStateResolver(ITokenSerializer serializer, IActivityActivator activityActivator)
|
||||
{
|
||||
_serializer = serializer;
|
||||
_activityActivator = activityActivator;
|
||||
}
|
||||
|
||||
public Variables? Resolve(ActivityDefinitionInput source, ActivityDefinition destination, Variables? destMember, ResolutionContext context)
|
||||
{
|
||||
var json = source.State;
|
||||
var variables = json != null ? _serializer.Deserialize<Variables>(json) : null;
|
||||
|
||||
return variables;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -9,9 +9,6 @@ namespace Elsa.Server.GraphQL.Mapping
|
|||
{
|
||||
public MappingProfile()
|
||||
{
|
||||
CreateMap<ActivityDefinitionInput, ActivityDefinition>()
|
||||
.ForMember(d => d.State, d => d.MapFrom<ActivityStateResolver>());
|
||||
|
||||
CreateMap<VersionOptionsInput, VersionOptions>().ConvertUsing<VersionOptionsConverter>();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,120 +1,120 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using AutoFixture;
|
||||
using Elsa.ActivityResults;
|
||||
using Elsa.Expressions;
|
||||
using Elsa.Models;
|
||||
using Elsa.Services;
|
||||
using Elsa.Services.Models;
|
||||
using Elsa.Testing.Shared.Autofixture;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Moq;
|
||||
using NodaTime;
|
||||
using NodaTime.Testing;
|
||||
using Xunit;
|
||||
using YesSql;
|
||||
using YesSql.Provider.Sqlite;
|
||||
|
||||
namespace Elsa.Core.UnitTests
|
||||
{
|
||||
public class WorkflowHostTests : IDisposable
|
||||
{
|
||||
private readonly IFixture _fixture;
|
||||
private readonly WorkflowHost _workflowHost;
|
||||
private TemporaryFolder _tempFolder;
|
||||
private ISession _session;
|
||||
|
||||
public WorkflowHostTests()
|
||||
{
|
||||
_fixture = new Fixture().Customize(new NodaTimeCustomization());
|
||||
_session = CreateSession();
|
||||
|
||||
var workflowActivatorMock = new Mock<IWorkflowFactory>();
|
||||
var workflowRegistryMock = new Mock<IWorkflowRegistry>();
|
||||
var workflowInstanceManager = new WorkflowInstanceManager(_session);
|
||||
var workflowExpressionEvaluatorMock = new Mock<IExpressionEvaluator>();
|
||||
var mediatorMock = new Mock<IMediator>();
|
||||
var now = _fixture.Create<Instant>();
|
||||
var clock = new FakeClock(now);
|
||||
var logger = new NullLogger<WorkflowHost>();
|
||||
var serviceProvider = new ServiceCollection().BuildServiceProvider();
|
||||
|
||||
workflowActivatorMock
|
||||
.Setup(x => x.InstantiateAsync(It.IsAny<WorkflowBlueprint>(), It.IsAny<string?>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync((WorkflowBlueprint workflow, string? correlationId, CancellationToken cancellationToken) => new WorkflowInstance());
|
||||
|
||||
_workflowHost = new WorkflowHost(
|
||||
workflowInstanceManager,
|
||||
workflowRegistryMock.Object,
|
||||
workflowActivatorMock.Object,
|
||||
workflowExpressionEvaluatorMock.Object,
|
||||
clock,
|
||||
mediatorMock.Object,
|
||||
serviceProvider,
|
||||
logger);
|
||||
}
|
||||
|
||||
public void Dispose() => _session.Dispose();
|
||||
|
||||
private ISession CreateSession()
|
||||
{
|
||||
_tempFolder = new TemporaryFolder();
|
||||
var connectionString = $@"Data Source={_tempFolder.Folder}elsa.db;Cache=Shared";
|
||||
var config = new Configuration().UseSqLite(connectionString).UseDefaultIdGenerator();
|
||||
var store = StoreFactory.CreateAndInitializeAsync(config).GetAwaiter().GetResult();
|
||||
return store.CreateSession();
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Can run simple workflow to completed state.")]
|
||||
public async Task RunAsync01()
|
||||
{
|
||||
var activityExecutionResultMock = new Mock<IActivityExecutionResult>();
|
||||
var activity = CreateActivity(activityExecutionResult: activityExecutionResultMock.Object);
|
||||
var workflow = CreateWorkflow(activity);
|
||||
var executionContext = await _workflowHost.RunWorkflowAsync(workflow);
|
||||
|
||||
Assert.Equal(WorkflowStatus.Completed, executionContext.UpdateWorkflowInstance().Status);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Invokes returned activity execution result.")]
|
||||
public async Task RunAsync02()
|
||||
{
|
||||
var activityExecutionResultMock = new Mock<IActivityExecutionResult>();
|
||||
var activity = CreateActivity(true, activityExecutionResultMock.Object);
|
||||
var workflow = CreateWorkflow(activity);
|
||||
var executionContext = await _workflowHost.RunWorkflowAsync(workflow);
|
||||
|
||||
activityExecutionResultMock
|
||||
.Verify(x => x.ExecuteAsync(It.IsAny<ActivityExecutionContext>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
private IActivity CreateActivity(bool canExecute = true, IActivityExecutionResult? activityExecutionResult = null)
|
||||
{
|
||||
var activityMock = new Mock<IActivity>();
|
||||
var activityId = _fixture.Create<string>();
|
||||
|
||||
activityMock.Setup(x => x.Id).Returns(activityId);
|
||||
|
||||
activityMock
|
||||
.Setup(x => x.CanExecuteAsync(It.IsAny<ActivityExecutionContext>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(canExecute);
|
||||
|
||||
if (activityExecutionResult != null)
|
||||
activityMock
|
||||
.Setup(x => x.ExecuteAsync(It.IsAny<ActivityExecutionContext>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(activityExecutionResult);
|
||||
|
||||
return activityMock.Object;
|
||||
}
|
||||
|
||||
private WorkflowBlueprint CreateWorkflow(IActivity activity)
|
||||
{
|
||||
var workflow = new WorkflowBlueprint();
|
||||
workflow.Activities.Add(activity);
|
||||
return workflow;
|
||||
}
|
||||
}
|
||||
}
|
||||
// using System;
|
||||
// using System.Threading;
|
||||
// using System.Threading.Tasks;
|
||||
// using AutoFixture;
|
||||
// using Elsa.ActivityResults;
|
||||
// using Elsa.Expressions;
|
||||
// using Elsa.Models;
|
||||
// using Elsa.Services;
|
||||
// using Elsa.Services.Models;
|
||||
// using Elsa.Testing.Shared.Autofixture;
|
||||
// using MediatR;
|
||||
// using Microsoft.Extensions.DependencyInjection;
|
||||
// using Microsoft.Extensions.Logging.Abstractions;
|
||||
// using Moq;
|
||||
// using NodaTime;
|
||||
// using NodaTime.Testing;
|
||||
// using Xunit;
|
||||
// using YesSql;
|
||||
// using YesSql.Provider.Sqlite;
|
||||
//
|
||||
// namespace Elsa.Core.UnitTests
|
||||
// {
|
||||
// public class WorkflowHostTests : IDisposable
|
||||
// {
|
||||
// private readonly IFixture _fixture;
|
||||
// private readonly WorkflowHost _workflowHost;
|
||||
// private TemporaryFolder _tempFolder;
|
||||
// private ISession _session;
|
||||
//
|
||||
// public WorkflowHostTests()
|
||||
// {
|
||||
// _fixture = new Fixture().Customize(new NodaTimeCustomization());
|
||||
// _session = CreateSession();
|
||||
//
|
||||
// var workflowActivatorMock = new Mock<IWorkflowFactory>();
|
||||
// var workflowRegistryMock = new Mock<IWorkflowRegistry>();
|
||||
// var workflowInstanceManager = new WorkflowInstanceManager(_session);
|
||||
// var workflowExpressionEvaluatorMock = new Mock<IExpressionEvaluator>();
|
||||
// var mediatorMock = new Mock<IMediator>();
|
||||
// var now = _fixture.Create<Instant>();
|
||||
// var clock = new FakeClock(now);
|
||||
// var logger = new NullLogger<WorkflowHost>();
|
||||
// var serviceProvider = new ServiceCollection().BuildServiceProvider();
|
||||
//
|
||||
// workflowActivatorMock
|
||||
// .Setup(x => x.InstantiateAsync(It.IsAny<WorkflowBlueprint>(), It.IsAny<string?>(), It.IsAny<CancellationToken>()))
|
||||
// .ReturnsAsync((WorkflowBlueprint workflow, string? correlationId, CancellationToken cancellationToken) => new WorkflowInstance());
|
||||
//
|
||||
// _workflowHost = new WorkflowHost(
|
||||
// workflowInstanceManager,
|
||||
// workflowRegistryMock.Object,
|
||||
// workflowActivatorMock.Object,
|
||||
// workflowExpressionEvaluatorMock.Object,
|
||||
// clock,
|
||||
// mediatorMock.Object,
|
||||
// serviceProvider,
|
||||
// logger);
|
||||
// }
|
||||
//
|
||||
// public void Dispose() => _session.Dispose();
|
||||
//
|
||||
// private ISession CreateSession()
|
||||
// {
|
||||
// _tempFolder = new TemporaryFolder();
|
||||
// var connectionString = $@"Data Source={_tempFolder.Folder}elsa.db;Cache=Shared";
|
||||
// var config = new Configuration().UseSqLite(connectionString).UseDefaultIdGenerator();
|
||||
// var store = StoreFactory.CreateAndInitializeAsync(config).GetAwaiter().GetResult();
|
||||
// return store.CreateSession();
|
||||
// }
|
||||
//
|
||||
// [Fact(DisplayName = "Can run simple workflow to completed state.")]
|
||||
// public async Task RunAsync01()
|
||||
// {
|
||||
// var activityExecutionResultMock = new Mock<IActivityExecutionResult>();
|
||||
// var activity = CreateActivity(activityExecutionResult: activityExecutionResultMock.Object);
|
||||
// var workflow = CreateWorkflow(activity);
|
||||
// var executionContext = await _workflowHost.RunWorkflowAsync(workflow);
|
||||
//
|
||||
// Assert.Equal(WorkflowStatus.Completed, executionContext.UpdateWorkflowInstance().Status);
|
||||
// }
|
||||
//
|
||||
// [Fact(DisplayName = "Invokes returned activity execution result.")]
|
||||
// public async Task RunAsync02()
|
||||
// {
|
||||
// var activityExecutionResultMock = new Mock<IActivityExecutionResult>();
|
||||
// var activity = CreateActivity(true, activityExecutionResultMock.Object);
|
||||
// var workflow = CreateWorkflow(activity);
|
||||
// var executionContext = await _workflowHost.RunWorkflowAsync(workflow);
|
||||
//
|
||||
// activityExecutionResultMock
|
||||
// .Verify(x => x.ExecuteAsync(It.IsAny<ActivityExecutionContext>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
// }
|
||||
//
|
||||
// private IActivity CreateActivity(bool canExecute = true, IActivityExecutionResult? activityExecutionResult = null)
|
||||
// {
|
||||
// var activityMock = new Mock<IActivity>();
|
||||
// var activityId = _fixture.Create<string>();
|
||||
//
|
||||
// activityMock.Setup(x => x.Id).Returns(activityId);
|
||||
//
|
||||
// activityMock
|
||||
// .Setup(x => x.CanExecuteAsync(It.IsAny<ActivityExecutionContext>(), It.IsAny<CancellationToken>()))
|
||||
// .ReturnsAsync(canExecute);
|
||||
//
|
||||
// if (activityExecutionResult != null)
|
||||
// activityMock
|
||||
// .Setup(x => x.ExecuteAsync(It.IsAny<ActivityExecutionContext>(), It.IsAny<CancellationToken>()))
|
||||
// .ReturnsAsync(activityExecutionResult);
|
||||
//
|
||||
// return activityMock.Object;
|
||||
// }
|
||||
//
|
||||
// private WorkflowBlueprint CreateWorkflow(IActivity activity)
|
||||
// {
|
||||
// var workflow = new WorkflowBlueprint();
|
||||
// workflow.Activities.Add(activity);
|
||||
// return workflow;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
Loading…
Reference in a new issue