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