-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[API Proposal]: Add formatting support to System.Net.ServerSentEvents
#109294
Comments
This will introduce warnings into folks' code. Why is it necessary? |
Seems like this design forces a |
I noticed that our
It seems like according to the spec, the event type is actually optional. We may introduce new warnings here but it strikes me as valid given the it's possible for the underlying value to be null. We're a lot more permissive about making non-nullable properties nullable in ASP.NET Core reviews so I tend to be more relax about introducing new warnings if they actually make sense. 😅 |
I initially experimented with a signature matching that of
We need a way to intercept line breaks. Maybe it's possible to do so by wrapping the underlying stream but I haven't tested this out. Worth a try you think? public delegate ValueTask SseItemFormatter<T>(Stream stream, T value); But not sure how well this would compose with a hypothetical future API that targets public delegate void SseItemFormatter<T>(IBufferWriter<byte> writer, T value); |
cc: @dotnet/ncl since the bot was lazy |
It is optional, and when it's not supplied, implementations are supposed to infer "message". So we exposed SseParser.EventTypeDefault, so that if it's not there in the wire data, the .NET representation of it can provide it explicitly. If we want to make the ctor parameter optional and have the constructor supply "message" when the event type is null, I'm fine with that. But making the property be nullable doesn't seem warranted; it's just introducing friction. What's the case where someone is going to behave differently based on whether EventType returns null or returns "message"? Presumably we actually make it harder for consumers with this being nullable, as someone wanting to handle the default case needs to check for both null and "message". |
The downside of keeping it non-nullable is that we'd mandating event types to be written on the formatter side. Unless of course we use a separate type to model written events or decide that |
Why? If it returns "message", the formatter can choose to elide it. That's true whether or not the property can also return null. |
So we make "message" a magic string? |
The spec makes it a magic string. |
namespace System.Net.ServerSentEvents;
public readonly struct SseItem<T>
{
- public SseItem(T data, string eventType);
+ public SseItem(T data, string? eventType); namespace System.Net.ServerSentEvents;
// Extends the existing type to support writing
public readonly partial struct SseItem<T>
{
public string? EventId { get; init; }
}
public static class SseFormatter
{
public static Task WriteAsync(IAsyncEnumerable<SseItem<string>> source, Stream destination, CancellationToken cancellationToken = default);
public static Task WriteAsync(IAsyncEnumerable<SseItem<T>> source, Stream destination, Action<T, IBufferWriter<byte>> itemFormatter, CancellationToken cancellationToken = default);
} |
I want to propose the following amendments to the API as approved above:
Thus, the amended design looks as follows: namespace System.Net.ServerSentEvents;
// Extends the existing type to support writing
public readonly partial struct SseItem<T>
{
public string? EventId { get; init; }
+ public TimeSpan? ReconnectionInterval { get; init; }
}
public static class SseFormatter
{
public static Task WriteAsync(IAsyncEnumerable<SseItem<string>> source, Stream destination, CancellationToken cancellationToken = default);
- public static Task WriteAsync(IAsyncEnumerable<SseItem<T>> source, Stream destination, Action<T, IBufferWriter<byte>> itemFormatter, CancellationToken cancellationToken = default);
+ public static Task WriteAsync(IAsyncEnumerable<SseItem<T>> source, Stream destination, Action<SseItem<T>, IBufferWriter<byte>> itemFormatter, CancellationToken cancellationToken = default);
} |
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
API Usage
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
: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 withPipeWriter
targets:The downside of either approach is that it becomes harder to define formatters from the user's perspective:
Risks
No response
The text was updated successfully, but these errors were encountered: