Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V1.5.1 #30

Merged
merged 6 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 19 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
# Micro Workflow .net
<!--start-->
[![Stats](https://img.shields.io/badge/Code_lines-1,7_K-ff69b4.svg)]()
[![Stats](https://img.shields.io/badge/Code_lines-1,8_K-ff69b4.svg)]()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please ensure to update the Test and Doc lines if there were actual changes in the count reflect the accurate statistics.

[![Stats](https://img.shields.io/badge/Test_lines-1,2_K-69ffb4.svg)]()
[![Stats](https://img.shields.io/badge/Doc_lines-594-ffb469.svg)]()
[![Stats](https://img.shields.io/badge/Doc_lines-936-ffb469.svg)]()
<!--end-->


<p align="center"> <img src="doc/microworkflow.webp" alt="logo"></p>

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "embedable" should be spelled "embeddable."

Micro Workflow is a very fast, small, embedable and distributed workflow system primarily for .Net developers.
Expand All @@ -14,22 +13,27 @@ The code base is so small every one can read and understand the inner workings i

# 1. Why use Micro Workflow

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding a bullet point for situations where the workflow itself allows for faster deployment and adjustments in functionality.

You should consider using Micro Workflow due to one or more of the following reason
You should consider using Micro Workflow for one or more of the following reasons.
* When you have a need for a queue,
* scheduling and re-scheduling of code to be executed
* distributing load across multiple servers
* or a business process that needs to be robust (have it being broken up into steps and its progress persisted).

when you have a need for a queue, scheduling of code to execute, or a business process that needs to be robus. We provide many examples in ["integration patterns"](https://github.com/kbilsted/MicroWorkflow.net/tree/feature/doc?tab=readme-ov-file#5-integration-patterns)
We provide many examples in ["integration patterns"](https://github.com/kbilsted/MicroWorkflow.net/tree/feature/doc?tab=readme-ov-file#5-integration-patterns) on how to get started.

Design philosophy

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider harmonizing bullet formatting where past bullet points end with periods, for uniformity.

**Simplicity**
* We model only the steps in a workflow, *not* the transitions between them
* This greatly *simplify* the model, the versioning of flows and steps
* enable you to use reusable code blocks for determining a transition
* It is *easy* to embed it directly into your solutions to improve resiliance or use as a stand-alone workflow
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "resiliance" should be spelled "resilience" for clarity.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The phrase "to improve resiliance or use as a stand-alone workflow" is slightly misleading. Consider clarifying that micro-workflow can improve resilience and can also be used as a stand-alone workflow.

* This greatly *simplifies* the model, especially when dealing with change and versioning
* It enables you to use reusable code blocks for determining a transition
* It is *easy* to embed micro workflow directly into your solutions to improve resiliance or use as a stand-alone workflow
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "debugable" should be spelled "debuggable."

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "testable" should be spelled "testable."


**We use C# all the way**
* We don't want to invent a new language - we love C#!
* We don't want to invent a new language for the workflow - we love C#!
* Workflow code is *readable*, *debugable*, and *testable* - like the rest of your code base.
* You can use existing best practices for logging, IOC containers etc. of your choice
* Since Workflow code is just C# it is *easy to commit and merge* use your existing *branching strategies*
* Workflow code is just C# so it is *easy to commit and merge* using your existing *branching strategies*
* You *do not* need a special graphical editor for specifying flows

**The datamodel is simple - just three DB tables**
Expand All @@ -38,15 +42,15 @@ when you have a need for a queue, scheduling of code to execute, or a business p

**Distributed mindset**
* Supports *Fail-over setup* To improve up-time applications/integrations are often running on multiple servers at the same time. This is a common scenario is supported with no special setup.
* Supports incremental deployments across more instances. When deploying multiple instances, the roll-out is typical gradual. Hence we support that steps may be added that is only known to a sub-set of the running workflows.
* Supports incremental deployments across multiple instances, meaning the roll-out is gradual. Hence we support that steps may be added that is only known to a sub-set of the running workflows.

**Scalable**
* You can add more workers in the workflow engine (vertical scaling)
* You can add more servers each running a workflow engine (horizontal scaling)

**No external dependencies**
* The core library has *no external dependencies*, you can use whatever database, logger, json/xml/binary serializer you want ... in any version you want
* Convenience supplement nuget packages for Newtonsoft json, Ado .net, and Autofac are provided
* To get you quickly started, we supply nuget packages for "Newtonsoft Json", "Ado .Net Db", and "Autofac IOC". The packages are completely optional.


# 2. Overview
Expand All @@ -61,11 +65,11 @@ Supported scalabilities

# 3. Getting started
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The phrase "To define a workflow with the two steps, a 'FetchData' step that fetches some data, and a 'AnalyzeWords'" can be made clearer by altering it to read "To define a workflow with two steps: a 'FetchData' step that fetches some data and an 'AnalyzeWords' step that analyzes the data."

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "sucesfully" should be spelled "successfully."


To define a workflow with the two steps `FetchData` (which fetches some data), and `AnalyzeWords` (that analyzes the data), we implement interface `IStepImplementation` twice.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider rephrasing for clarity. Instead of "there are no restrictions on the names of steps, but we found using a scheme similar to REST api's to be beneficial." you could say "While there are no restrictions on the naming of steps, using a naming scheme similar to REST APIs is recommended for consistency."

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an inconsistency as "There are no restrictions on the names of steps" and "Two workflow steps cannot have the same name". Consider consolidating these statements for better clarity.

To transition from one step to one (or several steps), use `Done()`. This tells the engine that the current step has finished sucesfully. You can supply one or more steps that will be executed in the future.
To define a workflow with the two steps, a `FetchData` step that fetches some data, and a `AnalyzeWords` step that analyzes the data, we implement interface `IStepImplementation` twice.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "mis-spelling" should be "misspelling." Additionally, ensure to have an apostrophe in "APIs."

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's helpful to reiterate that using a standardized naming convention for workflow steps increases clarity and maintainability.

To transition from one step to another, the step uses `return Done()`. This tells the engine that the current step has finished sucesfully. You can supply one or more steps that will be executed as a result of the success.
This is how you control ordering of events.

There are no restrictions on the names of steps, but we found using a scheme similar to REST api's is beneficial. Hence we recommend you to use `{version}/{business domain}/{workflow name}/{workflow step}`.
There are no restrictions on the names of steps, but we found using a scheme similar to REST api's to be beneficial. Hence using the following format `{version}/{business domain}/{workflow name}/{workflow step}`. By defining the name of the flow as a `public const` it is easy to "find usage" inside the code base and to ensure no mis-spelling. Two workflow steps cannot have the same name.

```C#
[StepName(Name)]
Expand Down
2 changes: 1 addition & 1 deletion src/Demos/ConsoleDemo/MicroWorkflow.ConsoleDemo.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Autofac" Version="8.0.0" />
<PackageReference Include="Autofac" Version="8.1.1" />
</ItemGroup>

<ItemGroup>
Expand Down
13 changes: 7 additions & 6 deletions src/Demos/MicroWorkflow.Tests/AdoSingletonStepTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ public void When_creating_a_singleton_Then_it_is_created()
Singleton = true,
FlowId = helper.FlowId
}];
helper.StepHandlers = [Handle(name, step => {
helper.StepHandlers = [Handle(name, step => {
stepResult = $"hello";
stepResultIsSingleton = step.Singleton;
return step.Done();
return step.Done();
})];
helper.StopWhenNoWork().BuildAndStart();

Expand Down Expand Up @@ -74,13 +74,14 @@ public void When_AddStepIfNotExists_two_identical_singleton_steps_Then_insert_fi
var name = helper.RndName;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change here from a single chain statement to a variable assignment and chain statement, improves readability and debugging, however, if id is expected to be reused later, it's more appropriate. Be sure this change aligns with the rest of the code.

var step = new Step(name) { Singleton = true };
SearchModel searchModel = new(Name: step.Name);
engine.Data.AddStepIfNotExists(step, searchModel)
.Should()

var id = engine.Data.AddStepIfNotExists(step, searchModel);
id.Should()
.HaveValue();

var step2 = new Step(name) { Singleton = true };
engine.Data.AddStepIfNotExists(step2, searchModel)
.Should()
id = engine.Data.AddStepIfNotExists(step2, searchModel);
id.Should()
.BeNull();
}
}
4 changes: 2 additions & 2 deletions src/Demos/MicroWorkflow.Tests/DocumentationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public async Task<ExecutionResult> ExecuteAsync(Step step)

// ... stuff

return step.Done();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By using Task.FromResult, you're ensuring the code is asynchronous but it can be considered redundant if the operation is not truly asynchronous, potentially confusing future maintainers.

return await Task.FromResult(step.Done());
}
}

Expand All @@ -82,7 +82,7 @@ public async Task<ExecutionResult> ExecuteAsync(Step step)

// ... fetch data

return step.Rerun(scheduleTime: step.ExecutionStartTime!.Value.AddHours(1));
return await Task.FromResult(step.Rerun(scheduleTime: step.ExecutionStartTime!.Value.AddHours(1)));
}
}

Expand Down
15 changes: 5 additions & 10 deletions src/Demos/MicroWorkflow.Tests/MicroWorkflow.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,12 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Autofac" Version="8.0.0" />
<PackageReference Include="AutoFixture" Version="4.18.1" />
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="Autofac" Version="8.1.1" />
<PackageReference Include="FluentAssertions" Version="7.0.0" />
<PackageReference Include="LineCounter" Version="1.1.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageReference Include="NUnit" Version="4.1.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
<PackageReference Include="coverlet.collector" Version="6.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="NUnit" Version="4.3.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
<PackageReference Include="ReassureTest" Version="0.8.0" />
</ItemGroup>

Expand Down
1 change: 1 addition & 0 deletions src/Demos/MicroWorkflow.Tests/PerformanceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

namespace MicroWorkflow;

[Explicit("slow")]
public class PerformanceTests
{
[Test]
Expand Down
6 changes: 3 additions & 3 deletions src/Demos/WebApiDemo/MicroWorkflow.WebApiDemo.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Autofac" Version="8.0.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="9.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="Autofac" Version="8.1.1" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="10.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.8.1" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.1.5" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.2.2" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Autofac" Version="8.0.0" />
<PackageReference Include="Autofac" Version="8.1.1" />
<ProjectReference Include="..\MicroWorkflow\MicroWorkflow.csproj" />

</ItemGroup>
Expand Down
Loading
Loading