dotnet recommends LightWorkFlowManager, a lightweight work process management library
This article will recommend my team’s open source LightWorkFlowManager lightweight work process management library, which is suitable for any application logic that needs to execute work processes. It can easily piece together multiple work processes, and automatically integrates retry and failure processing, as well as logs and Reporting function
This article will recommend my team’s open source LightWorkFlowManager lightweight work process management library, which is suitable for any application logic that needs to execute work processes. It can easily piece together multiple work processes, and automatically integrates retry and failure handling. As well as logging and reporting functions
This LightWorkFlowManager lightweight work process management library is an open source library that my team uses the most friendly MIT license on GitHub. Please see https://github.com/dotnet-campus/LightWorkFlowManager
This LightWorkFlowManager lightweight work process management library has been running on my team’s official product application for half a year now, and it is relatively stable. If you have any questions during use, you are welcome to create new Issues on GitHub for feedback
There are many existing work process management systems in the world, so why reinvent one? No reason, I made it myself and it works fine. This LightWorkFlowManager library lacks many functions compared with other work process management libraries, but it is better than being lightweight. And the most important selling point of LightWorkFlowManager is that it is friendly to debugging. It is suitable for use in logical situations with relatively good complexity, and can effectively reduce the additional complexity caused by introducing the work process management module itself
Many existing full-featured work process management libraries are used on ASP.NET Core. However, my requirement here is to use it on the client application framework, and in most cases it runs on the user’s device. Many service dependencies themselves do not exist. Although many existing fully functional work process management libraries can be configured to run on a single machine, doing so is not the recommended use of the library most of the time and will not be as smooth to use. To this end, my team developed LightWorkFlowManager, a lightweight work process management library. This library can be easily run on client frameworks, such as WPF applications, WinForms applications, and MAUI applications. At the same time, LightWorkFlowManager also takes into account the ASP.NET Core service itself, especially the dependency injection part, which can be connected to the default service dependency injection
I will give you an example to show you where this LightWorkFlowManager library is applicable. Suppose I get a development task, which is to parse PPT and take out the pictures in the PPT file. Breaking down this task will include the following three steps: Step 1, obtain the PPT file. Step 2: Call an existing helper method to obtain the image in the PPT file. Step 3: Process the image files in the obtained PPT file
In step one, there are multiple ways to obtain PPT files. For example, some are downloaded from online CDN servers, some are obtained from disk paths, and some are dragged in by users. These different input acquisition methods come from different entrances of each business
In step three, according to different business situations, it is necessary to upload the image files to the backend server, or some businesses need to display these images on the interface, etc.
As you can see from the above description, what I got is a requirement that can be scattered in various businesses. It seems that there are many different but logically similar requirements. Logical similarity means that steps can be forcibly classified for constraints. Logical duplication lies in the fact that many logics are completely reusable, such as logging and retry mechanisms. The retry mechanism can be used in almost all the above three steps. Whether you are a novice developer or an experienced developer, you know that whether you are downloading content from the Internet or uploading files, you need to go through unstable network transmission. At this time, the network transmission fails. Executing retry logic is a very common processing logic
Assuming that there is no assistance from the LightWorkFlowManager library, a possible implementation design is as follows: design a unified entrance, and pass in parameters through the entrance to determine and execute different step processing logic, as shown below
You can easily see the problem from the above picture. The entire logic complexity will be relatively high. There are multiple original business entrances. Then you enter the unified entrance in the PPT parsing task. In the PPT parsing task, The unified entrance then distributes logic to different processing logic based on parameters. The cyclomatic complexity of the entire logic will be relatively high. At the same time, if more business requirements are added in step one or step three, the entire logic will become more complicated. On the other hand, such complex logic will make it difficult to read and debug the code. For example, it is difficult to know the entire call chain very clearly. The call chain may be too complicated, such as it is difficult to perform repeated executions during debugging.
There is LightWorkFlowMaRequired Foo2Type parameters
await Manager
.SetContext((Foo1Type foo1) => ConvertFoo1ToFoo2(foo1))
.RunWorker();
Exception and retry
Each Worker can return a return value of type WorkerResult, which can tell the framework layer whether the current Worker is executed successfully. When execution fails, an error code can be assigned to facilitate positioning, debugging or output. When the execution fails, you can return to inform the framework layer whether it needs to retry. By default, the framework will automatically retry
There are two ways to interrupt subsequent worker execution:
Method 1: By returning a WorkerResult with a failed status. Once the status of the work manager is IsFail, all workers that do not mark CanRunWhenFail as true will be blocked from executing. In other words, except for the Worker workers that need to be executed continuously in a successful or failed state, other workers will not be executed, including the delegation transformation in SetContext.
Method 2: By throwing an exception, the subsequent logic can be blown up and no longer executed through the exception in dotnet
The above two methods are recommended by the framework. The framework design preference is to use method 1 to interrupt execution if performance is important. If there is complex business logic and a large amount of business logic is interspersed outside the work process, you can easily interrupt it through method 2
Execute other Worker workers in Worker
In a Worker, other Workers can be executed, so that branch logic can be implemented more freely, and the matryoshka decides to execute the worker
Examples are as follows:
Assume there is a Worker2 worker defined as follows:
class Worker2 : MessageWorker
{
protected override ValueTask<WorkerResult> DoInnerAsync(InputType input)
{
return SuccessTask(new OutputType());
}
}
recordInputType();
recordOutputType();
There is another Worker1 worker, and the Worker2 worker can be executed inside Worker1:
class Worker1 : MessageWorkerBase
{
public override async ValueTask Do(IWorkerContext context)
{
await Manager
.GetWorker()
.RunAsync(new InputType());
return WorkerResult.Success();
}
}
Delegation Worker
I have some very small and light logic that I want to add to the work process, but I don’t want to define a separate worker for this. You can try a delegate worker, such as the following code example
var delegateMessageWorker = new DelegateMessageWorker(_ =>
{
//Write the business content of the delegate worker here
});
var result = await messageWorkerManager.RunWorker(delegateMessageWorker);
If you don’t even want to create a DelegateMessageWorker, you can also directly use the RunWorker method of MessageWorkerManager to pass in the delegate, such as the following code example
await messageWorkerManager.RunWorker((IWorkerContext context) =>
{
//Write the business content of the delegate worker here
});
The Blog Park blog only makes backups and will no longer be updated when the blog is published. If you want to see the latest blog, please go to https://blog.lindexi.com/
This work Licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. You are welcome to reprint, use and republish, but be sure to retain the article signature [Lin Dexi] (https://www.cnblogs.com/lindexi) (including link: https://www.cnblogs.com/lindexi) and may not be used for commercial purposes For this purpose, modified works based on this article must be released under the same license. If you have any questions, please contact me [mailto:[email protected]].