using System.Net.ServerSentEvents; using System.Text.Json.Serialization; using System.Threading.Channels; namespace s8n_runtime; public class WorkflowEditApiChannel : WorkflowRuntimeNodeBase, IWorkflowNodeRunnable { private WebApplication? _app; public static Channel? LogServerChannel; public ushort Port { get; set; } = 3080; public async Task OnStart(WorkflowRuntime runtime, CancellationToken cancellation) { var builder = WebApplication.CreateBuilder(); builder.WebHost.UseUrls($"http://localhost:{Port}"); builder.Services.AddOpenApi().ConfigureHttpJsonOptions(options => { var opts = options.SerializerOptions; opts.IncludeFields = true; opts.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; opts.Converters.Add(new JsonStringEnumConverter()); }).AddCors(); builder.Services.AddSingleton(LogServerChannel = Channel.CreateBounded(new BoundedChannelOptions(10000) { FullMode = BoundedChannelFullMode.DropOldest })); _app = builder.Build(); _app.MapOpenApi(); _app.UseCors(policy => policy.AllowAnyOrigin()); _app.MapGet("/api/runtime", () => runtime); _app.MapGet("/api/log", (Channel channel) => { return TypedResults.ServerSentEvents(GetEvents()); async IAsyncEnumerable> GetEvents() { if (channel == null) yield break; var reader = channel.Reader; while (await reader.WaitToReadAsync()) { if (reader.TryRead(out var message)) { yield return new SseItem(message); } } } }); await _app.StartAsync(cancellation); } public async Task OnStop() { if (_app != null) await _app.DisposeAsync(); } }