# Workflow Service Engine

## NuGet Package Details

Package Name

[Llamachant.ExpressApp.Workflow.Service](https://www.nuget.org/packages/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
