feat(workflow): 添加更新流程实例变量功能

- 新增 UpdateWorkflowInstanceVariablesCommand 命令处理变量更新逻辑
- 实现 UpdateWorkflowInstanceVariablesCommandHandler 验证并保存变量到数据库
- 添加 UpdateWorkflowInstanceVariablesEndpoint 提供 REST API 接口
- 创建 UpdateWorkflowInstanceVariablesRequest 定义请求数据结构
- 实现 JSON 格式验证确保变量数据有效性
- 支持人工干预修正流程运行时数据的场景需求
This commit is contained in:
xiangning 2026-07-03 17:27:11 +08:00
parent 1e0844800e
commit a4a575cc4f
4 changed files with 94 additions and 0 deletions

View File

@ -0,0 +1,30 @@
using MediatR;
using Workflow.Application.Features.WorkflowInstances.Commands;
namespace BuildFlow.Host.Endpoints.Workflow.WorkflowInstance;
/// <summary>
/// 更新单个流程实例的运行时变量。用于人工干预修正流程数据(仅改 Variables,不动状态/定义版本)。
/// </summary>
public class UpdateWorkflowInstanceVariablesEndpoint(IMediator mediator)
: Endpoint<UpdateWorkflowInstanceVariablesRequest>
{
public override void Configure()
{
Put("/workflow-instances/{Id}/variables");
Permissions("workflow-instance:manage");
Summary(s =>
{
s.Summary = "Update variables of a single workflow instance";
});
}
public override async Task HandleAsync(UpdateWorkflowInstanceVariablesRequest req, CancellationToken ct)
{
var id = Route<Guid>("Id");
await mediator.Send(new UpdateWorkflowInstanceVariablesCommand(id, req.Variables), ct);
HttpContext.Response.StatusCode = 200;
HttpContext.Response.ContentType = "application/json";
await HttpContext.Response.WriteAsync("{}", ct);
}
}

View File

@ -0,0 +1,10 @@
namespace BuildFlow.Host.Endpoints.Workflow.WorkflowInstance;
/// <summary>
/// 更新流程实例变量请求体。
/// </summary>
public class UpdateWorkflowInstanceVariablesRequest
{
/// <summary>新的流程变量 JSON(必须是 JSON 对象,如 {"amount": 5000, "level": 3})。</summary>
public string Variables { get; set; } = string.Empty;
}

View File

@ -0,0 +1,11 @@
using MediatR;
namespace Workflow.Application.Features.WorkflowInstances.Commands;
/// <summary>
/// 更新单个流程实例的运行时变量(Variables)命令。
/// 用于人工干预修正流程数据(如表单填错、条件分支走错),仅改 Variables,不动状态、定义版本、token。
/// </summary>
public record UpdateWorkflowInstanceVariablesCommand(
Guid InstanceId,
string Variables) : IRequest<Unit>;

View File

@ -0,0 +1,43 @@
using System.Text.Json;
using MediatR;
using Workflow.Application.Features.WorkflowInstances.Commands;
using Workflow.Infrastructure.Persistence;
namespace Workflow.Application.Features.WorkflowInstances.Handlers;
/// <summary>
/// 更新流程实例变量处理器。校验实例存在且 Variables 为合法 JSON 对象后覆盖写入。
/// 不校验实例状态:Running/Suspended/Completed 均允许修正变量(人工干预场景)。
/// </summary>
public class UpdateWorkflowInstanceVariablesCommandHandler(WorkflowDbContext db)
: IRequestHandler<UpdateWorkflowInstanceVariablesCommand, Unit>
{
public async Task<Unit> Handle(UpdateWorkflowInstanceVariablesCommand request, CancellationToken ct)
{
var instance = await db.WorkflowInstances.FindAsync([request.InstanceId], ct)
?? throw new NotFoundException($"Workflow instance '{request.InstanceId}' not found.");
// 校验 Variables 是合法 JSON 对象,避免脏数据破坏引擎条件求值(ParseVariables 会吞异常返回空,
// 但这里前置校验能给出明确错误而非静默丢失变量)
ValidateVariablesJson(request.Variables);
instance.Variables = request.Variables;
await db.SaveChangesAsync(ct);
return Unit.Value;
}
private static void ValidateVariablesJson(string variables)
{
try
{
using var doc = JsonDocument.Parse(variables);
if (doc.RootElement.ValueKind != JsonValueKind.Object)
throw new BusinessException("流程变量必须是 JSON 对象(如 {\"key\":\"value\"})。");
}
catch (JsonException ex)
{
throw new BusinessException($"流程变量不是合法的 JSON:{ex.Message}");
}
}
}