WorkflowForge.Extensions.Persistence
2.1.2
See the version list below for details.
dotnet add package WorkflowForge.Extensions.Persistence --version 2.1.2
NuGet\Install-Package WorkflowForge.Extensions.Persistence -Version 2.1.2
<PackageReference Include="WorkflowForge.Extensions.Persistence" Version="2.1.2" />
<PackageVersion Include="WorkflowForge.Extensions.Persistence" Version="2.1.2" />
<PackageReference Include="WorkflowForge.Extensions.Persistence" />
paket add WorkflowForge.Extensions.Persistence --version 2.1.2
#r "nuget: WorkflowForge.Extensions.Persistence, 2.1.2"
#:package WorkflowForge.Extensions.Persistence@2.1.2
#addin nuget:?package=WorkflowForge.Extensions.Persistence&version=2.1.2
#tool nuget:?package=WorkflowForge.Extensions.Persistence&version=2.1.2
WorkflowForge.Extensions.Persistence
Save and resume workflows through IWorkflowPersistenceProvider: you choose SQL, Cosmos, Redis, files, or anything else. The package ships abstractions and middleware only, no built-in database driver.
Install
dotnet add package WorkflowForge.Extensions.Persistence
Targets .NET Standard 2.0 or later.
Quick Start
1. Implement the provider interface
using WorkflowForge.Extensions.Persistence.Abstractions;
public class SqlPersistenceProvider : IWorkflowPersistenceProvider
{
private readonly string _connectionString;
public SqlPersistenceProvider(string connectionString)
{
_connectionString = connectionString;
}
public async Task SaveAsync(
WorkflowExecutionSnapshot snapshot,
CancellationToken cancellationToken = default)
{
// Serialize and store the snapshot in your database
}
public async Task<WorkflowExecutionSnapshot?> TryLoadAsync(
Guid foundryExecutionId,
Guid workflowId,
CancellationToken cancellationToken = default)
{
// Load the snapshot from your database; return null if not found
}
public async Task DeleteAsync(
Guid foundryExecutionId,
Guid workflowId,
CancellationToken cancellationToken = default)
{
// Remove the snapshot from your database
}
}
2. Enable persistence on the foundry
using WorkflowForge;
using WorkflowForge.Extensions.Persistence;
IWorkflowPersistenceProvider provider = new SqlPersistenceProvider("Server=...");
var smith = WorkflowForge.CreateSmith();
var workflow = WorkflowForge.CreateWorkflow("MyWorkflow")
.AddOperation(/* your operations */)
.Build();
using var foundry = WorkflowForge.CreateFoundry("OrderService");
foundry.UsePersistence(provider);
await smith.ForgeAsync(workflow, foundry);
3. Enable with stable keys (for cross-process resume)
using WorkflowForge.Extensions.Persistence;
var options = new PersistenceOptions
{
InstanceId = "order-service-instance",
WorkflowKey = "process-order-v1"
};
foundry.UsePersistence(provider, options);
When InstanceId and WorkflowKey are set, deterministic GUIDs are derived from those strings so the same workflow can be found across process restarts.
Key points
- No default provider on purpose: stay storage-neutral (you implement
IWorkflowPersistenceProvider). Beyond core, depends only onMicrosoft.Extensions.*for options/DI. - Checkpoints after each successful operation; resume skips completed steps via
NextOperationIndex. - Optional stable keys tie executions to logical instances across restarts.
- Middleware is written to be safe under concurrent workflows.
How it works
The PersistenceMiddleware wraps each operation in the pipeline:
- Before each operation: Calls
TryLoadAsyncto check for a saved snapshot - If snapshot exists and operation already completed: Restores properties, skips the operation
- If not resumed: Calls the next middleware/operation normally
- After success: Builds a
WorkflowExecutionSnapshotwithNextOperationIndexincremented and callsSaveAsync - When all operations complete: Calls
DeleteAsyncto clean up
Snapshot structure
public sealed class WorkflowExecutionSnapshot
{
public Guid FoundryExecutionId { get; set; }
public Guid WorkflowId { get; set; }
public string WorkflowName { get; set; }
public int NextOperationIndex { get; set; }
public Dictionary<string, object?> Properties { get; set; }
}
NextOperationIndex: -1 means not started; N means operation at index N is nextProperties: Arbitrary key-value state fromfoundry.Properties; store only what you need for resumption
Configuration
Via appsettings.json
{
"WorkflowForge": {
"Extensions": {
"Persistence": {
"Enabled": true,
"PersistOnOperationComplete": true,
"PersistOnWorkflowComplete": true,
"PersistOnFailure": true,
"MaxVersions": 10,
"InstanceId": "my-instance-id",
"WorkflowKey": "my-workflow-key"
}
}
}
}
Via code
using WorkflowForge.Extensions.Persistence;
var options = new PersistenceOptions
{
Enabled = true,
PersistOnOperationComplete = true,
PersistOnWorkflowComplete = true,
PersistOnFailure = true,
MaxVersions = 10,
InstanceId = "my-instance-id",
WorkflowKey = "my-workflow-key"
};
foundry.UsePersistence(provider, options);
Via dependency injection
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using WorkflowForge.Extensions.Persistence;
services.AddPersistenceConfiguration(configuration);
var options = serviceProvider.GetRequiredService<IOptions<PersistenceOptions>>().Value;
Provider interface
public interface IWorkflowPersistenceProvider
{
Task SaveAsync(WorkflowExecutionSnapshot snapshot, CancellationToken cancellationToken = default);
Task<WorkflowExecutionSnapshot?> TryLoadAsync(Guid foundryExecutionId, Guid workflowId,
CancellationToken cancellationToken = default);
Task DeleteAsync(Guid foundryExecutionId, Guid workflowId,
CancellationToken cancellationToken = default);
}
Links
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.Extensions.Configuration.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Configuration.Binder (>= 10.0.10)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 10.0.10)
- Microsoft.Extensions.Options (>= 10.0.10)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.10)
- WorkflowForge (>= 2.1.2)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on WorkflowForge.Extensions.Persistence:
| Package | Downloads |
|---|---|
|
WorkflowForge.Extensions.Persistence.Recovery
Recovery orchestration for WorkflowForge persistence: resume workflows from last checkpoints, with configurable retry and hooks. |
GitHub repositories
This package is not used by any popular GitHub repositories.
v2.1.2: Fixed ILRepacked extensions (Polly, OpenTelemetry, Serilog) that were missing transitive dependencies and threw a runtime FileNotFoundException (e.g. Microsoft.Bcl.TimeProvider) — the required BCL/Microsoft.Extensions packages now flow to consumers. Implemented foundry performance monitoring so EnablePerformanceMonitoring()/GetPerformanceStatistics() work end-to-end. Fixed pooled-foundry state leaking across executions and audit entries recording "Unknown" workflow names. Centralized package versioning and shared metadata. Hardened lifecycle-event exception isolation and smith disposal.