Workflow Service Engine
NuGet Package Details
Package Name
Llamachant.ExpressApp.Workflow.Service
Overview
The Llamachant Framework Workflow Service module provides a standalone engine for processing workflow definitions created by the Llamachant Framework Workflow module. It enables decoupled, scalable, and scheduled execution of workflows, ideal for background processing scenarios.
This module can be hosted in a variety of runtime environments, including:
- Azure Functions (e.g., Timer-triggered execution for serverless scaling)
- Windows Services (for long-running, persistent processing)
- Console Applications (invoked manually or via Task Scheduler)
Installation
Step 1: Install the module
Install-Package 'LlamachantFramework.Workflow.Service'
Setup
Getting Started:
Once the module is installed, follow these steps:
- Create an instance of your XAF Application
- Initialize
WorkflowService.Instance - (Optional) Configure your custom Email Service
- Process the workflows
Sample Azure Function (Using XAF Blazor Application):
[FunctionName("RunWorkflowFunction")]
public void Run([TimerTrigger("0 * * * * *")] TimerInfo myTimer, ILogger log, ExecutionContext context)
{
DevExpress.Utils.AzureCompatibility.Enable = true;
try
{
log.LogInformation("*** Function is starting ***");
if (app == null)
{
config = new ConfigurationBuilder()
.SetBasePath(context.FunctionAppDirectory)
#if DEBUG
.AddJsonFile("local.settings.json", optional: true)
#endif
.AddEnvironmentVariables()
.Build();
IHostBuilder hostBuilder = Program.CreateHostBuilder(new string[0]);
app = (MyBlazorApplication)DesignTimeApplicationFactoryHelper.Create(hostBuilder);
app.ConnectionString = config.GetConnectionString("ConnectionString");
app.Setup();
log.LogInformation("Application created and setup complete.");
}
WorkflowService.Instance.TimeZone = TimeZoneInfo.FindSystemTimeZoneById(config.GetValue<string>("WorkflowTimezone"));
if (!app.GetSecurityStrategy().IsAuthenticated)
{
var p = new AuthenticationStandardLogonParameters {
UserName = config.GetValue<string>("WorkflowUserName"),
Password = config.GetValue<string>("WorkflowPassword")
};
app.GetSecurityStrategy().Logon(p);
}
if (app.GetSecurityStrategy().IsAuthenticated)
{
WorkflowService.Instance.Initialize(app, log);
WorkflowService.Instance.RunWorkflow();
}
log.LogInformation("*** Function is ending ***");
}
catch (Exception ex)
{
log.LogError(ex, "******** Service Crash ********");
}
}
Sample Windows Service
public partial class MyWorkflowService : ServiceBase
{
WorkflowQueueController queue = new WorkflowQueueController();
public MyWorkflowService() => InitializeComponent();
protected override void OnStart(string[] args)
{
queue.SetInterval(60);
queue.Start();
}
protected override void OnStop() => queue.Stop();
}
Sample Console Application
public class MyConsoleApp
{
public static void Main(string[] args)
{
var app = new MyWindowsFormsApplication();
app.ConnectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
app.Setup();
var p = new AuthenticationStandardLogonParameters { UserName = "Admin" };
app.GetSecurityStrategy().Logon(p);
WorkflowService.Instance.Initialize(app, new FileSystemLogger(@"C:\Logs\"));
WorkflowService.Instance.RunWorkflow();
}
}
Managing Workflow Definition Dates
WorkflowService.Instance.ProgressWorkflowDefinitionDate += (s, args) =>
{
while (e.NextRunDate.DayOfWeek == DayOfWeek.Saturday || e.NextRunDate.DayOfWeek == DayOfWeek.Sunday)
e.NextRunDate = e.NextRunDate.AddDays(1);
};
Calculate if Workflow Processing Is Required
WorkflowService.Instance.CalculateNeedsProcessing += (s, args) =>
{
var c = e.ObjectToProcess as Client;
bool blankemail = c != null && string.IsNullOrEmpty(c.EmailAddress) && e.WorkflowDefinition.Name == "My workflow Definition";
e.Process = !blankemail;
};
Getting Started:
Once the module is installed, follow these steps:
- Create an instance of your XAF Application
- Initialize
WorkflowService.Instance - (Optional) Configure your custom Email Service
- Process the workflows