71 lines
2.1 KiB
C#
71 lines
2.1 KiB
C#
|
|
using Microsoft.EntityFrameworkCore;
|
||
|
|
using w4c_workflows.Data;
|
||
|
|
using w4c_workflows.Models;
|
||
|
|
|
||
|
|
namespace w4c_workflows.Services.Runs;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// Persists <c>durable</c>/<c>handler</c> checkpoint state. The checkpoint
|
||
|
|
/// records the instance's position (<c>TaskId</c> = the next task to run) and
|
||
|
|
/// the input to feed it (<c>StateJson</c>), enabling resume after an external
|
||
|
|
/// event. The instance id is a run id for <c>durable</c> workflows and a stable
|
||
|
|
/// per-workflow id for <c>handler</c> workflows.
|
||
|
|
/// </summary>
|
||
|
|
public class DurableStateStore
|
||
|
|
{
|
||
|
|
private readonly WorkflowsDbContext _db;
|
||
|
|
|
||
|
|
public DurableStateStore(WorkflowsDbContext db)
|
||
|
|
{
|
||
|
|
_db = db;
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task CheckpointAsync(
|
||
|
|
string instanceId,
|
||
|
|
Guid taskId,
|
||
|
|
string? stateJson,
|
||
|
|
string? correlationId,
|
||
|
|
CancellationToken ct)
|
||
|
|
{
|
||
|
|
var existing = await _db.DurableStates
|
||
|
|
.FirstOrDefaultAsync(d => d.InstanceId == instanceId, ct);
|
||
|
|
|
||
|
|
var now = DateTime.UtcNow;
|
||
|
|
if (existing == null)
|
||
|
|
{
|
||
|
|
_db.DurableStates.Add(new DurableState
|
||
|
|
{
|
||
|
|
InstanceId = instanceId,
|
||
|
|
TaskId = taskId,
|
||
|
|
StateJson = stateJson,
|
||
|
|
CheckpointAt = now,
|
||
|
|
CorrelationId = correlationId,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
existing.TaskId = taskId;
|
||
|
|
existing.StateJson = stateJson;
|
||
|
|
existing.CheckpointAt = now;
|
||
|
|
if (!string.IsNullOrWhiteSpace(correlationId))
|
||
|
|
existing.CorrelationId = correlationId;
|
||
|
|
}
|
||
|
|
|
||
|
|
await _db.SaveChangesAsync(ct);
|
||
|
|
}
|
||
|
|
|
||
|
|
public Task<DurableState?> GetAsync(string instanceId, CancellationToken ct)
|
||
|
|
=> _db.DurableStates.FirstOrDefaultAsync(d => d.InstanceId == instanceId, ct);
|
||
|
|
|
||
|
|
public async Task ClearAsync(string instanceId, CancellationToken ct)
|
||
|
|
{
|
||
|
|
var existing = await _db.DurableStates
|
||
|
|
.FirstOrDefaultAsync(d => d.InstanceId == instanceId, ct);
|
||
|
|
if (existing == null)
|
||
|
|
return;
|
||
|
|
|
||
|
|
_db.DurableStates.Remove(existing);
|
||
|
|
await _db.SaveChangesAsync(ct);
|
||
|
|
}
|
||
|
|
}
|