Elsa Core 之 SendSignal


流程设计器中定义

使用依赖注入

public class FireController : Controller
{
    private readonly ISignaler _signaler;

    public FireController(ISignaler signaler)
    {
        _signaler = signaler;
    }
        
    [HttpGet("start")]
    public async Task<IActionResult> StartFire(CancellationToken cancellationToken)
    {
        var startedWorkflows = await _signaler.TriggerSignalAsync("Fire", cancellationToken: cancellationToken);
        return Ok(startedWorkflows);
    }
        
    [HttpGet("{workflowInstanceId}/extinguish")]
    public async Task<IActionResult> Extinguish(string workflowInstanceId, CancellationToken cancellationToken)
    {
        var startedWorkflows = await _signaler.TriggerSignalAsync("Water", workflowInstanceId: workflowInstanceId, cancellationToken: cancellationToken);
        return Ok(startedWorkflows);
    }
}

ISignaler

注:注意参数 correlationId

public interface ISignaler
{
    /// <summary>
    /// Runs all workflows that start with or are blocked on the <see cref="SignalReceived"/> activity.
    /// </summary>
    Task<IEnumerable<CollectedWorkflow>> TriggerSignalTokenAsync(string signalToken, object? input = default, CancellationToken cancellationToken = default);
        
    /// <summary>
    /// Runs all workflows that start with or are blocked on the <see cref="SignalReceived"/> activity.
    /// </summary>
    Task<IEnumerable<CollectedWorkflow>> TriggerSignalAsync(string signal, object? input = null, string? workflowInstanceId = null, string? correlationId = null, CancellationToken cancellationToken = default);
        
    /// <summary>
    /// Dispatches all workflows that start with or are blocked on the <see cref="SignalReceived"/> activity.
    /// </summary>
    Task<IEnumerable<CollectedWorkflow>> DispatchSignalTokenAsync(string token, object? input = default, CancellationToken cancellationToken = default);
        
    /// <summary>
    /// Dispatches all workflows that start with or are blocked on the <see cref="SignalReceived"/> activity.
    /// </summary>
    Task<IEnumerable<CollectedWorkflow>> DispatchSignalAsync(string signal, object? input = default, string? workflowInstanceId = default, string? correlationId = default, CancellationToken cancellationToken = default);
}

通过调用http触发

代码实现过程

1、创建token

public static string GenerateSignalUrl(this ActivityExecutionContext context, string signal)
{
    var token = context.GenerateSignalToken(signal);
    var url = $"/signals/trigger/{token}";
    var absoluteUrlProvider = context.GetService<IAbsoluteUrlProvider>();
    return absoluteUrlProvider.ToAbsoluteUrl(url).ToString();
}

2、接收触发

[ApiController]
[Route("signals/trigger/{token}")]
[Produces("application/json")]
public class TriggerEndpoint : ControllerBase
{
    private readonly ISignaler _signaler;
    private readonly ITokenService _tokenService;
    private readonly IMediator _mediator;

    public TriggerEndpoint(ISignaler signaler, ITokenService tokenService, IMediator mediator)
    {
        _signaler = signaler;
        _tokenService = tokenService;
        _mediator = mediator;
    }

    [HttpGet, HttpPost]
    public async Task<IActionResult> Handle(string token, CancellationToken cancellationToken)
    {
        if (!_tokenService.TryDecryptToken(token, out SignalModel signal))
            return BadRequest();

        var affectedWorkflows = await _signaler.TriggerSignalAsync(signal.Name, null, signal.WorkflowInstanceId, cancellationToken: cancellationToken).ToList();

        await _mediator.Publish(new HttpTriggeredSignal(signal, affectedWorkflows), cancellationToken);

        var response = HttpContext.Response;

        return response.HasStarted || response.StatusCode != (int) HttpStatusCode.OK
            ? new EmptyResult()
            : Ok(affectedWorkflows);
    }
}

触发过程

Url形如

https://localhost:5001/signals/trigger/CfDJ8N8Lsy4pruVEidtlAk3o7Q8ldA99wFAiqleV276DAD7X0sKGxxsBtKpIK6QUwOHx9d-Rz8T3xJwAd-VAx7vlzLszj-hZb2VVsFOjUrrd73yNiRo4509LFMf0LaReXev3VWM9qoiKrXfcncwMkPaJUAu0qyYiPSGC1YaLF0N16YvG3EFYxiIuO2nH38oVNhxgLsw27s5S1Xg3q-1zU3K67Hw

上面的链接

使用设计器

可以参考如下代码

Document from {{ Variables.Document.Author.Name }} received for review.<br><a href="{{ "Approve" | signal_url }}">Approve</a> or <a href="{{ "Reject" | signal_url }}">Reject</a>

上面的signal_url 是一个filter,通过该filter看可以生成上面的Url

关键字: elsa