-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Closed
Labels
api-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implementedarea-System.Netin-prThere is an active PR which will close this issue when it is mergedThere is an active PR which will close this issue when it is merged
Milestone
Description
Background and motivation
The System.Net.ServerSentEvents library added support for parsing SSE events. We should also add support for formatting SSE events on the server side, in a way that unlocks work for dotnet/aspnetcore#56172.
API Proposal
namespace System.Net.ServerSentEvents;
// Extends the existing type to support writing
public readonly struct SseItem<T>
{
- public SseItem(T data, string eventType);
+ public SseItem(T data, string? eventType);
public T Data { get; }
- public string EventType { get; }
+ public string? EventType { get; }
+ public string? EventId { get; init; }
}
public delegate T SseItemParser<out T>(string eventType, ReadOnlySpan<byte> data);
+public delegate byte[] SseItemFormatter<T>(T value);
+public sealed class SseFormatter
+{
+ public static SseFormatter Create<T>(IAsyncEnumerable<SseItem<string>> source);
+ public static SseFormatter Create<T>(IAsyncEnumerable<SseItem<T>> source, SseItemFormatter<T> itemFormatter);
+
+ public Task WriteToStreamAsync(Stream stream, CancellationToken cancellationToken = default);
+ public void WriteToStream(Stream stream, CancellationToken cancellationToken = default);
+}API Usage
IAsyncEnumerable<SseItem<int>> source = ...;
SseFormatter formatter = SseFormatter.Create<int>(source, value => JsonSerializer.SerializeToBytes(value));
await formatter.WriteToStreamAsync(targetStream, cancellationToken);Alternative Designs
The current SseItemFormatter delegate uses an allocating design, but which is simpler to use. Alternative designs would involve writing either to a Stream:
public delegate ValueTask SseItemFormatter<T>(Stream stream, T value);But this would require wrapping the underlying stream in order to intercept potential line breaks. Alternatively, we could use an IBufferWriter<byte> which also composes better with PipeWriter targets:
public delegate void SseItemFormatter<T>(IBufferWriter<byte> writer, T value);The downside of either approach is that it becomes harder to define formatters from the user's perspective:
SseFormatter formatter = SseFormatter.Create<int>(source, (bufferWriter, value) =>
{
var writer = new Utf8JsonWriter(bufferWriter);
return JsonSerializer.SerializeToBytes(bufferWriter, value);
});Risks
No response
Metadata
Metadata
Assignees
Labels
api-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implementedarea-System.Netin-prThere is an active PR which will close this issue when it is mergedThere is an active PR which will close this issue when it is merged