Few more tweaks to the workflow engine

This commit is contained in:
Colin Dawson 2026-02-03 11:00:09 +00:00
parent e062d15101
commit b9876b1d7b
8 changed files with 86 additions and 87 deletions

View File

@ -6,12 +6,13 @@ namespace e_suite.Workflow.Core.Extensions;
public static class StageExtensions public static class StageExtensions
{ {
public static bool CanComplete<T>(this IStage<T> stage) //Todo can only be on a run-time instance
where T : TaskTypeAttribute //public static bool CanComplete<T>(this IStage<T> stage)
{ // where T : TaskTypeAttribute
return stage.Tasks.All(x => //{
x.IsCompleted()); // return stage.Tasks.All(x =>
} // x.IsCompleted());
//}
private static readonly ConcurrentDictionary<Type, IEnumerable<Type>> AllowedTasksCache = new(); private static readonly ConcurrentDictionary<Type, IEnumerable<Type>> AllowedTasksCache = new();

View File

@ -101,21 +101,22 @@ public static class TaskExtensions
} }
public static bool IsCompleted(this ITask task) //Todo can only be on a run-time instance
{ //public static bool IsCompleted(this ITask task)
return task.TaskState.In(TaskState.Completed, TaskState.Cancelled); //{
} // return task.TaskState.In(TaskState.Completed, TaskState.Cancelled);
//}
public static bool ReadyToActivate(this ITask task) //public static bool ReadyToActivate(this ITask task)
{ //{
foreach (var predecessor in task.Predecessors) // foreach (var predecessor in task.Predecessors)
{ // {
if (!predecessor.IsCompleted()) // if (!predecessor.IsCompleted())
{ // {
return false; // return false;
} // }
} // }
return true; // return true;
} //}
} }

View File

@ -14,13 +14,6 @@ public interface ITask
/// </summary> /// </summary>
ITask Parent { get; } ITask Parent { get; }
//Todo move this out to runtime only.
/// <summary>
/// Current state of the Task.
/// </summary>
TaskState TaskState { get; set; }
/// <summary> /// <summary>
/// Name of the task as seen by users, must be unique in the workflow. /// Name of the task as seen by users, must be unique in the workflow.
/// </summary> /// </summary>
@ -68,20 +61,21 @@ public interface ITask
public IList<string> Tags { get; set; } public IList<string> Tags { get; set; }
/// <summary> //Todo can only be on a run-time instance
/// Called when the task status has been progressed from Pending to Active. ///// <summary>
/// ///// Called when the task status has been progressed from Pending to Active.
/// Note: You can use this method to set the TaskStatus to ReadyToComplete if there is no manual processing needed for this task. /////
/// After this method is completed, the TaskStatus must be either Active or ReadyToComplete. ///// Note: You can use this method to set the TaskStatus to ReadyToComplete if there is no manual processing needed for this task.
/// </summary> ///// After this method is completed, the TaskStatus must be either Active or ReadyToComplete.
/// <returns></returns> ///// </summary>
Task OnActivateAsync(); ///// <returns></returns>
//Task OnActivateAsync();
/// <summary> ///// <summary>
/// Called when the task status has been progressed from ReadyToComplete to Completed ///// Called when the task status has been progressed from ReadyToComplete to Completed
/// </summary> ///// </summary>
/// <returns>True when the task completes successfully, false when it is considered failed.</returns> ///// <returns>True when the task completes successfully, false when it is considered failed.</returns>
Task<bool> OnCompleteAsync(); //Task<bool> OnCompleteAsync();
//Todo add support for events (soap, rest, sftp, e-mail) //Todo add support for events (soap, rest, sftp, e-mail)
} }

View File

@ -25,25 +25,25 @@ public interface IWorkflow : IStage<GeneralTaskAttribute>
/// </summary> /// </summary>
string Description { get; set; } string Description { get; set; }
//todo Move this out to runtime only. //Todo can only be on a run-time instance
/// <summary> ///// <summary>
/// If the workflow has been paused, will be true. ///// If the workflow has been paused, will be true.
/// </summary> ///// </summary>
bool Paused { get; } //bool Paused { get; }
///// <summary>
///// Called when the task status has been progressed from Pending to Active.
/////
///// Note: You can use this method to set the TaskStatus to ReadyToComplete if there is no manual processing needed for this task.
///// After this method is completed, the TaskStatus must be either Active or ReadyToComplete.
///// </summary>
///// <returns></returns>
//Task OnActivateAsync();
/// <summary> ///// <summary>
/// Called when the task status has been progressed from Pending to Active. ///// Called when the task status has been progressed from ReadyToComplete to Completed
/// ///// When this method is completed the state must be either Active, or Completed.
/// Note: You can use this method to set the TaskStatus to ReadyToComplete if there is no manual processing needed for this task. ///// </summary>
/// After this method is completed, the TaskStatus must be either Active or ReadyToComplete. ///// <returns></returns>
/// </summary> //Task OnCompleteAsync();
/// <returns></returns>
Task OnActivateAsync();
/// <summary>
/// Called when the task status has been progressed from ReadyToComplete to Completed
/// When this method is completed the state must be either Active, or Completed.
/// </summary>
/// <returns></returns>
Task OnCompleteAsync();
} }

View File

@ -7,7 +7,6 @@ public abstract class TaskBase : ITask
{ {
public Guid Guid { get; set; } = Guid.CreateVersion7(); public Guid Guid { get; set; } = Guid.CreateVersion7();
public required ITask Parent { get; set; } public required ITask Parent { get; set; }
public TaskState TaskState { get; set; } = TaskState.Pending;
public required string Name { get; set; } public required string Name { get; set; }
public string Description { get; set; } = string.Empty; public string Description { get; set; } = string.Empty;
public IList<ITask> Predecessors { get; set; } = new List<ITask>(); public IList<ITask> Predecessors { get; set; } = new List<ITask>();
@ -19,13 +18,14 @@ public abstract class TaskBase : ITask
public required TimeSpan Duration { get; set; } public required TimeSpan Duration { get; set; }
public IList<string> Tags { get; set; } = new List<string>(); public IList<string> Tags { get; set; } = new List<string>();
public virtual Task OnActivateAsync() //Todo can only be on a run-time instance
{ //public virtual Task OnActivateAsync()
return Task.CompletedTask; //{
} // return Task.CompletedTask;
//}
public virtual Task<bool> OnCompleteAsync() //public virtual Task<bool> OnCompleteAsync()
{ //{
return Task.FromResult(true); // return Task.FromResult(true);
} //}
} }

View File

@ -10,9 +10,10 @@ public class ApprovalTask : TaskBase, IStage<ApprovalTaskAttribute>, IFailedLoop
public ICollection<ITask> Tasks { get; } = new List<ITask>(); public ICollection<ITask> Tasks { get; } = new List<ITask>();
public override Task<bool> OnCompleteAsync() //Todo can only be on a run-time instance
{ //public override Task<bool> OnCompleteAsync()
//{
return Task.FromResult(true); // return Task.FromResult(true);
} //}
} }

View File

@ -1,5 +1,4 @@
using e_suite.Workflow.Core.Attributes; using e_suite.Workflow.Core.Attributes;
using e_suite.Workflow.Core.Enums;
namespace e_suite.Workflow.Core.Tasks; namespace e_suite.Workflow.Core.Tasks;
@ -9,9 +8,10 @@ namespace e_suite.Workflow.Core.Tasks;
[GeneralTask] [GeneralTask]
public class MilestoneTask : TaskBase public class MilestoneTask : TaskBase
{ {
public override async Task OnActivateAsync() //Todo can only be on a run-time instance
{ //public override async Task OnActivateAsync()
await base.OnActivateAsync(); //{
TaskState = TaskState.ReadyToComplete; // await base.OnActivateAsync();
} // TaskState = TaskState.ReadyToComplete;
//}
} }

View File

@ -21,12 +21,14 @@ public class WorkflowVersion : IWorkflow
public WorkflowState CurrentState { get; set; } = WorkflowState.Pending; public WorkflowState CurrentState { get; set; } = WorkflowState.Pending;
public required string ActivityNameTemplate { get; set; } public required string ActivityNameTemplate { get; set; }
public string Description { get; set; } = string.Empty; public string Description { get; set; } = string.Empty;
public bool Paused { get; } = false;
public async Task OnActivateAsync()
{
}
public async Task OnCompleteAsync() //Todo can only be on a run-time instance
{ //public bool Paused { get; } = false;
} //public async Task OnActivateAsync()
//{
//}
//public async Task OnCompleteAsync()
//{
//}
} }