feat(engine): WebhookRegistry — (workflowId, path) → invocation lookup

This commit is contained in:
Claude
2026-08-28 14:58:06 +00:00
parent eabd6f175d
commit c88d27294b
2 changed files with 37 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
using System.Collections.Concurrent;
using System.Text.Json;
namespace VolcanicCore.Api.Engine;
public delegate Task WebhookInvocation(JsonElement body, Guid answerChannelId, CancellationToken ct);
public sealed class WebhookRegistry
{
private sealed record Key(string WorkflowId, string Path);
private readonly ConcurrentDictionary<Key, WebhookInvocation> _routes = new();
// Returns an IDisposable that removes the registration when disposed —
// that's what WebhookNode.StartAsync will hand back to TriggerHost.
public IDisposable Register(string workflowId, string path, WebhookInvocation invoke)
{
var key = new Key(workflowId, Normalize(path));
if (!_routes.TryAdd(key, invoke))
throw new InvalidOperationException(
$"Webhook path '{path}' is already registered for workflow {workflowId}.");
return new Unregister(this, key);
}
public WebhookInvocation? Lookup(string workflowId, string path)
=> _routes.TryGetValue(new Key(workflowId, Normalize(path)), out var cb) ? cb : null;
private static string Normalize(string path) => path.Trim('/');
private sealed class Unregister : IDisposable
{
private readonly WebhookRegistry _owner;
private readonly Key _key;
public Unregister(WebhookRegistry o, Key k) { _owner = o; _key = k; }
public void Dispose() => _owner._routes.TryRemove(_key, out _);
}
}

View File

@@ -118,6 +118,7 @@ builder.Services.AddSingleton<IConnectionInstanceRegistry>(sp =>
sp.GetRequiredService<ConnectionInstanceRegistry>());
builder.Services.AddSingleton<WebhookRouter>();
builder.Services.AddSingleton<WebhookRegistry>();
var app = builder.Build();