Skip to content

Commit

Permalink
Basic functioning workflow engine
Browse files Browse the repository at this point in the history
  • Loading branch information
Sipke Schoorstra committed Oct 12, 2018
1 parent d659e38 commit 1635618
Show file tree
Hide file tree
Showing 39 changed files with 1,146 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[*]
charset=utf-8
end_of_line=crlf
trim_trailing_whitespace=false
insert_final_newline=false
indent_style=space
indent_size=4

39 changes: 39 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#Ignore thumbnails created by Windows
Thumbs.db

#Ignore files built by Visual Studio
*.obj
*.exe
*.pdb
*.user
*.aps
*.pch
*.vspscc
*_i.c
*_p.c
*.ncb
*.suo
*.tlb
*.tlh
*.bak
*.cache
*.ilk
*.log
[Bb]in
[Dd]ebug*/
*.lib
*.sbr
obj/
[Rr]elease*/
_ReSharper*/
[Tt]est[Rr]esult*
.vs/

#Nuget packages folder
packages/

#Ignore git-related files
*.orig

#Rider
.idea
58 changes: 58 additions & 0 deletions Flowsharp.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28010.2036
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flowsharp.Abstractions", "src\Flowsharp.Abstractions\Flowsharp.Abstractions.csproj", "{300EE2D5-54C5-46F2-AD03-BB43589EA074}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flowsharp.Core", "src\Flowsharp.Core\Flowsharp.Core.csproj", "{3B33AE9C-0465-4DA3-8C02-65E5766A7ED4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Flowsharp.Samples.Console", "src\Flowsharp.Samples.Console\Flowsharp.Samples.Console.csproj", "{48EDB976-3227-4DFD-BBB3-3BC9AEA19A88}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{DA71CDAA-8DD3-4D5F-9FBD-8E4B37A2D925}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "items", "items", "{7165BB9E-F22C-40D2-B7B1-CA3EFA2529A0}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.gitignore = .gitignore
README.md = README.md
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Flowsharp.Fluid", "src\Flowsharp.Fluid\Flowsharp.Fluid.csproj", "{B20D6AF5-91B1-4455-8541-22C5B31288D0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{300EE2D5-54C5-46F2-AD03-BB43589EA074}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{300EE2D5-54C5-46F2-AD03-BB43589EA074}.Debug|Any CPU.Build.0 = Debug|Any CPU
{300EE2D5-54C5-46F2-AD03-BB43589EA074}.Release|Any CPU.ActiveCfg = Release|Any CPU
{300EE2D5-54C5-46F2-AD03-BB43589EA074}.Release|Any CPU.Build.0 = Release|Any CPU
{3B33AE9C-0465-4DA3-8C02-65E5766A7ED4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3B33AE9C-0465-4DA3-8C02-65E5766A7ED4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3B33AE9C-0465-4DA3-8C02-65E5766A7ED4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3B33AE9C-0465-4DA3-8C02-65E5766A7ED4}.Release|Any CPU.Build.0 = Release|Any CPU
{48EDB976-3227-4DFD-BBB3-3BC9AEA19A88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{48EDB976-3227-4DFD-BBB3-3BC9AEA19A88}.Debug|Any CPU.Build.0 = Debug|Any CPU
{48EDB976-3227-4DFD-BBB3-3BC9AEA19A88}.Release|Any CPU.ActiveCfg = Release|Any CPU
{48EDB976-3227-4DFD-BBB3-3BC9AEA19A88}.Release|Any CPU.Build.0 = Release|Any CPU
{B20D6AF5-91B1-4455-8541-22C5B31288D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B20D6AF5-91B1-4455-8541-22C5B31288D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B20D6AF5-91B1-4455-8541-22C5B31288D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B20D6AF5-91B1-4455-8541-22C5B31288D0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8B0975FD-7050-48B0-88C5-48C33378E158}
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{300EE2D5-54C5-46F2-AD03-BB43589EA074} = {DA71CDAA-8DD3-4D5F-9FBD-8E4B37A2D925}
{3B33AE9C-0465-4DA3-8C02-65E5766A7ED4} = {DA71CDAA-8DD3-4D5F-9FBD-8E4B37A2D925}
{48EDB976-3227-4DFD-BBB3-3BC9AEA19A88} = {DA71CDAA-8DD3-4D5F-9FBD-8E4B37A2D925}
{B20D6AF5-91B1-4455-8541-22C5B31288D0} = {DA71CDAA-8DD3-4D5F-9FBD-8E4B37A2D925}
EndGlobalSection
EndGlobal
135 changes: 135 additions & 0 deletions src/Flowsharp.Abstractions/Activities/Activity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Flowsharp.ActivityResults;
using Flowsharp.Models;
using Microsoft.Extensions.Localization;

namespace Flowsharp.Activities
{
public abstract class Activity : IActivity
{
public virtual string Name => GetType().Name;

public Task ProvideMetadataAsync(ActivityMetadataContext context, CancellationToken cancellationToken)
{
ProvideMetadata(context);
return Task.CompletedTask;
}

public virtual Task<bool> CanExecuteAsync(WorkflowExecutionContext workflowContext, ActivityExecutionContext activityContext, CancellationToken cancellationToken)
{
return Task.FromResult(true);
}

public virtual Task<ActivityExecutionResult> ExecuteAsync(WorkflowExecutionContext workflowContext, ActivityExecutionContext activityContext, CancellationToken cancellationToken)
{
return Task.FromResult(Execute(workflowContext, activityContext));
}

public virtual Task<ActivityExecutionResult> ResumeAsync(WorkflowExecutionContext workflowContext, ActivityExecutionContext activityContext, CancellationToken cancellationToken)
{
return Task.FromResult(Resume(workflowContext, activityContext));
}

public virtual IEnumerable<Outcome> GetOutcomes(WorkflowExecutionContext workflowContext, ActivityExecutionContext activityContext)
{
return Enumerable.Empty<Outcome>();
}

public virtual Task OnActivityExecutedAsync(WorkflowExecutionContext workflowContext, ActivityExecutionContext activityContext, CancellationToken cancellationToken)
{
OnActivityExecuted(workflowContext, activityContext);
return Task.CompletedTask;
}

public virtual Task OnActivityExecutingAsync(WorkflowExecutionContext workflowContext, ActivityExecutionContext activityContext, CancellationToken cancellationToken)
{
OnActivityExecuting(workflowContext, activityContext);
return Task.CompletedTask;
}

public virtual Task ReceiveInputAsync(WorkflowExecutionContext workflowContext, IDictionary<string, object> input, CancellationToken cancellationToken)
{
ReceiveInput(workflowContext, input);
return Task.CompletedTask;
}

public virtual Task WorkflowResumedAsync(WorkflowExecutionContext workflowContext, CancellationToken cancellationToken)
{
WorkflowResumed(workflowContext);
return Task.CompletedTask;
}

public virtual Task WorkflowResumingAsync(WorkflowExecutionContext workflowContext, CancellationToken cancellationToken)
{
WorkflowResuming(workflowContext);
return Task.CompletedTask;
}

public virtual Task WorkflowStartedAsync(WorkflowExecutionContext workflowContext, CancellationToken cancellationToken)
{
WorkflowStarted(workflowContext);
return Task.CompletedTask;
}

public virtual Task WorkflowStartingAsync(WorkflowExecutionContext workflowContext, CancellationToken cancellationToken)
{
WorkflowStarting(workflowContext);
return Task.CompletedTask;
}

protected virtual void ProvideMetadata(ActivityMetadataContext context)
{
}

protected virtual ActivityExecutionResult Execute(WorkflowExecutionContext workflowContext, ActivityExecutionContext activityContext)
{
return Noop();
}

protected virtual ActivityExecutionResult Resume(WorkflowExecutionContext workflowContext, ActivityExecutionContext activityContext)
{
return Noop();
}

protected virtual void OnActivityExecuted(WorkflowExecutionContext workflowContext, ActivityExecutionContext activityContext) {}
protected virtual void OnActivityExecuting(WorkflowExecutionContext workflowContext, ActivityExecutionContext activityContext) {}
protected virtual void ReceiveInput(WorkflowExecutionContext workflowContext, IDictionary<string, object> input) {}
protected virtual void WorkflowResumed(WorkflowExecutionContext workflowContext) {}
protected virtual void WorkflowResuming(WorkflowExecutionContext workflowContext) {}
protected virtual void WorkflowStarted(WorkflowExecutionContext workflowContext) {}
protected virtual void WorkflowStarting(WorkflowExecutionContext workflowContext) {}

protected IEnumerable<Outcome> Outcomes(params LocalizedString[] names)
{
return names.Select(x => new Outcome(x));
}

protected IEnumerable<Outcome> Outcomes(IEnumerable<LocalizedString> names)
{
return names.Select(x => new Outcome(x));
}

protected ActivityExecutionResult Outcomes(params string[] names)
{
return Outcomes((IEnumerable<string>)names);
}

protected ActivityExecutionResult Outcomes(IEnumerable<string> names)
{
return new OutcomeResult(names);
}

protected ActivityExecutionResult Halt()
{
return new HaltResult();
}

protected ActivityExecutionResult Noop()
{
return new NoopResult();
}
}
}
83 changes: 83 additions & 0 deletions src/Flowsharp.Abstractions/Activities/IActivity.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Flowsharp.ActivityResults;
using Flowsharp.Models;

namespace Flowsharp.Activities
{
public interface IActivity
{
/// <summary>
/// The system name of the activity.
/// </summary>
/// <remarks>The Name is used to identify a given activity type and must be unique.</remarks>
string Name { get; }

/// <summary>
/// Provides metadata about the specified activity.
/// </summary>
Task ProvideMetadataAsync(ActivityMetadataContext context, CancellationToken cancellationToken);

/// <summary>
/// Returns a list of possible outcomes when the activity is executed.
/// </summary>
IEnumerable<Outcome> GetOutcomes(WorkflowExecutionContext workflowContext, ActivityExecutionContext activityContext);

/// <summary>
/// Returns a value of whether the specified activity can execute.
/// </summary>
Task<bool> CanExecuteAsync(WorkflowExecutionContext workflowContext, ActivityExecutionContext activityContext, CancellationToken cancellationToken);

/// <summary>
/// Executes the specified activity.
/// </summary>
Task<ActivityExecutionResult> ExecuteAsync(WorkflowExecutionContext workflowContext, ActivityExecutionContext activityContext, CancellationToken cancellationToken);

/// <summary>
/// Resumes the specified activity.
/// </summary>
Task<ActivityExecutionResult> ResumeAsync(WorkflowExecutionContext workflowContext, ActivityExecutionContext activityContext, CancellationToken cancellationToken);

/// <summary>
/// Executes before a workflow starts or resumes, giving activities an opportunity to read and store any values of interest.
/// </summary>
Task ReceiveInputAsync(WorkflowExecutionContext workflowContext, IDictionary<string, object> input, CancellationToken cancellationToken);

/// <summary>
/// Executes when a workflow is about to start.
/// </summary>
Task WorkflowStartingAsync(WorkflowExecutionContext workflowContext, CancellationToken cancellationToken);

/// <summary>
/// Executes when a workflow has started.
/// </summary>
Task WorkflowStartedAsync(WorkflowExecutionContext context, CancellationToken cancellationToken);

/// <summary>
/// Executes when a workflow is about to be resumed.
/// </summary>
Task WorkflowResumingAsync(WorkflowExecutionContext context, CancellationToken cancellationToken);

/// <summary>
/// Executes when a workflow is resumed.
/// </summary>
Task WorkflowResumedAsync(WorkflowExecutionContext context, CancellationToken cancellationToken);

/// <summary>
/// Executes when an activity is about to be executed.
/// </summary>
/// <param name="workflowContext">The workflow execution context.</param>
/// <param name="activityContext">The activity context containing the activity that is the subject of the event.</param>
/// <param name="cancellationToken">The cancellation token.</param>
Task OnActivityExecutingAsync(WorkflowExecutionContext workflowContext, ActivityExecutionContext activityContext, CancellationToken cancellationToken = default(CancellationToken));

/// <summary>
/// Called on each activity when an activity has been executed.
/// </summary>
/// <param name="workflowContext">The workflow execution context.</param>
/// <param name="activityContext">The activity context containing the activity that is the subject of the event.</param>
/// <param name="cancellationToken">The cancellation token.</param>
Task OnActivityExecutedAsync(WorkflowExecutionContext workflowContext, ActivityExecutionContext activityContext, CancellationToken cancellationToken);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Flowsharp.Activities;
using Flowsharp.Descriptors;
using Flowsharp.Services;

namespace Flowsharp.ActivityProviders
{
/// <summary>
/// Provides activities based on <see cref="IActivity"/> implementations that have been registered with the service container.
/// </summary>
public class TypedActivityProvider : IActivityProvider
{
private readonly Func<IEnumerable<IActivity>> _activitiesFactory;

public TypedActivityProvider(Func<IEnumerable<IActivity>> activitiesFactory)
{
_activitiesFactory = activitiesFactory;
}

public Task<IEnumerable<ActivityDescriptor>> GetActivityDescriptorsAsync(CancellationToken cancellationToken)
{
return Task.FromResult(_activitiesFactory().Select(ToDescriptor));
}

private ActivityDescriptor ToDescriptor(IActivity activity)
{
return new ActivityDescriptor
{
Name = activity.Name,
GetMetadataAsync = activity.ProvideMetadataAsync,
CanExecuteAsync = activity.CanExecuteAsync,
GetOutcomes = activity.GetOutcomes,
ExecuteActivityAsync = activity.ExecuteAsync,
ResumeActivityAsync = activity.ResumeAsync,
ReceiveInputAsync = activity.ReceiveInputAsync,
WorkflowResumedAsync = activity.WorkflowResumedAsync,
WorkflowResumingAsync = activity.WorkflowResumingAsync,
WorkflowStartedAsync = activity.WorkflowStartedAsync,
WorkflowStartingAsync = activity.WorkflowStartingAsync,
OnActivityExecutedAsync = activity.OnActivityExecutedAsync,
OnActivityExecutingAsync = activity.OnActivityExecutingAsync
};
}
}
}
Loading

0 comments on commit 1635618

Please sign in to comment.